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 if (defined($descr)) {
1890 $conf->{description
} = $descr;
1893 $conf = $res->{$section} = {};
1896 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1898 if (defined($descr)) {
1900 $conf->{description
} = $descr;
1903 $conf = $res->{snapshots
}->{$section} = {};
1907 if ($line =~ m/^\#(.*)\s*$/) {
1908 $descr = '' if !defined($descr);
1909 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1913 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1914 $descr = '' if !defined($descr);
1915 $descr .= PVE
::Tools
::decode_text
($2);
1916 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1917 $conf->{snapstate
} = $1;
1918 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1921 $conf->{$key} = $value;
1922 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1924 if ($section eq 'pending') {
1925 $conf->{delete} = $value; # we parse this later
1927 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1929 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1932 eval { $value = check_type
($key, $value); };
1934 warn "vm $vmid - unable to parse value of '$key' - $@";
1936 my $fmt = $confdesc->{$key}->{format
};
1937 if ($fmt && $fmt eq 'pve-qm-drive') {
1938 my $v = parse_drive
($key, $value);
1939 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1940 $v->{file
} = $volid;
1941 $value = print_drive
($vmid, $v);
1943 warn "vm $vmid - unable to parse value of '$key'\n";
1948 if ($key eq 'cdrom') {
1949 $conf->{ide2
} = $value;
1951 $conf->{$key} = $value;
1957 if (defined($descr)) {
1959 $conf->{description
} = $descr;
1961 delete $res->{snapstate
}; # just to be sure
1966 sub write_vm_config
{
1967 my ($filename, $conf) = @_;
1969 delete $conf->{snapstate
}; # just to be sure
1971 if ($conf->{cdrom
}) {
1972 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1973 $conf->{ide2
} = $conf->{cdrom
};
1974 delete $conf->{cdrom
};
1977 # we do not use 'smp' any longer
1978 if ($conf->{sockets
}) {
1979 delete $conf->{smp
};
1980 } elsif ($conf->{smp
}) {
1981 $conf->{sockets
} = $conf->{smp
};
1982 delete $conf->{cores
};
1983 delete $conf->{smp
};
1986 my $used_volids = {};
1988 my $cleanup_config = sub {
1989 my ($cref, $pending, $snapname) = @_;
1991 foreach my $key (keys %$cref) {
1992 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1993 $key eq 'snapstate' || $key eq 'pending';
1994 my $value = $cref->{$key};
1995 if ($key eq 'delete') {
1996 die "propertry 'delete' is only allowed in [PENDING]\n"
1998 # fixme: check syntax?
2001 eval { $value = check_type
($key, $value); };
2002 die "unable to parse value of '$key' - $@" if $@;
2004 $cref->{$key} = $value;
2006 if (!$snapname && valid_drivename
($key)) {
2007 my $drive = parse_drive
($key, $value);
2008 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2013 &$cleanup_config($conf);
2015 &$cleanup_config($conf->{pending
}, 1);
2017 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2018 die "internal error" if $snapname eq 'pending';
2019 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2022 # remove 'unusedX' settings if we re-add a volume
2023 foreach my $key (keys %$conf) {
2024 my $value = $conf->{$key};
2025 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2026 delete $conf->{$key};
2030 my $generate_raw_config = sub {
2031 my ($conf, $pending) = @_;
2035 # add description as comment to top of file
2036 if (defined(my $descr = $conf->{description
})) {
2038 foreach my $cl (split(/\n/, $descr)) {
2039 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2042 $raw .= "#\n" if $pending;
2046 foreach my $key (sort keys %$conf) {
2047 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2048 $raw .= "$key: $conf->{$key}\n";
2053 my $raw = &$generate_raw_config($conf);
2055 if (scalar(keys %{$conf->{pending
}})){
2056 $raw .= "\n[PENDING]\n";
2057 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2060 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2061 $raw .= "\n[$snapname]\n";
2062 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2068 sub update_config_nolock
{
2069 my ($vmid, $conf, $skiplock) = @_;
2071 check_lock
($conf) if !$skiplock;
2073 my $cfspath = cfs_config_path
($vmid);
2075 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2079 my ($vmid, $conf, $skiplock) = @_;
2081 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2088 # we use static defaults from our JSON schema configuration
2089 foreach my $key (keys %$confdesc) {
2090 if (defined(my $default = $confdesc->{$key}->{default})) {
2091 $res->{$key} = $default;
2095 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2096 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2102 my $vmlist = PVE
::Cluster
::get_vmlist
();
2104 return $res if !$vmlist || !$vmlist->{ids
};
2105 my $ids = $vmlist->{ids
};
2107 foreach my $vmid (keys %$ids) {
2108 my $d = $ids->{$vmid};
2109 next if !$d->{node
} || $d->{node
} ne $nodename;
2110 next if !$d->{type
} || $d->{type
} ne 'qemu';
2111 $res->{$vmid}->{exists} = 1;
2116 # test if VM uses local resources (to prevent migration)
2117 sub check_local_resources
{
2118 my ($conf, $noerr) = @_;
2122 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2123 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2125 foreach my $k (keys %$conf) {
2126 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2127 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2130 die "VM uses local resources\n" if $loc_res && !$noerr;
2135 # check if used storages are available on all nodes (use by migrate)
2136 sub check_storage_availability
{
2137 my ($storecfg, $conf, $node) = @_;
2139 foreach_drive
($conf, sub {
2140 my ($ds, $drive) = @_;
2142 my $volid = $drive->{file
};
2145 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2148 # check if storage is available on both nodes
2149 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2150 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2154 # list nodes where all VM images are available (used by has_feature API)
2156 my ($conf, $storecfg) = @_;
2158 my $nodelist = PVE
::Cluster
::get_nodelist
();
2159 my $nodehash = { map { $_ => 1 } @$nodelist };
2160 my $nodename = PVE
::INotify
::nodename
();
2162 foreach_drive
($conf, sub {
2163 my ($ds, $drive) = @_;
2165 my $volid = $drive->{file
};
2168 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2170 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2171 if ($scfg->{disable
}) {
2173 } elsif (my $avail = $scfg->{nodes
}) {
2174 foreach my $node (keys %$nodehash) {
2175 delete $nodehash->{$node} if !$avail->{$node};
2177 } elsif (!$scfg->{shared
}) {
2178 foreach my $node (keys %$nodehash) {
2179 delete $nodehash->{$node} if $node ne $nodename
2191 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2195 my ($pidfile, $pid) = @_;
2197 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2201 return undef if !$line;
2202 my @param = split(/\0/, $line);
2204 my $cmd = $param[0];
2205 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2207 for (my $i = 0; $i < scalar (@param); $i++) {
2210 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2211 my $p = $param[$i+1];
2212 return 1 if $p && ($p eq $pidfile);
2221 my ($vmid, $nocheck, $node) = @_;
2223 my $filename = config_file
($vmid, $node);
2225 die "unable to find configuration file for VM $vmid - no such machine\n"
2226 if !$nocheck && ! -f
$filename;
2228 my $pidfile = pidfile_name
($vmid);
2230 if (my $fd = IO
::File-
>new("<$pidfile")) {
2235 my $mtime = $st->mtime;
2236 if ($mtime > time()) {
2237 warn "file '$filename' modified in future\n";
2240 if ($line =~ m/^(\d+)$/) {
2242 if (check_cmdline
($pidfile, $pid)) {
2243 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2255 my $vzlist = config_list
();
2257 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2259 while (defined(my $de = $fd->read)) {
2260 next if $de !~ m/^(\d+)\.pid$/;
2262 next if !defined($vzlist->{$vmid});
2263 if (my $pid = check_running
($vmid)) {
2264 $vzlist->{$vmid}->{pid
} = $pid;
2272 my ($storecfg, $conf) = @_;
2274 my $bootdisk = $conf->{bootdisk
};
2275 return undef if !$bootdisk;
2276 return undef if !valid_drivename
($bootdisk);
2278 return undef if !$conf->{$bootdisk};
2280 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2281 return undef if !defined($drive);
2283 return undef if drive_is_cdrom
($drive);
2285 my $volid = $drive->{file
};
2286 return undef if !$volid;
2288 return $drive->{size
};
2291 my $last_proc_pid_stat;
2293 # get VM status information
2294 # This must be fast and should not block ($full == false)
2295 # We only query KVM using QMP if $full == true (this can be slow)
2297 my ($opt_vmid, $full) = @_;
2301 my $storecfg = PVE
::Storage
::config
();
2303 my $list = vzlist
();
2304 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2306 my $cpucount = $cpuinfo->{cpus
} || 1;
2308 foreach my $vmid (keys %$list) {
2309 next if $opt_vmid && ($vmid ne $opt_vmid);
2311 my $cfspath = cfs_config_path
($vmid);
2312 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2315 $d->{pid
} = $list->{$vmid}->{pid
};
2317 # fixme: better status?
2318 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2320 my $size = disksize
($storecfg, $conf);
2321 if (defined($size)) {
2322 $d->{disk
} = 0; # no info available
2323 $d->{maxdisk
} = $size;
2329 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2330 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2331 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2333 $d->{name
} = $conf->{name
} || "VM $vmid";
2334 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2336 if ($conf->{balloon
}) {
2337 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2338 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2349 $d->{diskwrite
} = 0;
2351 $d->{template
} = is_template
($conf);
2356 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2357 foreach my $dev (keys %$netdev) {
2358 next if $dev !~ m/^tap([1-9]\d*)i/;
2360 my $d = $res->{$vmid};
2363 $d->{netout
} += $netdev->{$dev}->{receive
};
2364 $d->{netin
} += $netdev->{$dev}->{transmit
};
2367 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2368 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2373 my $ctime = gettimeofday
;
2375 foreach my $vmid (keys %$list) {
2377 my $d = $res->{$vmid};
2378 my $pid = $d->{pid
};
2381 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2382 next if !$pstat; # not running
2384 my $used = $pstat->{utime} + $pstat->{stime
};
2386 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2388 if ($pstat->{vsize
}) {
2389 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2392 my $old = $last_proc_pid_stat->{$pid};
2394 $last_proc_pid_stat->{$pid} = {
2402 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2404 if ($dtime > 1000) {
2405 my $dutime = $used - $old->{used
};
2407 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2408 $last_proc_pid_stat->{$pid} = {
2414 $d->{cpu
} = $old->{cpu
};
2418 return $res if !$full;
2420 my $qmpclient = PVE
::QMPClient-
>new();
2422 my $ballooncb = sub {
2423 my ($vmid, $resp) = @_;
2425 my $info = $resp->{'return'};
2426 return if !$info->{max_mem
};
2428 my $d = $res->{$vmid};
2430 # use memory assigned to VM
2431 $d->{maxmem
} = $info->{max_mem
};
2432 $d->{balloon
} = $info->{actual
};
2434 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2435 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2436 $d->{freemem
} = $info->{free_mem
};
2439 $d->{ballooninfo
} = $info;
2442 my $blockstatscb = sub {
2443 my ($vmid, $resp) = @_;
2444 my $data = $resp->{'return'} || [];
2445 my $totalrdbytes = 0;
2446 my $totalwrbytes = 0;
2448 for my $blockstat (@$data) {
2449 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2450 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2452 $blockstat->{device
} =~ s/drive-//;
2453 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2455 $res->{$vmid}->{diskread
} = $totalrdbytes;
2456 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2459 my $statuscb = sub {
2460 my ($vmid, $resp) = @_;
2462 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2463 # this fails if ballon driver is not loaded, so this must be
2464 # the last commnand (following command are aborted if this fails).
2465 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2467 my $status = 'unknown';
2468 if (!defined($status = $resp->{'return'}->{status
})) {
2469 warn "unable to get VM status\n";
2473 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2476 foreach my $vmid (keys %$list) {
2477 next if $opt_vmid && ($vmid ne $opt_vmid);
2478 next if !$res->{$vmid}->{pid
}; # not running
2479 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2482 $qmpclient->queue_execute(undef, 1);
2484 foreach my $vmid (keys %$list) {
2485 next if $opt_vmid && ($vmid ne $opt_vmid);
2486 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2493 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2496 my $current_size = 1024;
2497 my $dimm_size = 512;
2498 return if $current_size == $memory;
2500 for (my $j = 0; $j < 8; $j++) {
2501 for (my $i = 0; $i < 32; $i++) {
2502 my $name = "dimm${dimm_id}";
2504 my $numanode = $i % $sockets;
2505 $current_size += $dimm_size;
2506 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2507 return $current_size if $current_size >= $memory;
2513 sub foreach_reverse_dimm
{
2514 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2517 my $current_size = 4177920;
2518 my $dimm_size = 65536;
2519 return if $current_size == $memory;
2521 for (my $j = 0; $j < 8; $j++) {
2522 for (my $i = 0; $i < 32; $i++) {
2523 my $name = "dimm${dimm_id}";
2525 my $numanode = $i % $sockets;
2526 $current_size -= $dimm_size;
2527 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2528 return $current_size if $current_size <= $memory;
2535 my ($conf, $func) = @_;
2537 foreach my $ds (keys %$conf) {
2538 next if !valid_drivename
($ds);
2540 my $drive = parse_drive
($ds, $conf->{$ds});
2543 &$func($ds, $drive);
2548 my ($conf, $func) = @_;
2552 my $test_volid = sub {
2553 my ($volid, $is_cdrom) = @_;
2557 $volhash->{$volid} = $is_cdrom || 0;
2560 foreach_drive
($conf, sub {
2561 my ($ds, $drive) = @_;
2562 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2565 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2566 my $snap = $conf->{snapshots
}->{$snapname};
2567 &$test_volid($snap->{vmstate
}, 0);
2568 foreach_drive
($snap, sub {
2569 my ($ds, $drive) = @_;
2570 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2574 foreach my $volid (keys %$volhash) {
2575 &$func($volid, $volhash->{$volid});
2579 sub vga_conf_has_spice
{
2582 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2587 sub config_to_command
{
2588 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2591 my $globalFlags = [];
2592 my $machineFlags = [];
2598 my $kvmver = kvm_user_version
();
2599 my $vernum = 0; # unknown
2600 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2601 $vernum = $1*1000000+$2*1000;
2602 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2603 $vernum = $1*1000000+$2*1000+$3;
2606 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2608 my $have_ovz = -f
'/proc/vz/vestat';
2610 my $q35 = machine_type_is_q35
($conf);
2611 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2612 my $machine_type = $forcemachine || $conf->{machine
};
2614 my $cpuunits = defined($conf->{cpuunits
}) ?
2615 $conf->{cpuunits
} : $defaults->{cpuunits
};
2617 push @$cmd, '/usr/bin/systemd-run';
2618 push @$cmd, '--scope';
2619 push @$cmd, '--slice', "qemu";
2620 push @$cmd, '--unit', $vmid;
2621 push @$cmd, '-p', "CPUShares=$cpuunits";
2622 if ($conf->{cpulimit
}) {
2623 my $cpulimit = int($conf->{cpulimit
} * 100);
2624 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2627 push @$cmd, '/usr/bin/kvm';
2629 push @$cmd, '-id', $vmid;
2633 my $qmpsocket = qmp_socket
($vmid);
2634 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2635 push @$cmd, '-mon', "chardev=qmp,mode=control";
2637 my $socket = vnc_socket
($vmid);
2638 push @$cmd, '-vnc', "unix:$socket,x509,password";
2640 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2642 push @$cmd, '-daemonize';
2644 if ($conf->{smbios1
}) {
2645 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2649 # the q35 chipset support native usb2, so we enable usb controller
2650 # by default for this machine type
2651 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2653 $pciaddr = print_pci_addr
("piix3", $bridges);
2654 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2657 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2658 next if !$conf->{"usb$i"};
2661 # include usb device config
2662 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2665 my $vga = $conf->{vga
};
2667 my $qxlnum = vga_conf_has_spice
($vga);
2668 $vga = 'qxl' if $qxlnum;
2671 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2672 $conf->{ostype
} eq 'win7' ||
2673 $conf->{ostype
} eq 'w2k8')) {
2680 # enable absolute mouse coordinates (needed by vnc)
2682 if (defined($conf->{tablet
})) {
2683 $tablet = $conf->{tablet
};
2685 $tablet = $defaults->{tablet
};
2686 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2687 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2690 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2693 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2694 my $d = parse_hostpci
($conf->{"hostpci$i"});
2697 my $pcie = $d->{pcie
};
2699 die "q35 machine model is not enabled" if !$q35;
2700 $pciaddr = print_pcie_addr
("hostpci$i");
2702 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2705 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2706 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2707 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2708 if ($xvga && $xvga ne '') {
2709 push @$cpuFlags, 'kvm=off';
2712 $driver = "vfio-pci" if $xvga ne '';
2713 my $pcidevices = $d->{pciid
};
2714 my $multifunction = 1 if @$pcidevices > 1;
2717 foreach my $pcidevice (@$pcidevices) {
2719 my $id = "hostpci$i";
2720 $id .= ".$j" if $multifunction;
2721 my $addr = $pciaddr;
2722 $addr .= ".$j" if $multifunction;
2723 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2726 $devicestr .= "$rombar$xvga";
2727 $devicestr .= ",multifunction=on" if $multifunction;
2730 push @$devices, '-device', $devicestr;
2736 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2737 my $d = parse_usb_device
($conf->{"usb$i"});
2739 if ($d->{vendorid
} && $d->{productid
}) {
2740 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2741 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2742 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2743 } elsif ($d->{spice
}) {
2744 # usb redir support for spice
2745 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2746 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2751 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2752 if (my $path = $conf->{"serial$i"}) {
2753 if ($path eq 'socket') {
2754 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2755 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2756 push @$devices, '-device', "isa-serial,chardev=serial$i";
2758 die "no such serial device\n" if ! -c
$path;
2759 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2760 push @$devices, '-device', "isa-serial,chardev=serial$i";
2766 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2767 if (my $path = $conf->{"parallel$i"}) {
2768 die "no such parallel device\n" if ! -c
$path;
2769 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2770 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2771 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2775 my $vmname = $conf->{name
} || "vm$vmid";
2777 push @$cmd, '-name', $vmname;
2780 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2781 $sockets = $conf->{sockets
} if $conf->{sockets
};
2783 my $cores = $conf->{cores
} || 1;
2785 my $maxcpus = $sockets * $cores;
2787 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2789 my $allowed_vcpus = $cpuinfo->{cpus
};
2791 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2792 if ($allowed_vcpus < $maxcpus);
2794 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2796 push @$cmd, '-nodefaults';
2798 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2800 my $bootindex_hash = {};
2802 foreach my $o (split(//, $bootorder)) {
2803 $bootindex_hash->{$o} = $i*100;
2807 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2809 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2811 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2813 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2816 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2818 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2819 my $useLocaltime = $conf->{localtime};
2821 if (my $ost = $conf->{ostype
}) {
2822 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2824 if ($ost =~ m/^w/) { # windows
2825 $useLocaltime = 1 if !defined($conf->{localtime});
2827 # use time drift fix when acpi is enabled
2828 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2829 $tdf = 1 if !defined($conf->{tdf
});
2833 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2835 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2836 push @$cmd, '-no-hpet';
2837 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2838 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2839 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2840 push @$cpuFlags , 'hv_time' if !$nokvm;
2843 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2847 if ($ost eq 'win7' || $ost eq 'win8') {
2848 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2852 push @$rtcFlags, 'driftfix=slew' if $tdf;
2855 push @$machineFlags, 'accel=tcg';
2857 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2860 if ($machine_type) {
2861 push @$machineFlags, "type=${machine_type}";
2864 if ($conf->{startdate
}) {
2865 push @$rtcFlags, "base=$conf->{startdate}";
2866 } elsif ($useLocaltime) {
2867 push @$rtcFlags, 'base=localtime';
2870 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2871 $cpu = $conf->{cpu
} if $conf->{cpu
};
2873 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2875 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2877 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2879 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2881 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2883 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2885 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2886 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2889 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2891 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2893 push @$cmd, '-cpu', $cpu;
2895 my $memory = $conf->{memory
} || $defaults->{memory
};
2896 my $static_memory = 0;
2897 my $dimm_memory = 0;
2899 if ($hotplug_features->{memory
}) {
2900 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2901 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2902 $static_memory = $STATICMEM;
2903 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2904 $dimm_memory = $memory - $static_memory;
2905 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2909 $static_memory = $memory;
2910 push @$cmd, '-m', $static_memory;
2913 if ($conf->{numa
}) {
2915 my $numa_totalmemory = undef;
2916 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2917 next if !$conf->{"numa$i"};
2918 my $numa = parse_numa
($conf->{"numa$i"});
2921 die "missing numa node$i memory value\n" if !$numa->{memory
};
2922 my $numa_memory = $numa->{memory
};
2923 $numa_totalmemory += $numa_memory;
2924 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2927 my $cpus_start = $numa->{cpus
}->{start
};
2928 die "missing numa node$i cpus\n" if !defined($cpus_start);
2929 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2930 my $cpus = $cpus_start;
2931 if (defined($cpus_end)) {
2932 $cpus .= "-$cpus_end";
2933 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2937 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2938 if (defined($hostnodes_start)) {
2939 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2940 my $hostnodes = $hostnodes_start;
2941 if (defined($hostnodes_end)) {
2942 $hostnodes .= "-$hostnodes_end";
2943 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2946 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2947 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2948 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2952 my $policy = $numa->{policy
};
2953 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2954 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2957 push @$cmd, '-object', $numa_object;
2958 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2961 die "total memory for NUMA nodes must be equal to vm static memory\n"
2962 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2964 #if no custom tology, we split memory and cores across numa nodes
2965 if(!$numa_totalmemory) {
2967 my $numa_memory = ($static_memory / $sockets) . "M";
2969 for (my $i = 0; $i < $sockets; $i++) {
2971 my $cpustart = ($cores * $i);
2972 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2973 my $cpus = $cpustart;
2974 $cpus .= "-$cpuend" if $cpuend;
2976 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2977 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2982 if ($hotplug_features->{memory
}) {
2983 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2984 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2985 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2986 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2988 #if dimm_memory is not aligned to dimm map
2989 if($current_size > $memory) {
2990 $conf->{memory
} = $current_size;
2991 update_config_nolock
($vmid, $conf, 1);
2996 push @$cmd, '-S' if $conf->{freeze
};
2998 # set keyboard layout
2999 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3000 push @$cmd, '-k', $kb if $kb;
3003 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3004 #push @$cmd, '-soundhw', 'es1370';
3005 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3007 if($conf->{agent
}) {
3008 my $qgasocket = qmp_socket
($vmid, 1);
3009 my $pciaddr = print_pci_addr
("qga0", $bridges);
3010 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3011 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3012 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3019 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3020 for(my $i = 1; $i < $qxlnum; $i++){
3021 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3022 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3025 # assume other OS works like Linux
3026 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3027 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3031 my $pciaddr = print_pci_addr
("spice", $bridges);
3033 my $nodename = PVE
::INotify
::nodename
();
3034 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3035 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3037 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3039 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3040 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3041 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3044 # enable balloon by default, unless explicitly disabled
3045 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3046 $pciaddr = print_pci_addr
("balloon0", $bridges);
3047 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3050 if ($conf->{watchdog
}) {
3051 my $wdopts = parse_watchdog
($conf->{watchdog
});
3052 $pciaddr = print_pci_addr
("watchdog", $bridges);
3053 my $watchdog = $wdopts->{model
} || 'i6300esb';
3054 push @$devices, '-device', "$watchdog$pciaddr";
3055 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3059 my $scsicontroller = {};
3060 my $ahcicontroller = {};
3061 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3063 # Add iscsi initiator name if available
3064 if (my $initiator = get_initiator_name
()) {
3065 push @$devices, '-iscsi', "initiator-name=$initiator";
3068 foreach_drive
($conf, sub {
3069 my ($ds, $drive) = @_;
3071 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3072 push @$vollist, $drive->{file
};
3075 $use_virtio = 1 if $ds =~ m/^virtio/;
3077 if (drive_is_cdrom
($drive)) {
3078 if ($bootindex_hash->{d
}) {
3079 $drive->{bootindex
} = $bootindex_hash->{d
};
3080 $bootindex_hash->{d
} += 1;
3083 if ($bootindex_hash->{c
}) {
3084 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3085 $bootindex_hash->{c
} += 1;
3089 if($drive->{interface
} eq 'virtio'){
3090 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3093 if ($drive->{interface
} eq 'scsi') {
3095 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3097 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3098 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3101 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3102 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3103 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3107 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3108 $queues = ",num_queues=$drive->{queues}";
3111 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3112 $scsicontroller->{$controller}=1;
3115 if ($drive->{interface
} eq 'sata') {
3116 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3117 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3118 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3119 $ahcicontroller->{$controller}=1;
3122 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3123 push @$devices, '-drive',$drive_cmd;
3124 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3127 for (my $i = 0; $i < $MAX_NETS; $i++) {
3128 next if !$conf->{"net$i"};
3129 my $d = parse_net
($conf->{"net$i"});
3132 $use_virtio = 1 if $d->{model
} eq 'virtio';
3134 if ($bootindex_hash->{n
}) {
3135 $d->{bootindex
} = $bootindex_hash->{n
};
3136 $bootindex_hash->{n
} += 1;
3139 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3140 push @$devices, '-netdev', $netdevfull;
3142 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3143 push @$devices, '-device', $netdevicefull;
3148 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3153 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3155 while (my ($k, $v) = each %$bridges) {
3156 $pciaddr = print_pci_addr
("pci.$k");
3157 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3162 if ($conf->{args
}) {
3163 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3167 push @$cmd, @$devices;
3168 push @$cmd, '-rtc', join(',', @$rtcFlags)
3169 if scalar(@$rtcFlags);
3170 push @$cmd, '-machine', join(',', @$machineFlags)
3171 if scalar(@$machineFlags);
3172 push @$cmd, '-global', join(',', @$globalFlags)
3173 if scalar(@$globalFlags);
3175 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3180 return "${var_run_tmpdir}/$vmid.vnc";
3186 my $res = vm_mon_cmd
($vmid, 'query-spice');
3188 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3192 my ($vmid, $qga) = @_;
3193 my $sockettype = $qga ?
'qga' : 'qmp';
3194 return "${var_run_tmpdir}/$vmid.$sockettype";
3199 return "${var_run_tmpdir}/$vmid.pid";
3202 sub vm_devices_list
{
3205 my $res = vm_mon_cmd
($vmid, 'query-pci');
3207 foreach my $pcibus (@$res) {
3208 foreach my $device (@{$pcibus->{devices
}}) {
3209 next if !$device->{'qdev_id'};
3210 if ($device->{'pci_bridge'}) {
3211 $devices->{$device->{'qdev_id'}} = 1;
3212 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3213 next if !$bridge_device->{'qdev_id'};
3214 $devices->{$bridge_device->{'qdev_id'}} = 1;
3215 $devices->{$device->{'qdev_id'}}++;
3218 $devices->{$device->{'qdev_id'}} = 1;
3223 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3224 foreach my $block (@$resblock) {
3225 if($block->{device
} =~ m/^drive-(\S+)/){
3230 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3231 foreach my $mice (@$resmice) {
3232 if ($mice->{name
} eq 'QEMU HID Tablet') {
3233 $devices->{tablet
} = 1;
3242 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3244 my $q35 = machine_type_is_q35
($conf);
3246 my $devices_list = vm_devices_list
($vmid);
3247 return 1 if defined($devices_list->{$deviceid});
3249 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3251 if ($deviceid eq 'tablet') {
3253 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3255 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3257 qemu_iothread_add
($vmid, $deviceid, $device);
3259 qemu_driveadd
($storecfg, $vmid, $device);
3260 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3262 qemu_deviceadd
($vmid, $devicefull);
3263 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3265 eval { qemu_drivedel
($vmid, $deviceid); };
3270 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3273 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3274 my $pciaddr = print_pci_addr
($deviceid);
3275 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3277 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3279 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3280 qemu_iothread_add
($vmid, $deviceid, $device);
3281 $devicefull .= ",iothread=iothread-$deviceid";
3284 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3285 $devicefull .= ",num_queues=$device->{queues}";
3288 qemu_deviceadd
($vmid, $devicefull);
3289 qemu_deviceaddverify
($vmid, $deviceid);
3291 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3293 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3294 qemu_driveadd
($storecfg, $vmid, $device);
3296 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3297 eval { qemu_deviceadd
($vmid, $devicefull); };
3299 eval { qemu_drivedel
($vmid, $deviceid); };
3304 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3306 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3307 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3308 qemu_deviceadd
($vmid, $netdevicefull);
3309 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3311 eval { qemu_netdevdel
($vmid, $deviceid); };
3316 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3319 my $pciaddr = print_pci_addr
($deviceid);
3320 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3322 qemu_deviceadd
($vmid, $devicefull);
3323 qemu_deviceaddverify
($vmid, $deviceid);
3326 die "can't hotplug device '$deviceid'\n";
3332 # fixme: this should raise exceptions on error!
3333 sub vm_deviceunplug
{
3334 my ($vmid, $conf, $deviceid) = @_;
3336 my $devices_list = vm_devices_list
($vmid);
3337 return 1 if !defined($devices_list->{$deviceid});
3339 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3341 if ($deviceid eq 'tablet') {
3343 qemu_devicedel
($vmid, $deviceid);
3345 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3347 qemu_devicedel
($vmid, $deviceid);
3348 qemu_devicedelverify
($vmid, $deviceid);
3349 qemu_drivedel
($vmid, $deviceid);
3350 qemu_iothread_del
($conf, $vmid, $deviceid);
3352 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3354 qemu_devicedel
($vmid, $deviceid);
3355 qemu_devicedelverify
($vmid, $deviceid);
3356 qemu_iothread_del
($conf, $vmid, $deviceid);
3358 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3360 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3361 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3362 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3364 qemu_devicedel
($vmid, $deviceid);
3365 qemu_drivedel
($vmid, $deviceid);
3366 qemu_deletescsihw
($conf, $vmid, $deviceid);
3368 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3370 qemu_devicedel
($vmid, $deviceid);
3371 qemu_devicedelverify
($vmid, $deviceid);
3372 qemu_netdevdel
($vmid, $deviceid);
3375 die "can't unplug device '$deviceid'\n";
3381 sub qemu_deviceadd
{
3382 my ($vmid, $devicefull) = @_;
3384 $devicefull = "driver=".$devicefull;
3385 my %options = split(/[=,]/, $devicefull);
3387 vm_mon_cmd
($vmid, "device_add" , %options);
3390 sub qemu_devicedel
{
3391 my ($vmid, $deviceid) = @_;
3393 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3396 sub qemu_iothread_add
{
3397 my($vmid, $deviceid, $device) = @_;
3399 if ($device->{iothread
}) {
3400 my $iothreads = vm_iothreads_list
($vmid);
3401 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3405 sub qemu_iothread_del
{
3406 my($conf, $vmid, $deviceid) = @_;
3408 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3409 if ($device->{iothread
}) {
3410 my $iothreads = vm_iothreads_list
($vmid);
3411 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3415 sub qemu_objectadd
{
3416 my($vmid, $objectid, $qomtype) = @_;
3418 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3423 sub qemu_objectdel
{
3424 my($vmid, $objectid) = @_;
3426 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3432 my ($storecfg, $vmid, $device) = @_;
3434 my $drive = print_drive_full
($storecfg, $vmid, $device);
3435 $drive =~ s/\\/\\\\/g;
3436 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3438 # If the command succeeds qemu prints: "OK
"
3439 return 1 if $ret =~ m/OK/s;
3441 die "adding drive failed
: $ret\n";
3445 my($vmid, $deviceid) = @_;
3447 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3450 return 1 if $ret eq "";
3452 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3453 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3455 die "deleting drive
$deviceid failed
: $ret\n";
3458 sub qemu_deviceaddverify {
3459 my ($vmid, $deviceid) = @_;
3461 for (my $i = 0; $i <= 5; $i++) {
3462 my $devices_list = vm_devices_list($vmid);
3463 return 1 if defined($devices_list->{$deviceid});
3467 die "error on hotplug device
'$deviceid'\n";
3471 sub qemu_devicedelverify {
3472 my ($vmid, $deviceid) = @_;
3474 # need to verify that the device is correctly removed as device_del
3475 # is async and empty return is not reliable
3477 for (my $i = 0; $i <= 5; $i++) {
3478 my $devices_list = vm_devices_list($vmid);
3479 return 1 if !defined($devices_list->{$deviceid});
3483 die "error on hot-unplugging device
'$deviceid'\n";
3486 sub qemu_findorcreatescsihw {
3487 my ($storecfg, $conf, $vmid, $device) = @_;
3489 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3491 my $scsihwid="$controller_prefix$controller";
3492 my $devices_list = vm_devices_list($vmid);
3494 if(!defined($devices_list->{$scsihwid})) {
3495 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3501 sub qemu_deletescsihw {
3502 my ($conf, $vmid, $opt) = @_;
3504 my $device = parse_drive($opt, $conf->{$opt});
3506 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3507 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3511 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3513 my $devices_list = vm_devices_list($vmid);
3514 foreach my $opt (keys %{$devices_list}) {
3515 if (PVE::QemuServer::valid_drivename($opt)) {
3516 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3517 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3523 my $scsihwid="scsihw
$controller";
3525 vm_deviceunplug($vmid, $conf, $scsihwid);
3530 sub qemu_add_pci_bridge {
3531 my ($storecfg, $conf, $vmid, $device) = @_;
3537 print_pci_addr($device, $bridges);
3539 while (my ($k, $v) = each %$bridges) {
3542 return 1 if !defined($bridgeid) || $bridgeid < 1;
3544 my $bridge = "pci
.$bridgeid";
3545 my $devices_list = vm_devices_list($vmid);
3547 if (!defined($devices_list->{$bridge})) {
3548 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3554 sub qemu_set_link_status {
3555 my ($vmid, $device, $up) = @_;
3557 vm_mon_cmd($vmid, "set_link
", name => $device,
3558 up => $up ? JSON::true : JSON::false);
3561 sub qemu_netdevadd {
3562 my ($vmid, $conf, $device, $deviceid) = @_;
3564 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3565 my %options = split(/[=,]/, $netdev);
3567 vm_mon_cmd($vmid, "netdev_add
", %options);
3571 sub qemu_netdevdel {
3572 my ($vmid, $deviceid) = @_;
3574 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3577 sub qemu_cpu_hotplug {
3578 my ($vmid, $conf, $vcpus) = @_;
3581 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3582 $sockets = $conf->{sockets} if $conf->{sockets};
3583 my $cores = $conf->{cores} || 1;
3584 my $maxcpus = $sockets * $cores;
3586 $vcpus = $maxcpus if !$vcpus;
3588 die "you can
't add more vcpus than maxcpus\n"
3589 if $vcpus > $maxcpus;
3591 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3592 die "online cpu unplug is not yet possible\n"
3593 if $vcpus < $currentvcpus;
3595 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3596 die "vcpus in running vm is different than configuration\n"
3597 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3599 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3600 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3604 sub qemu_memory_hotplug {
3605 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3607 return $value if !check_running($vmid);
3609 my $memory = $conf->{memory} || $defaults->{memory};
3610 $value = $defaults->{memory} if !$value;
3611 return $value if $value == $memory;
3613 my $static_memory = $STATICMEM;
3614 my $dimm_memory = $memory - $static_memory;
3616 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3617 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3621 $sockets = $conf->{sockets} if $conf->{sockets};
3623 if($value > $memory) {
3625 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3626 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3628 return if $current_size <= $conf->{memory};
3630 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3632 eval { qemu_objectdel($vmid, "mem-
$name"); };
3636 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3638 eval { qemu_objectdel($vmid, "mem-
$name"); };
3641 #update conf after each succesful module hotplug
3642 $conf->{memory} = $current_size;
3643 update_config_nolock($vmid, $conf, 1);
3648 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3649 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3651 return if $current_size >= $conf->{memory};
3652 print "try to unplug memory dimm
$name\n";
3656 eval { qemu_devicedel($vmid, $name) };
3658 my $dimm_list = qemu_dimm_list($vmid);
3659 last if !$dimm_list->{$name};
3660 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3664 #update conf after each succesful module unplug
3665 $conf->{memory} = $current_size;
3667 eval { qemu_objectdel($vmid, "mem-
$name"); };
3668 update_config_nolock($vmid, $conf, 1);
3673 sub qemu_dimm_list {
3676 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3679 foreach my $dimm (@$dimmarray) {
3681 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3682 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3683 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3684 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3685 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3690 sub qemu_block_set_io_throttle {
3691 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3693 return if !check_running($vmid) ;
3695 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));
3699 # old code, only used to shutdown old VM after update
3701 my ($fh, $timeout) = @_;
3703 my $sel = new IO::Select;
3710 while (scalar (@ready = $sel->can_read($timeout))) {
3712 if ($count = $fh->sysread($buf, 8192)) {
3713 if ($buf =~ /^(.*)\(qemu\) $/s) {
3720 if (!defined($count)) {
3727 die "monitor
read timeout
\n" if !scalar(@ready);
3732 # old code, only used to shutdown old VM after update
3733 sub vm_monitor_command {
3734 my ($vmid, $cmdstr, $nocheck) = @_;
3739 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3741 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3743 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3744 die "unable to
connect to VM
$vmid socket - $!\n";
3748 # hack: migrate sometime blocks the monitor (when migrate_downtime
3750 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3751 $timeout = 60*60; # 1 hour
3755 my $data = __read_avail($sock, $timeout);
3757 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3758 die "got unexpected qemu monitor banner
\n";
3761 my $sel = new IO::Select;
3764 if (!scalar(my @ready = $sel->can_write($timeout))) {
3765 die "monitor
write error
- timeout
";
3768 my $fullcmd = "$cmdstr\r";
3770 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3773 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3774 die "monitor
write error
- $!";
3777 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3781 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3782 $timeout = 60*60; # 1 hour
3783 } elsif ($cmdstr =~ m/^(eject|change)/) {
3784 $timeout = 60; # note: cdrom mount command is slow
3786 if ($res = __read_avail($sock, $timeout)) {
3788 my @lines = split("\r?
\n", $res);
3790 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3792 $res = join("\n", @lines);
3800 syslog("err
", "VM
$vmid monitor command failed
- $err");
3807 sub qemu_block_resize {
3808 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3810 my $running = check_running($vmid);
3812 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3814 return if !$running;
3816 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3820 sub qemu_volume_snapshot {
3821 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3823 my $running = check_running($vmid);
3825 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3826 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3828 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3832 sub qemu_volume_snapshot_delete {
3833 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3835 my $running = check_running($vmid);
3837 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3839 return if !$running;
3841 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3844 sub set_migration_caps {
3850 "auto-converge
" => 1,
3852 "x-rdma-pin-all
" => 0,
3856 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3858 for my $supported_capability (@$supported_capabilities) {
3860 capability => $supported_capability->{capability},
3861 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3865 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3868 my $fast_plug_option = {
3877 # hotplug changes in [PENDING]
3878 # $selection hash can be used to only apply specified options, for
3879 # example: { cores => 1 } (only apply changed 'cores')
3880 # $errors ref is used to return error messages
3881 sub vmconfig_hotplug_pending {
3882 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3884 my $defaults = load_defaults();
3886 # commit values which do not have any impact on running VM first
3887 # Note: those option cannot raise errors, we we do not care about
3888 # $selection and always apply them.
3890 my $add_error = sub {
3891 my ($opt, $msg) = @_;
3892 $errors->{$opt} = "hotplug problem
- $msg";
3896 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3897 if ($fast_plug_option->{$opt}) {
3898 $conf->{$opt} = $conf->{pending}->{$opt};
3899 delete $conf->{pending}->{$opt};
3905 update_config_nolock($vmid, $conf, 1);
3906 $conf = load_config($vmid); # update/reload
3909 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3911 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3912 foreach my $opt (@delete) {
3913 next if $selection && !$selection->{$opt};
3915 if ($opt eq 'hotplug') {
3916 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3917 } elsif ($opt eq 'tablet') {
3918 die "skip
\n" if !$hotplug_features->{usb};
3919 if ($defaults->{tablet}) {
3920 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3922 vm_deviceunplug($vmid, $conf, $opt);
3924 } elsif ($opt eq 'vcpus') {
3925 die "skip
\n" if !$hotplug_features->{cpu};
3926 qemu_cpu_hotplug($vmid, $conf, undef);
3927 } elsif ($opt eq 'balloon') {
3928 # enable balloon device is not hotpluggable
3929 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3930 } elsif ($fast_plug_option->{$opt}) {
3932 } elsif ($opt =~ m/^net(\d+)$/) {
3933 die "skip
\n" if !$hotplug_features->{network};
3934 vm_deviceunplug($vmid, $conf, $opt);
3935 } elsif (valid_drivename($opt)) {
3936 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3937 vm_deviceunplug($vmid, $conf, $opt);
3938 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3939 } elsif ($opt =~ m/^memory$/) {
3940 die "skip
\n" if !$hotplug_features->{memory};
3941 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3942 } elsif ($opt eq 'cpuunits') {
3943 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3944 } elsif ($opt eq 'cpulimit') {
3945 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3951 &$add_error($opt, $err) if $err ne "skip
\n";
3953 # save new config if hotplug was successful
3954 delete $conf->{$opt};
3955 vmconfig_undelete_pending_option($conf, $opt);
3956 update_config_nolock($vmid, $conf, 1);
3957 $conf = load_config($vmid); # update/reload
3961 foreach my $opt (keys %{$conf->{pending}}) {
3962 next if $selection && !$selection->{$opt};
3963 my $value = $conf->{pending}->{$opt};
3965 if ($opt eq 'hotplug') {
3966 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3967 } elsif ($opt eq 'tablet') {
3968 die "skip
\n" if !$hotplug_features->{usb};
3970 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3971 } elsif ($value == 0) {
3972 vm_deviceunplug($vmid, $conf, $opt);
3974 } elsif ($opt eq 'vcpus') {
3975 die "skip
\n" if !$hotplug_features->{cpu};
3976 qemu_cpu_hotplug($vmid, $conf, $value);
3977 } elsif ($opt eq 'balloon') {
3978 # enable/disable balloning device is not hotpluggable
3979 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3980 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3981 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3983 # allow manual ballooning if shares is set to zero
3984 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3985 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3986 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3988 } elsif ($opt =~ m/^net(\d+)$/) {
3989 # some changes can be done without hotplug
3990 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3991 $vmid, $opt, $value);
3992 } elsif (valid_drivename($opt)) {
3993 # some changes can be done without hotplug
3994 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3995 $vmid, $opt, $value, 1);
3996 } elsif ($opt =~ m/^memory$/) { #dimms
3997 die "skip
\n" if !$hotplug_features->{memory};
3998 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3999 } elsif ($opt eq 'cpuunits') {
4000 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4001 } elsif ($opt eq 'cpulimit') {
4002 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4003 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4005 die "skip
\n"; # skip non-hot-pluggable options
4009 &$add_error($opt, $err) if $err ne "skip
\n";
4011 # save new config if hotplug was successful
4012 $conf->{$opt} = $value;
4013 delete $conf->{pending}->{$opt};
4014 update_config_nolock($vmid, $conf, 1);
4015 $conf = load_config($vmid); # update/reload
4020 sub vmconfig_apply_pending {
4021 my ($vmid, $conf, $storecfg) = @_;
4025 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
4026 foreach my $opt (@delete) { # delete
4027 die "internal error
" if $opt =~ m/^unused/;
4028 $conf = load_config($vmid); # update/reload
4029 if (!defined($conf->{$opt})) {
4030 vmconfig_undelete_pending_option($conf, $opt);
4031 update_config_nolock($vmid, $conf, 1);
4032 } elsif (valid_drivename($opt)) {
4033 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
4034 vmconfig_undelete_pending_option($conf, $opt);
4035 delete $conf->{$opt};
4036 update_config_nolock($vmid, $conf, 1);
4038 vmconfig_undelete_pending_option($conf, $opt);
4039 delete $conf->{$opt};
4040 update_config_nolock($vmid, $conf, 1);
4044 $conf = load_config($vmid); # update/reload
4046 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4047 $conf = load_config($vmid); # update/reload
4049 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4050 # skip if nothing changed
4051 } elsif (valid_drivename($opt)) {
4052 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4053 if defined($conf->{$opt});
4054 $conf->{$opt} = $conf->{pending}->{$opt};
4056 $conf->{$opt} = $conf->{pending}->{$opt};
4059 delete $conf->{pending}->{$opt};
4060 update_config_nolock($vmid, $conf, 1);
4064 my $safe_num_ne = sub {
4067 return 0 if !defined($a) && !defined($b);
4068 return 1 if !defined($a);
4069 return 1 if !defined($b);
4074 my $safe_string_ne = sub {
4077 return 0 if !defined($a) && !defined($b);
4078 return 1 if !defined($a);
4079 return 1 if !defined($b);
4084 sub vmconfig_update_net {
4085 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4087 my $newnet = parse_net($value);
4089 if ($conf->{$opt}) {
4090 my $oldnet = parse_net($conf->{$opt});
4092 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4093 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4094 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4095 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4097 # for non online change, we try to hot-unplug
4098 die "skip
\n" if !$hotplug;
4099 vm_deviceunplug($vmid, $conf, $opt);
4102 die "internal error
" if $opt !~ m/net(\d+)/;
4103 my $iface = "tap
${vmid
}i
$1";
4105 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4106 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4109 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4110 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4111 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4112 PVE::Network::tap_unplug($iface);
4113 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4116 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4117 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4125 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4131 sub vmconfig_update_disk {
4132 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4134 # fixme: do we need force?
4136 my $drive = parse_drive($opt, $value);
4138 if ($conf->{$opt}) {
4140 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4142 my $media = $drive->{media} || 'disk';
4143 my $oldmedia = $old_drive->{media} || 'disk';
4144 die "unable to change media type
\n" if $media ne $oldmedia;
4146 if (!drive_is_cdrom($old_drive)) {
4148 if ($drive->{file} ne $old_drive->{file}) {
4150 die "skip
\n" if !$hotplug;
4152 # unplug and register as unused
4153 vm_deviceunplug($vmid, $conf, $opt);
4154 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4157 # update existing disk
4159 # skip non hotpluggable value
4160 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4161 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4162 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4163 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4168 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4169 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4170 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4171 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4172 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4173 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4174 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4175 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4176 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4177 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4178 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4179 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4181 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4182 ($drive->{mbps} || 0)*1024*1024,
4183 ($drive->{mbps_rd} || 0)*1024*1024,
4184 ($drive->{mbps_wr} || 0)*1024*1024,
4185 $drive->{iops} || 0,
4186 $drive->{iops_rd} || 0,
4187 $drive->{iops_wr} || 0,
4188 ($drive->{mbps_max} || 0)*1024*1024,
4189 ($drive->{mbps_rd_max} || 0)*1024*1024,
4190 ($drive->{mbps_wr_max} || 0)*1024*1024,
4191 $drive->{iops_max} || 0,
4192 $drive->{iops_rd_max} || 0,
4193 $drive->{iops_wr_max} || 0);
4202 if ($drive->{file} eq 'none') {
4203 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4205 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4206 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4207 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4215 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4217 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4221 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4223 lock_config($vmid, sub {
4224 my $conf = load_config($vmid, $migratedfrom);
4226 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4228 check_lock($conf) if !$skiplock;
4230 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4232 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4233 vmconfig_apply_pending($vmid, $conf, $storecfg);
4234 $conf = load_config($vmid); # update/reload
4237 my $defaults = load_defaults();
4239 # set environment variable useful inside network script
4240 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4242 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4244 my $migrate_port = 0;
4247 if ($statefile eq 'tcp') {
4248 my $localip = "localhost
";
4249 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4250 my $nodename = PVE::INotify::nodename();
4251 if ($datacenterconf->{migration_unsecure}) {
4252 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4254 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4255 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4256 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4257 push @$cmd, '-incoming', $migrate_uri;
4260 push @$cmd, '-loadstate', $statefile;
4267 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4268 my $d = parse_hostpci($conf->{"hostpci
$i"});
4270 my $pcidevices = $d->{pciid};
4271 foreach my $pcidevice (@$pcidevices) {
4272 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4274 my $info = pci_device_info("0000:$pciid");
4275 die "IOMMU
not present
\n" if !check_iommu_support();
4276 die "no pci device info
for device
'$pciid'\n" if !$info;
4278 if ($d->{driver} && $d->{driver} eq "vfio
") {
4279 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4281 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4284 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4288 PVE::Storage::activate_volumes($storecfg, $vollist);
4290 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4293 die "start failed: $err" if $err;
4295 print "migration listens on $migrate_uri\n" if $migrate_uri;
4297 if ($statefile && $statefile ne 'tcp
') {
4298 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4302 if ($migratedfrom) {
4305 set_migration_caps($vmid);
4310 print "spice listens on port $spice_port\n";
4311 if ($spice_ticket) {
4312 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4313 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4319 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4320 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4321 if $conf->{balloon};
4324 foreach my $opt (keys %$conf) {
4325 next if $opt !~ m/^net\d+$/;
4326 my $nicconf = parse_net($conf->{$opt});
4327 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4331 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4332 path => "machine/peripheral/balloon0",
4333 property => "guest-stats-polling-interval",
4334 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4340 my ($vmid, $execute, %params) = @_;
4342 my $cmd = { execute => $execute, arguments => \%params };
4343 vm_qmp_command($vmid, $cmd);
4346 sub vm_mon_cmd_nocheck {
4347 my ($vmid, $execute, %params) = @_;
4349 my $cmd = { execute => $execute, arguments => \%params };
4350 vm_qmp_command($vmid, $cmd, 1);
4353 sub vm_qmp_command {
4354 my ($vmid, $cmd, $nocheck) = @_;
4359 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4360 $timeout = $cmd->{arguments}->{timeout};
4361 delete $cmd->{arguments}->{timeout};
4365 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4366 my $sname = qmp_socket($vmid);
4367 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4368 my $qmpclient = PVE::QMPClient->new();
4370 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4371 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4372 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4373 if scalar(%{$cmd->{arguments}});
4374 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4376 die "unable to
open monitor
socket\n";
4380 syslog("err
", "VM
$vmid qmp command failed
- $err");
4387 sub vm_human_monitor_command {
4388 my ($vmid, $cmdline) = @_;
4393 execute => 'human-monitor-command',
4394 arguments => { 'command-line' => $cmdline},
4397 return vm_qmp_command($vmid, $cmd);
4400 sub vm_commandline {
4401 my ($storecfg, $vmid) = @_;
4403 my $conf = load_config($vmid);
4405 my $defaults = load_defaults();
4407 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4409 return join(' ', @$cmd);
4413 my ($vmid, $skiplock) = @_;
4415 lock_config($vmid, sub {
4417 my $conf = load_config($vmid);
4419 check_lock($conf) if !$skiplock;
4421 vm_mon_cmd($vmid, "system_reset
");
4425 sub get_vm_volumes {
4429 foreach_volid($conf, sub {
4430 my ($volid, $is_cdrom) = @_;
4432 return if $volid =~ m|^/|;
4434 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4437 push @$vollist, $volid;
4443 sub vm_stop_cleanup {
4444 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4449 my $vollist = get_vm_volumes($conf);
4450 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4453 foreach my $ext (qw(mon qmp pid vnc qga)) {
4454 unlink "/var/run/qemu-server/${vmid}.$ext";
4457 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4459 warn $@ if $@; # avoid errors - just warn
4462 # Note: use $nockeck to skip tests if VM configuration file exists.
4463 # We need that when migration VMs to other nodes (files already moved)
4464 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4466 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4468 $force = 1 if !defined($force) && !$shutdown;
4471 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4472 kill 15, $pid if $pid;
4473 my $conf = load_config
($vmid, $migratedfrom);
4474 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4478 lock_config
($vmid, sub {
4480 my $pid = check_running
($vmid, $nocheck);
4485 $conf = load_config
($vmid);
4486 check_lock
($conf) if !$skiplock;
4487 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4488 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4489 $timeout = $opts->{down
} if $opts->{down
};
4493 $timeout = 60 if !defined($timeout);
4497 if (defined($conf) && $conf->{agent
}) {
4498 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4500 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4503 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4510 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4515 if ($count >= $timeout) {
4517 warn "VM still running - terminating now with SIGTERM\n";
4520 die "VM quit/powerdown failed - got timeout\n";
4523 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4528 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4531 die "VM quit/powerdown failed\n";
4539 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4544 if ($count >= $timeout) {
4545 warn "VM still running - terminating now with SIGKILL\n";
4550 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4555 my ($vmid, $skiplock) = @_;
4557 lock_config
($vmid, sub {
4559 my $conf = load_config
($vmid);
4561 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4563 vm_mon_cmd
($vmid, "stop");
4568 my ($vmid, $skiplock) = @_;
4570 lock_config
($vmid, sub {
4572 my $conf = load_config
($vmid);
4574 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4576 vm_mon_cmd
($vmid, "cont");
4581 my ($vmid, $skiplock, $key) = @_;
4583 lock_config
($vmid, sub {
4585 my $conf = load_config
($vmid);
4587 # there is no qmp command, so we use the human monitor command
4588 vm_human_monitor_command
($vmid, "sendkey $key");
4593 my ($storecfg, $vmid, $skiplock) = @_;
4595 lock_config
($vmid, sub {
4597 my $conf = load_config
($vmid);
4599 check_lock
($conf) if !$skiplock;
4601 if (!check_running
($vmid)) {
4602 destroy_vm
($storecfg, $vmid);
4604 die "VM $vmid is running - destroy failed\n";
4612 my ($filename, $buf) = @_;
4614 my $fh = IO
::File-
>new($filename, "w");
4615 return undef if !$fh;
4617 my $res = print $fh $buf;
4624 sub pci_device_info
{
4629 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4630 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4632 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4633 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4635 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4636 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4638 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4639 return undef if !defined($product) || $product !~ s/^0x//;
4644 product
=> $product,
4650 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4659 my $name = $dev->{name
};
4661 my $fn = "$pcisysfs/devices/$name/reset";
4663 return file_write
($fn, "1");
4666 sub pci_dev_bind_to_stub
{
4669 my $name = $dev->{name
};
4671 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4672 return 1 if -d
$testdir;
4674 my $data = "$dev->{vendor} $dev->{product}";
4675 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4677 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4678 if (!file_write
($fn, $name)) {
4679 return undef if -f
$fn;
4682 $fn = "$pcisysfs/drivers/pci-stub/bind";
4683 if (! -d
$testdir) {
4684 return undef if !file_write
($fn, $name);
4690 sub pci_dev_bind_to_vfio
{
4693 my $name = $dev->{name
};
4695 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4697 if (!-d
$vfio_basedir) {
4698 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4700 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4702 my $testdir = "$vfio_basedir/$name";
4703 return 1 if -d
$testdir;
4705 my $data = "$dev->{vendor} $dev->{product}";
4706 return undef if !file_write
("$vfio_basedir/new_id", $data);
4708 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4709 if (!file_write
($fn, $name)) {
4710 return undef if -f
$fn;
4713 $fn = "$vfio_basedir/bind";
4714 if (! -d
$testdir) {
4715 return undef if !file_write
($fn, $name);
4721 sub pci_dev_group_bind_to_vfio
{
4724 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4726 if (!-d
$vfio_basedir) {
4727 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4729 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4731 # get IOMMU group devices
4732 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4733 my @devs = grep /^0000:/, readdir($D);
4736 foreach my $pciid (@devs) {
4737 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4739 # pci bridges, switches or root ports are not supported
4740 # they have a pci_bus subdirectory so skip them
4741 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4743 my $info = pci_device_info
($1);
4744 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4750 sub print_pci_addr
{
4751 my ($id, $bridges) = @_;
4755 piix3
=> { bus
=> 0, addr
=> 1 },
4756 #addr2 : first videocard
4757 balloon0
=> { bus
=> 0, addr
=> 3 },
4758 watchdog
=> { bus
=> 0, addr
=> 4 },
4759 scsihw0
=> { bus
=> 0, addr
=> 5 },
4760 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4761 scsihw1
=> { bus
=> 0, addr
=> 6 },
4762 ahci0
=> { bus
=> 0, addr
=> 7 },
4763 qga0
=> { bus
=> 0, addr
=> 8 },
4764 spice
=> { bus
=> 0, addr
=> 9 },
4765 virtio0
=> { bus
=> 0, addr
=> 10 },
4766 virtio1
=> { bus
=> 0, addr
=> 11 },
4767 virtio2
=> { bus
=> 0, addr
=> 12 },
4768 virtio3
=> { bus
=> 0, addr
=> 13 },
4769 virtio4
=> { bus
=> 0, addr
=> 14 },
4770 virtio5
=> { bus
=> 0, addr
=> 15 },
4771 hostpci0
=> { bus
=> 0, addr
=> 16 },
4772 hostpci1
=> { bus
=> 0, addr
=> 17 },
4773 net0
=> { bus
=> 0, addr
=> 18 },
4774 net1
=> { bus
=> 0, addr
=> 19 },
4775 net2
=> { bus
=> 0, addr
=> 20 },
4776 net3
=> { bus
=> 0, addr
=> 21 },
4777 net4
=> { bus
=> 0, addr
=> 22 },
4778 net5
=> { bus
=> 0, addr
=> 23 },
4779 vga1
=> { bus
=> 0, addr
=> 24 },
4780 vga2
=> { bus
=> 0, addr
=> 25 },
4781 vga3
=> { bus
=> 0, addr
=> 26 },
4782 hostpci2
=> { bus
=> 0, addr
=> 27 },
4783 hostpci3
=> { bus
=> 0, addr
=> 28 },
4784 #addr29 : usb-host (pve-usb.cfg)
4785 'pci.1' => { bus
=> 0, addr
=> 30 },
4786 'pci.2' => { bus
=> 0, addr
=> 31 },
4787 'net6' => { bus
=> 1, addr
=> 1 },
4788 'net7' => { bus
=> 1, addr
=> 2 },
4789 'net8' => { bus
=> 1, addr
=> 3 },
4790 'net9' => { bus
=> 1, addr
=> 4 },
4791 'net10' => { bus
=> 1, addr
=> 5 },
4792 'net11' => { bus
=> 1, addr
=> 6 },
4793 'net12' => { bus
=> 1, addr
=> 7 },
4794 'net13' => { bus
=> 1, addr
=> 8 },
4795 'net14' => { bus
=> 1, addr
=> 9 },
4796 'net15' => { bus
=> 1, addr
=> 10 },
4797 'net16' => { bus
=> 1, addr
=> 11 },
4798 'net17' => { bus
=> 1, addr
=> 12 },
4799 'net18' => { bus
=> 1, addr
=> 13 },
4800 'net19' => { bus
=> 1, addr
=> 14 },
4801 'net20' => { bus
=> 1, addr
=> 15 },
4802 'net21' => { bus
=> 1, addr
=> 16 },
4803 'net22' => { bus
=> 1, addr
=> 17 },
4804 'net23' => { bus
=> 1, addr
=> 18 },
4805 'net24' => { bus
=> 1, addr
=> 19 },
4806 'net25' => { bus
=> 1, addr
=> 20 },
4807 'net26' => { bus
=> 1, addr
=> 21 },
4808 'net27' => { bus
=> 1, addr
=> 22 },
4809 'net28' => { bus
=> 1, addr
=> 23 },
4810 'net29' => { bus
=> 1, addr
=> 24 },
4811 'net30' => { bus
=> 1, addr
=> 25 },
4812 'net31' => { bus
=> 1, addr
=> 26 },
4813 'virtio6' => { bus
=> 2, addr
=> 1 },
4814 'virtio7' => { bus
=> 2, addr
=> 2 },
4815 'virtio8' => { bus
=> 2, addr
=> 3 },
4816 'virtio9' => { bus
=> 2, addr
=> 4 },
4817 'virtio10' => { bus
=> 2, addr
=> 5 },
4818 'virtio11' => { bus
=> 2, addr
=> 6 },
4819 'virtio12' => { bus
=> 2, addr
=> 7 },
4820 'virtio13' => { bus
=> 2, addr
=> 8 },
4821 'virtio14' => { bus
=> 2, addr
=> 9 },
4822 'virtio15' => { bus
=> 2, addr
=> 10 },
4823 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4824 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4825 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4826 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4827 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4828 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4829 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4830 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4831 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4832 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4833 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4834 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4835 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4836 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4837 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4838 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4839 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4840 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4841 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4842 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4843 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4844 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4845 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4846 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4847 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4848 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4849 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4850 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4851 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4852 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4853 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4857 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4858 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4859 my $bus = $devices->{$id}->{bus
};
4860 $res = ",bus=pci.$bus,addr=$addr";
4861 $bridges->{$bus} = 1 if $bridges;
4867 sub print_pcie_addr
{
4872 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4873 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4874 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4875 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4878 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4879 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4880 my $bus = $devices->{$id}->{bus
};
4881 $res = ",bus=$bus,addr=$addr";
4887 # vzdump restore implementaion
4889 sub tar_archive_read_firstfile
{
4890 my $archive = shift;
4892 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4894 # try to detect archive type first
4895 my $pid = open (TMP
, "tar tf '$archive'|") ||
4896 die "unable to open file '$archive'\n";
4897 my $firstfile = <TMP
>;
4901 die "ERROR: archive contaions no data\n" if !$firstfile;
4907 sub tar_restore_cleanup
{
4908 my ($storecfg, $statfile) = @_;
4910 print STDERR
"starting cleanup\n";
4912 if (my $fd = IO
::File-
>new($statfile, "r")) {
4913 while (defined(my $line = <$fd>)) {
4914 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4917 if ($volid =~ m
|^/|) {
4918 unlink $volid || die 'unlink failed\n';
4920 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4922 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4924 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4926 print STDERR
"unable to parse line in statfile - $line";
4933 sub restore_archive
{
4934 my ($archive, $vmid, $user, $opts) = @_;
4936 my $format = $opts->{format
};
4939 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4940 $format = 'tar' if !$format;
4942 } elsif ($archive =~ m/\.tar$/) {
4943 $format = 'tar' if !$format;
4944 } elsif ($archive =~ m/.tar.lzo$/) {
4945 $format = 'tar' if !$format;
4947 } elsif ($archive =~ m/\.vma$/) {
4948 $format = 'vma' if !$format;
4949 } elsif ($archive =~ m/\.vma\.gz$/) {
4950 $format = 'vma' if !$format;
4952 } elsif ($archive =~ m/\.vma\.lzo$/) {
4953 $format = 'vma' if !$format;
4956 $format = 'vma' if !$format; # default
4959 # try to detect archive format
4960 if ($format eq 'tar') {
4961 return restore_tar_archive
($archive, $vmid, $user, $opts);
4963 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4967 sub restore_update_config_line
{
4968 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4970 return if $line =~ m/^\#qmdump\#/;
4971 return if $line =~ m/^\#vzdump\#/;
4972 return if $line =~ m/^lock:/;
4973 return if $line =~ m/^unused\d+:/;
4974 return if $line =~ m/^parent:/;
4975 return if $line =~ m/^template:/; # restored VM is never a template
4977 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4978 # try to convert old 1.X settings
4979 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4980 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4981 my ($model, $macaddr) = split(/\=/, $devconfig);
4982 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4985 bridge
=> "vmbr$ind",
4986 macaddr
=> $macaddr,
4988 my $netstr = print_net
($net);
4990 print $outfd "net$cookie->{netcount}: $netstr\n";
4991 $cookie->{netcount
}++;
4993 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4994 my ($id, $netstr) = ($1, $2);
4995 my $net = parse_net
($netstr);
4996 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4997 $netstr = print_net
($net);
4998 print $outfd "$id: $netstr\n";
4999 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5002 if ($line =~ m/backup=no/) {
5003 print $outfd "#$line";
5004 } elsif ($virtdev && $map->{$virtdev}) {
5005 my $di = parse_drive
($virtdev, $value);
5006 delete $di->{format
}; # format can change on restore
5007 $di->{file
} = $map->{$virtdev};
5008 $value = print_drive
($vmid, $di);
5009 print $outfd "$virtdev: $value\n";
5019 my ($cfg, $vmid) = @_;
5021 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5023 my $volid_hash = {};
5024 foreach my $storeid (keys %$info) {
5025 foreach my $item (@{$info->{$storeid}}) {
5026 next if !($item->{volid
} && $item->{size
});
5027 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5028 $volid_hash->{$item->{volid
}} = $item;
5035 sub get_used_paths
{
5036 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5040 my $scan_config = sub {
5041 my ($cref, $snapname) = @_;
5043 foreach my $key (keys %$cref) {
5044 my $value = $cref->{$key};
5045 if (valid_drivename
($key)) {
5046 next if $skip_drive && $key eq $skip_drive;
5047 my $drive = parse_drive
($key, $value);
5048 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5049 if ($drive->{file
} =~ m!^/!) {
5050 $used_path->{$drive->{file
}}++; # = 1;
5052 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5054 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5056 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5057 $used_path->{$path}++; # = 1;
5063 &$scan_config($conf);
5067 if ($scan_snapshots) {
5068 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5069 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5076 sub update_disksize
{
5077 my ($vmid, $conf, $volid_hash) = @_;
5083 # Note: it is allowed to define multiple storages with same path (alias), so
5084 # we need to check both 'volid' and real 'path' (two different volid can point
5085 # to the same path).
5090 foreach my $opt (keys %$conf) {
5091 if (valid_drivename
($opt)) {
5092 my $drive = parse_drive
($opt, $conf->{$opt});
5093 my $volid = $drive->{file
};
5096 $used->{$volid} = 1;
5097 if ($volid_hash->{$volid} &&
5098 (my $path = $volid_hash->{$volid}->{path
})) {
5099 $usedpath->{$path} = 1;
5102 next if drive_is_cdrom
($drive);
5103 next if !$volid_hash->{$volid};
5105 $drive->{size
} = $volid_hash->{$volid}->{size
};
5106 my $new = print_drive
($vmid, $drive);
5107 if ($new ne $conf->{$opt}) {
5109 $conf->{$opt} = $new;
5114 # remove 'unusedX' entry if volume is used
5115 foreach my $opt (keys %$conf) {
5116 next if $opt !~ m/^unused\d+$/;
5117 my $volid = $conf->{$opt};
5118 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5119 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5121 delete $conf->{$opt};
5125 foreach my $volid (sort keys %$volid_hash) {
5126 next if $volid =~ m/vm-$vmid-state-/;
5127 next if $used->{$volid};
5128 my $path = $volid_hash->{$volid}->{path
};
5129 next if !$path; # just to be sure
5130 next if $usedpath->{$path};
5132 add_unused_volume
($conf, $volid);
5133 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5140 my ($vmid, $nolock) = @_;
5142 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5144 my $volid_hash = scan_volids
($cfg, $vmid);
5146 my $updatefn = sub {
5149 my $conf = load_config
($vmid);
5154 foreach my $volid (keys %$volid_hash) {
5155 my $info = $volid_hash->{$volid};
5156 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5159 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5161 update_config_nolock
($vmid, $conf, 1) if $changes;
5164 if (defined($vmid)) {
5168 lock_config
($vmid, $updatefn, $vmid);
5171 my $vmlist = config_list
();
5172 foreach my $vmid (keys %$vmlist) {
5176 lock_config
($vmid, $updatefn, $vmid);
5182 sub restore_vma_archive
{
5183 my ($archive, $vmid, $user, $opts, $comp) = @_;
5185 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5186 my $readfrom = $archive;
5191 my $qarchive = PVE
::Tools
::shellquote
($archive);
5192 if ($comp eq 'gzip') {
5193 $uncomp = "zcat $qarchive|";
5194 } elsif ($comp eq 'lzop') {
5195 $uncomp = "lzop -d -c $qarchive|";
5197 die "unknown compression method '$comp'\n";
5202 my $tmpdir = "/var/tmp/vzdumptmp$$";
5205 # disable interrupts (always do cleanups)
5206 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5207 warn "got interrupt - ignored\n";
5210 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5211 POSIX
::mkfifo
($mapfifo, 0600);
5214 my $openfifo = sub {
5215 open($fifofh, '>', $mapfifo) || die $!;
5218 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5225 my $rpcenv = PVE
::RPCEnvironment
::get
();
5227 my $conffile = config_file
($vmid);
5228 my $tmpfn = "$conffile.$$.tmp";
5230 # Note: $oldconf is undef if VM does not exists
5231 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5233 my $print_devmap = sub {
5234 my $virtdev_hash = {};
5236 my $cfgfn = "$tmpdir/qemu-server.conf";
5238 # we can read the config - that is already extracted
5239 my $fh = IO
::File-
>new($cfgfn, "r") ||
5240 "unable to read qemu-server.conf - $!\n";
5242 while (defined(my $line = <$fh>)) {
5243 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5244 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5245 die "archive does not contain data for drive '$virtdev'\n"
5246 if !$devinfo->{$devname};
5247 if (defined($opts->{storage
})) {
5248 $storeid = $opts->{storage
} || 'local';
5249 } elsif (!$storeid) {
5252 $format = 'raw' if !$format;
5253 $devinfo->{$devname}->{devname
} = $devname;
5254 $devinfo->{$devname}->{virtdev
} = $virtdev;
5255 $devinfo->{$devname}->{format
} = $format;
5256 $devinfo->{$devname}->{storeid
} = $storeid;
5258 # check permission on storage
5259 my $pool = $opts->{pool
}; # todo: do we need that?
5260 if ($user ne 'root@pam') {
5261 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5264 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5268 foreach my $devname (keys %$devinfo) {
5269 die "found no device mapping information for device '$devname'\n"
5270 if !$devinfo->{$devname}->{virtdev
};
5273 my $cfg = cfs_read_file
('storage.cfg');
5275 # create empty/temp config
5277 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5278 foreach_drive
($oldconf, sub {
5279 my ($ds, $drive) = @_;
5281 return if drive_is_cdrom
($drive);
5283 my $volid = $drive->{file
};
5285 return if !$volid || $volid =~ m
|^/|;
5287 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5288 return if !$path || !$owner || ($owner != $vmid);
5290 # Note: only delete disk we want to restore
5291 # other volumes will become unused
5292 if ($virtdev_hash->{$ds}) {
5293 PVE
::Storage
::vdisk_free
($cfg, $volid);
5299 foreach my $virtdev (sort keys %$virtdev_hash) {
5300 my $d = $virtdev_hash->{$virtdev};
5301 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5302 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5304 # test if requested format is supported
5305 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5306 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5307 $d->{format
} = $defFormat if !$supported;
5309 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5310 $d->{format
}, undef, $alloc_size);
5311 print STDERR
"new volume ID is '$volid'\n";
5312 $d->{volid
} = $volid;
5313 my $path = PVE
::Storage
::path
($cfg, $volid);
5315 my $write_zeros = 1;
5316 # fixme: what other storages types initialize volumes with zero?
5317 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5318 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5322 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5324 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5325 $map->{$virtdev} = $volid;
5328 $fh->seek(0, 0) || die "seek failed - $!\n";
5330 my $outfd = new IO
::File
($tmpfn, "w") ||
5331 die "unable to write config for VM $vmid\n";
5333 my $cookie = { netcount
=> 0 };
5334 while (defined(my $line = <$fh>)) {
5335 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5344 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5345 die "interrupted by signal\n";
5347 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5349 $oldtimeout = alarm($timeout);
5356 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5357 my ($dev_id, $size, $devname) = ($1, $2, $3);
5358 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5359 } elsif ($line =~ m/^CTIME: /) {
5360 # we correctly received the vma config, so we can disable
5361 # the timeout now for disk allocation (set to 10 minutes, so
5362 # that we always timeout if something goes wrong)
5365 print $fifofh "done\n";
5366 my $tmp = $oldtimeout || 0;
5367 $oldtimeout = undef;
5373 print "restore vma archive: $cmd\n";
5374 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5378 alarm($oldtimeout) if $oldtimeout;
5386 my $cfg = cfs_read_file
('storage.cfg');
5387 foreach my $devname (keys %$devinfo) {
5388 my $volid = $devinfo->{$devname}->{volid
};
5391 if ($volid =~ m
|^/|) {
5392 unlink $volid || die 'unlink failed\n';
5394 PVE
::Storage
::vdisk_free
($cfg, $volid);
5396 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5398 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5405 rename($tmpfn, $conffile) ||
5406 die "unable to commit configuration file '$conffile'\n";
5408 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5410 eval { rescan
($vmid, 1); };
5414 sub restore_tar_archive
{
5415 my ($archive, $vmid, $user, $opts) = @_;
5417 if ($archive ne '-') {
5418 my $firstfile = tar_archive_read_firstfile
($archive);
5419 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5420 if $firstfile ne 'qemu-server.conf';
5423 my $storecfg = cfs_read_file
('storage.cfg');
5425 # destroy existing data - keep empty config
5426 my $vmcfgfn = config_file
($vmid);
5427 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5429 my $tocmd = "/usr/lib/qemu-server/qmextract";
5431 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5432 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5433 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5434 $tocmd .= ' --info' if $opts->{info
};
5436 # tar option "xf" does not autodetect compression when read from STDIN,
5437 # so we pipe to zcat
5438 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5439 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5441 my $tmpdir = "/var/tmp/vzdumptmp$$";
5444 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5445 local $ENV{VZDUMP_VMID
} = $vmid;
5446 local $ENV{VZDUMP_USER
} = $user;
5448 my $conffile = config_file
($vmid);
5449 my $tmpfn = "$conffile.$$.tmp";
5451 # disable interrupts (always do cleanups)
5452 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5453 print STDERR
"got interrupt - ignored\n";
5458 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5459 die "interrupted by signal\n";
5462 if ($archive eq '-') {
5463 print "extracting archive from STDIN\n";
5464 run_command
($cmd, input
=> "<&STDIN");
5466 print "extracting archive '$archive'\n";
5470 return if $opts->{info
};
5474 my $statfile = "$tmpdir/qmrestore.stat";
5475 if (my $fd = IO
::File-
>new($statfile, "r")) {
5476 while (defined (my $line = <$fd>)) {
5477 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5478 $map->{$1} = $2 if $1;
5480 print STDERR
"unable to parse line in statfile - $line\n";
5486 my $confsrc = "$tmpdir/qemu-server.conf";
5488 my $srcfd = new IO
::File
($confsrc, "r") ||
5489 die "unable to open file '$confsrc'\n";
5491 my $outfd = new IO
::File
($tmpfn, "w") ||
5492 die "unable to write config for VM $vmid\n";
5494 my $cookie = { netcount
=> 0 };
5495 while (defined (my $line = <$srcfd>)) {
5496 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5508 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5515 rename $tmpfn, $conffile ||
5516 die "unable to commit configuration file '$conffile'\n";
5518 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5520 eval { rescan
($vmid, 1); };
5525 # Internal snapshots
5527 # NOTE: Snapshot create/delete involves several non-atomic
5528 # action, and can take a long time.
5529 # So we try to avoid locking the file and use 'lock' variable
5530 # inside the config file instead.
5532 my $snapshot_copy_config = sub {
5533 my ($source, $dest) = @_;
5535 foreach my $k (keys %$source) {
5536 next if $k eq 'snapshots';
5537 next if $k eq 'snapstate';
5538 next if $k eq 'snaptime';
5539 next if $k eq 'vmstate';
5540 next if $k eq 'lock';
5541 next if $k eq 'digest';
5542 next if $k eq 'description';
5543 next if $k =~ m/^unused\d+$/;
5545 $dest->{$k} = $source->{$k};
5549 my $snapshot_apply_config = sub {
5550 my ($conf, $snap) = @_;
5552 # copy snapshot list
5554 snapshots
=> $conf->{snapshots
},
5557 # keep description and list of unused disks
5558 foreach my $k (keys %$conf) {
5559 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5560 $newconf->{$k} = $conf->{$k};
5563 &$snapshot_copy_config($snap, $newconf);
5568 sub foreach_writable_storage
{
5569 my ($conf, $func) = @_;
5573 foreach my $ds (keys %$conf) {
5574 next if !valid_drivename
($ds);
5576 my $drive = parse_drive
($ds, $conf->{$ds});
5578 next if drive_is_cdrom
($drive);
5580 my $volid = $drive->{file
};
5582 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5583 $sidhash->{$sid} = $sid if $sid;
5586 foreach my $sid (sort keys %$sidhash) {
5591 my $alloc_vmstate_volid = sub {
5592 my ($storecfg, $vmid, $conf, $snapname) = @_;
5594 # Note: we try to be smart when selecting a $target storage
5598 # search shared storage first
5599 foreach_writable_storage
($conf, sub {
5601 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5602 return if !$scfg->{shared
};
5604 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5608 # now search local storage
5609 foreach_writable_storage
($conf, sub {
5611 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5612 return if $scfg->{shared
};
5614 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5618 $target = 'local' if !$target;
5620 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5621 # we abort live save after $conf->{memory}, so we need at max twice that space
5622 my $size = $conf->{memory
}*2 + $driver_state_size;
5624 my $name = "vm-$vmid-state-$snapname";
5625 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5626 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5627 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5632 my $snapshot_prepare = sub {
5633 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5637 my $updatefn = sub {
5639 my $conf = load_config
($vmid);
5641 die "you can't take a snapshot if it's a template\n"
5642 if is_template
($conf);
5646 $conf->{lock} = 'snapshot';
5648 die "snapshot name '$snapname' already used\n"
5649 if defined($conf->{snapshots
}->{$snapname});
5651 my $storecfg = PVE
::Storage
::config
();
5652 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5654 $snap = $conf->{snapshots
}->{$snapname} = {};
5656 if ($save_vmstate && check_running
($vmid)) {
5657 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5660 &$snapshot_copy_config($conf, $snap);
5662 $snap->{snapstate
} = "prepare";
5663 $snap->{snaptime
} = time();
5664 $snap->{description
} = $comment if $comment;
5666 # always overwrite machine if we save vmstate. This makes sure we
5667 # can restore it later using correct machine type
5668 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5670 update_config_nolock
($vmid, $conf, 1);
5673 lock_config
($vmid, $updatefn);
5678 my $snapshot_commit = sub {
5679 my ($vmid, $snapname) = @_;
5681 my $updatefn = sub {
5683 my $conf = load_config
($vmid);
5685 die "missing snapshot lock\n"
5686 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5688 my $has_machine_config = defined($conf->{machine
});
5690 my $snap = $conf->{snapshots
}->{$snapname};
5692 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5694 die "wrong snapshot state\n"
5695 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5697 delete $snap->{snapstate
};
5698 delete $conf->{lock};
5700 my $newconf = &$snapshot_apply_config($conf, $snap);
5702 delete $newconf->{machine
} if !$has_machine_config;
5704 $newconf->{parent
} = $snapname;
5706 update_config_nolock
($vmid, $newconf, 1);
5709 lock_config
($vmid, $updatefn);
5712 sub snapshot_rollback
{
5713 my ($vmid, $snapname) = @_;
5717 my $storecfg = PVE
::Storage
::config
();
5719 my $conf = load_config
($vmid);
5721 my $get_snapshot_config = sub {
5723 die "you can't rollback if vm is a template\n" if is_template
($conf);
5725 my $res = $conf->{snapshots
}->{$snapname};
5727 die "snapshot '$snapname' does not exist\n" if !defined($res);
5732 my $snap = &$get_snapshot_config();
5734 foreach_drive
($snap, sub {
5735 my ($ds, $drive) = @_;
5737 return if drive_is_cdrom
($drive);
5739 my $volid = $drive->{file
};
5741 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5744 my $updatefn = sub {
5746 $conf = load_config
($vmid);
5748 $snap = &$get_snapshot_config();
5750 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5751 if $snap->{snapstate
};
5755 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5758 die "unable to rollback vm $vmid: vm is running\n"
5759 if check_running
($vmid);
5762 $conf->{lock} = 'rollback';
5764 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5765 delete $conf->{lock};
5771 my $has_machine_config = defined($conf->{machine
});
5773 # copy snapshot config to current config
5774 $conf = &$snapshot_apply_config($conf, $snap);
5775 $conf->{parent
} = $snapname;
5777 # Note: old code did not store 'machine', so we try to be smart
5778 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5779 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5780 # we remove the 'machine' configuration if not explicitly specified
5781 # in the original config.
5782 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5785 update_config_nolock
($vmid, $conf, 1);
5787 if (!$prepare && $snap->{vmstate
}) {
5788 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5789 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5793 lock_config
($vmid, $updatefn);
5795 foreach_drive
($snap, sub {
5796 my ($ds, $drive) = @_;
5798 return if drive_is_cdrom
($drive);
5800 my $volid = $drive->{file
};
5801 my $device = "drive-$ds";
5803 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5807 lock_config
($vmid, $updatefn);
5810 my $savevm_wait = sub {
5814 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5815 if (!$stat->{status
}) {
5816 die "savevm not active\n";
5817 } elsif ($stat->{status
} eq 'active') {
5820 } elsif ($stat->{status
} eq 'completed') {
5823 die "query-savevm returned status '$stat->{status}'\n";
5828 sub do_snapshots_with_qemu
{
5829 my ($storecfg, $volid) = @_;
5831 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5833 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5837 if ($volid =~ m/\.(qcow2|qed)$/){
5844 sub snapshot_create
{
5845 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5847 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5849 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5851 my $config = load_config
($vmid);
5853 my $running = check_running
($vmid);
5855 my $freezefs = $running && $config->{agent
};
5856 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5861 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5862 warn "guest-fsfreeze-freeze problems - $@" if $@;
5866 # create internal snapshots of all drives
5868 my $storecfg = PVE
::Storage
::config
();
5871 if ($snap->{vmstate
}) {
5872 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5873 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5874 &$savevm_wait($vmid);
5876 vm_mon_cmd
($vmid, "savevm-start");
5880 foreach_drive
($snap, sub {
5881 my ($ds, $drive) = @_;
5883 return if drive_is_cdrom
($drive);
5885 my $volid = $drive->{file
};
5886 my $device = "drive-$ds";
5888 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5889 $drivehash->{$ds} = 1;
5895 eval { vm_mon_cmd
($vmid, "savevm-end") };
5899 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5900 warn "guest-fsfreeze-thaw problems - $@" if $@;
5903 # savevm-end is async, we need to wait
5905 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5906 if (!$stat->{bytes
}) {
5909 print "savevm not yet finished\n";
5917 warn "snapshot create failed: starting cleanup\n";
5918 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5923 &$snapshot_commit($vmid, $snapname);
5926 # Note: $drivehash is only set when called from snapshot_create.
5927 sub snapshot_delete
{
5928 my ($vmid, $snapname, $force, $drivehash) = @_;
5935 my $unlink_parent = sub {
5936 my ($confref, $new_parent) = @_;
5938 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5940 $confref->{parent
} = $new_parent;
5942 delete $confref->{parent
};
5947 my $updatefn = sub {
5948 my ($remove_drive) = @_;
5950 my $conf = load_config
($vmid);
5954 die "you can't delete a snapshot if vm is a template\n"
5955 if is_template
($conf);
5958 $snap = $conf->{snapshots
}->{$snapname};
5960 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5962 # remove parent refs
5964 &$unlink_parent($conf, $snap->{parent
});
5965 foreach my $sn (keys %{$conf->{snapshots
}}) {
5966 next if $sn eq $snapname;
5967 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5971 if ($remove_drive) {
5972 if ($remove_drive eq 'vmstate') {
5973 delete $snap->{$remove_drive};
5975 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5976 my $volid = $drive->{file
};
5977 delete $snap->{$remove_drive};
5978 add_unused_volume
($conf, $volid);
5983 $snap->{snapstate
} = 'delete';
5985 delete $conf->{snapshots
}->{$snapname};
5986 delete $conf->{lock} if $drivehash;
5987 foreach my $volid (@$unused) {
5988 add_unused_volume
($conf, $volid);
5992 update_config_nolock
($vmid, $conf, 1);
5995 lock_config
($vmid, $updatefn);
5997 # now remove vmstate file
5999 my $storecfg = PVE
::Storage
::config
();
6001 if ($snap->{vmstate
}) {
6002 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6004 die $err if !$force;
6007 # save changes (remove vmstate from snapshot)
6008 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6011 # now remove all internal snapshots
6012 foreach_drive
($snap, sub {
6013 my ($ds, $drive) = @_;
6015 return if drive_is_cdrom
($drive);
6017 my $volid = $drive->{file
};
6018 my $device = "drive-$ds";
6020 if (!$drivehash || $drivehash->{$ds}) {
6021 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6023 die $err if !$force;
6028 # save changes (remove drive fron snapshot)
6029 lock_config
($vmid, $updatefn, $ds) if !$force;
6030 push @$unused, $volid;
6033 # now cleanup config
6035 lock_config
($vmid, $updatefn);
6039 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6042 foreach_drive
($conf, sub {
6043 my ($ds, $drive) = @_;
6045 return if drive_is_cdrom
($drive);
6046 my $volid = $drive->{file
};
6047 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6050 return $err ?
0 : 1;
6053 sub template_create
{
6054 my ($vmid, $conf, $disk) = @_;
6056 my $storecfg = PVE
::Storage
::config
();
6058 foreach_drive
($conf, sub {
6059 my ($ds, $drive) = @_;
6061 return if drive_is_cdrom
($drive);
6062 return if $disk && $ds ne $disk;
6064 my $volid = $drive->{file
};
6065 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6067 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6068 $drive->{file
} = $voliddst;
6069 $conf->{$ds} = print_drive
($vmid, $drive);
6070 update_config_nolock
($vmid, $conf, 1);
6077 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6080 sub qemu_img_convert
{
6081 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6083 my $storecfg = PVE
::Storage
::config
();
6084 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6085 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6087 if ($src_storeid && $dst_storeid) {
6088 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6089 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6091 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6092 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6094 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6095 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6098 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6099 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6100 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6104 if($line =~ m/\((\S+)\/100\
%\)/){
6106 my $transferred = int($size * $percent / 100);
6107 my $remaining = $size - $transferred;
6109 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6114 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6116 die "copy failed: $err" if $err;
6120 sub qemu_img_format
{
6121 my ($scfg, $volname) = @_;
6123 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6130 sub qemu_drive_mirror
{
6131 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6133 my $storecfg = PVE
::Storage
::config
();
6134 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6136 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6138 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6140 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6142 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6143 $opts->{format
} = $format if $format;
6145 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6148 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6150 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6151 my $stat = @$stats[0];
6152 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6153 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6155 my $busy = $stat->{busy
};
6156 my $ready = $stat->{ready
};
6158 if (my $total = $stat->{len
}) {
6159 my $transferred = $stat->{offset
} || 0;
6160 my $remaining = $total - $transferred;
6161 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6163 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6167 if ($stat->{ready
} eq 'true') {
6169 last if $vmiddst != $vmid;
6171 # try to switch the disk if source and destination are on the same guest
6172 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6174 die $@ if $@ !~ m/cannot be completed/;
6183 my $cancel_job = sub {
6184 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6186 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6187 my $stat = @$stats[0];
6194 eval { &$cancel_job(); };
6195 die "mirroring error: $err";
6198 if ($vmiddst != $vmid) {
6199 # if we clone a disk for a new target vm, we don't switch the disk
6200 &$cancel_job(); # so we call block-job-cancel
6205 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6206 $newvmid, $storage, $format, $full, $newvollist) = @_;
6211 print "create linked clone of drive $drivename ($drive->{file})\n";
6212 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6213 push @$newvollist, $newvolid;
6215 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6216 $storeid = $storage if $storage;
6218 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6220 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6221 $format = qemu_img_format
($scfg, $volname);
6224 # test if requested format is supported - else use default
6225 my $supported = grep { $_ eq $format } @$validFormats;
6226 $format = $defFormat if !$supported;
6228 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6230 print "create full clone of drive $drivename ($drive->{file})\n";
6231 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6232 push @$newvollist, $newvolid;
6234 if (!$running || $snapname) {
6235 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6237 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6241 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6244 $disk->{format
} = undef;
6245 $disk->{file
} = $newvolid;
6246 $disk->{size
} = $size;
6251 # this only works if VM is running
6252 sub get_current_qemu_machine
{
6255 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6256 my $res = vm_qmp_command
($vmid, $cmd);
6258 my ($current, $default);
6259 foreach my $e (@$res) {
6260 $default = $e->{name
} if $e->{'is-default'};
6261 $current = $e->{name
} if $e->{'is-current'};
6264 # fallback to the default machine if current is not supported by qemu
6265 return $current || $default || 'pc';
6268 sub qemu_machine_feature_enabled
{
6269 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6274 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6276 $current_major = $3;
6277 $current_minor = $4;
6279 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6281 $current_major = $1;
6282 $current_minor = $2;
6285 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6294 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6295 my (undef, $id, $function) = @_;
6296 my $res = { id
=> $id, function
=> $function};
6297 push @{$devices->{$id}}, $res;
6303 sub vm_iothreads_list
{
6306 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6309 foreach my $iothread (@$res) {
6310 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6317 my ($conf, $drive) = @_;
6321 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6323 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6329 my $controller = int($drive->{index} / $maxdev);
6330 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6332 return ($maxdev, $controller, $controller_prefix);