1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
36 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
38 # Note about locking: we use flock on the config file protect
39 # against concurent actions.
40 # Aditionaly, we have a 'lock' setting in the config file. This
41 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
42 # allowed when such lock is set. But you can ignore this kind of
43 # lock with the --skiplock flag.
45 cfs_register_file
('/qemu-server/',
49 PVE
::JSONSchema
::register_standard_option
('skiplock', {
50 description
=> "Ignore locks - only root is allowed to use this option.",
55 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
56 description
=> "Some command save/restore state from this location.",
62 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
63 description
=> "The name of the snapshot.",
64 type
=> 'string', format
=> 'pve-configid',
68 #no warnings 'redefine';
71 my ($controller, $vmid, $option, $value) = @_;
73 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
74 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
78 my $nodename = PVE
::INotify
::nodename
();
80 mkdir "/etc/pve/nodes/$nodename";
81 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
84 my $var_run_tmpdir = "/var/run/qemu-server";
85 mkdir $var_run_tmpdir;
87 my $lock_dir = "/var/lock/qemu-server";
90 my $pcisysfs = "/sys/bus/pci";
96 description
=> "Specifies whether a VM will be started during system bootup.",
102 description
=> "Automatic restart after crash (currently ignored).",
107 type
=> 'string', format
=> 'pve-hotplug-features',
108 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
109 default => 'network,disk,usb',
114 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
120 description
=> "Lock/unlock the VM.",
121 enum
=> [qw(migrate backup snapshot rollback)],
126 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
134 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
142 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
149 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
155 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
163 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
164 enum
=> PVE
::Tools
::kvmkeymaplist
(),
169 type
=> 'string', format
=> 'dns-name',
170 description
=> "Set a name for the VM. Only used on the configuration web interface.",
175 description
=> "scsi controller model",
176 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
182 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
187 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
188 description
=> <<EODESC,
189 Used to enable special optimization/features for specific
192 other => unspecified OS
193 wxp => Microsoft Windows XP
194 w2k => Microsoft Windows 2000
195 w2k3 => Microsoft Windows 2003
196 w2k8 => Microsoft Windows 2008
197 wvista => Microsoft Windows Vista
198 win7 => Microsoft Windows 7
199 win8 => Microsoft Windows 8/2012
200 l24 => Linux 2.4 Kernel
201 l26 => Linux 2.6/3.X Kernel
202 solaris => solaris/opensolaris/openindiania kernel
204 other|l24|l26|solaris ... no special behaviour
205 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
211 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
212 pattern
=> '[acdn]{1,4}',
217 type
=> 'string', format
=> 'pve-qm-bootdisk',
218 description
=> "Enable booting from specified disk.",
219 pattern
=> '(ide|sata|scsi|virtio)\d+',
224 description
=> "The number of CPUs. Please use option -sockets instead.",
231 description
=> "The number of CPU sockets.",
238 description
=> "The number of cores per socket.",
245 description
=> "Enable/disable Numa.",
251 description
=> "Number of hotplugged vcpus.",
258 description
=> "Enable/disable ACPI.",
264 description
=> "Enable/disable Qemu GuestAgent.",
270 description
=> "Enable/disable KVM hardware virtualization.",
276 description
=> "Enable/disable time drift fix.",
282 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
287 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
292 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
293 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
297 type
=> 'string', format
=> 'pve-qm-watchdog',
298 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
299 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
304 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
305 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
306 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
309 startup
=> get_standard_option
('pve-startup-order'),
313 description
=> "Enable/disable Template.",
319 description
=> <<EODESCR,
320 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
322 args: -no-reboot -no-hpet
329 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
334 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
338 migrate_downtime
=> {
341 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
347 type
=> 'string', format
=> 'pve-qm-drive',
348 typetext
=> 'volume',
349 description
=> "This is an alias for option -ide2",
353 description
=> "Emulated CPU type.",
355 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
358 parent
=> get_standard_option
('pve-snapshot-name', {
360 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
364 description
=> "Timestamp for snapshots.",
370 type
=> 'string', format
=> 'pve-volume-id',
371 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
374 description
=> "Specific the Qemu machine type.",
376 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
381 description
=> "Specify SMBIOS type 1 fields.",
382 type
=> 'string', format
=> 'pve-qm-smbios1',
383 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
389 # what about other qemu settings ?
391 #machine => 'string',
404 ##soundhw => 'string',
406 while (my ($k, $v) = each %$confdesc) {
407 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
410 my $MAX_IDE_DISKS = 4;
411 my $MAX_SCSI_DISKS = 14;
412 my $MAX_VIRTIO_DISKS = 16;
413 my $MAX_SATA_DISKS = 6;
414 my $MAX_USB_DEVICES = 5;
416 my $MAX_UNUSED_DISKS = 8;
417 my $MAX_HOSTPCI_DEVICES = 4;
418 my $MAX_SERIAL_PORTS = 4;
419 my $MAX_PARALLEL_PORTS = 3;
421 my $MAX_MEM = 4194304;
422 my $STATICMEM = 1024;
426 type
=> 'string', format
=> 'pve-qm-numanode',
427 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
428 description
=> "numa topology",
430 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
432 for (my $i = 0; $i < $MAX_NUMA; $i++) {
433 $confdesc->{"numa$i"} = $numadesc;
436 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
437 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
438 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
439 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
443 type
=> 'string', format
=> 'pve-qm-net',
444 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
445 description
=> <<EODESCR,
446 Specify network devices.
448 MODEL is one of: $nic_model_list_txt
450 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
451 automatically generated if not specified.
453 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
455 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
457 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
463 The DHCP server assign addresses to the guest starting from 10.0.2.15.
467 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
469 for (my $i = 0; $i < $MAX_NETS; $i++) {
470 $confdesc->{"net$i"} = $netdesc;
477 type
=> 'string', format
=> 'pve-qm-drive',
478 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
479 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
481 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
485 type
=> 'string', format
=> 'pve-qm-drive',
486 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,queues=<nbqueues>]',
487 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
489 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
493 type
=> 'string', format
=> 'pve-qm-drive',
494 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
495 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
497 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
501 type
=> 'string', format
=> 'pve-qm-drive',
502 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on]',
503 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
505 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
509 type
=> 'string', format
=> 'pve-qm-usb-device',
510 typetext
=> 'host=HOSTUSBDEVICE|spice',
511 description
=> <<EODESCR,
512 Configure an USB device (n is 0 to 4). This can be used to
513 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
515 'bus-port(.port)*' (decimal numbers) or
516 'vendor_id:product_id' (hexadeciaml numbers)
518 You can use the 'lsusb -t' command to list existing usb devices.
520 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
522 The value 'spice' can be used to add a usb redirection devices for spice.
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
530 type
=> 'string', format
=> 'pve-qm-hostpci',
531 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
532 description
=> <<EODESCR,
533 Map host pci devices. HOSTPCIDEVICE syntax is:
535 'bus:dev.func' (hexadecimal numbers)
537 You can us the 'lspci' command to list existing pci devices.
539 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
541 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
543 Experimental: user reported problems with this option.
546 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
551 pattern
=> '(/dev/.+|socket)',
552 description
=> <<EODESCR,
553 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
555 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
557 Experimental: user reported problems with this option.
564 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
565 description
=> <<EODESCR,
566 Map host parallel devices (n is 0 to 2).
568 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
570 Experimental: user reported problems with this option.
574 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
575 $confdesc->{"parallel$i"} = $paralleldesc;
578 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
579 $confdesc->{"serial$i"} = $serialdesc;
582 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
583 $confdesc->{"hostpci$i"} = $hostpcidesc;
586 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
587 $drivename_hash->{"ide$i"} = 1;
588 $confdesc->{"ide$i"} = $idedesc;
591 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
592 $drivename_hash->{"sata$i"} = 1;
593 $confdesc->{"sata$i"} = $satadesc;
596 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
597 $drivename_hash->{"scsi$i"} = 1;
598 $confdesc->{"scsi$i"} = $scsidesc ;
601 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
602 $drivename_hash->{"virtio$i"} = 1;
603 $confdesc->{"virtio$i"} = $virtiodesc;
606 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
607 $confdesc->{"usb$i"} = $usbdesc;
612 type
=> 'string', format
=> 'pve-volume-id',
613 description
=> "Reference to unused volumes.",
616 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
617 $confdesc->{"unused$i"} = $unuseddesc;
620 my $kvm_api_version = 0;
624 return $kvm_api_version if $kvm_api_version;
626 my $fh = IO
::File-
>new("</dev/kvm") ||
629 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
630 $kvm_api_version = $v;
635 return $kvm_api_version;
638 my $kvm_user_version;
640 sub kvm_user_version
{
642 return $kvm_user_version if $kvm_user_version;
644 $kvm_user_version = 'unknown';
646 my $tmp = `kvm -help 2>/dev/null`;
648 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
649 $kvm_user_version = $2;
652 return $kvm_user_version;
656 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
659 # order is important - used to autoselect boot disk
660 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
661 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
662 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
663 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
666 sub valid_drivename
{
669 return defined($drivename_hash->{$dev});
674 return defined($confdesc->{$key});
678 return $nic_model_list;
681 sub os_list_description
{
686 w2k
=> 'Windows 2000',
687 w2k3
=>, 'Windows 2003',
688 w2k8
=> 'Windows 2008',
689 wvista
=> 'Windows Vista',
691 win8
=> 'Windows 8/2012',
701 return $cdrom_path if $cdrom_path;
703 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
704 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
705 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
709 my ($storecfg, $vmid, $cdrom) = @_;
711 if ($cdrom eq 'cdrom') {
712 return get_cdrom_path
();
713 } elsif ($cdrom eq 'none') {
715 } elsif ($cdrom =~ m
|^/|) {
718 return PVE
::Storage
::path
($storecfg, $cdrom);
722 # try to convert old style file names to volume IDs
723 sub filename_to_volume_id
{
724 my ($vmid, $file, $media) = @_;
726 if (!($file eq 'none' || $file eq 'cdrom' ||
727 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
729 return undef if $file =~ m
|/|;
731 if ($media && $media eq 'cdrom') {
732 $file = "local:iso/$file";
734 $file = "local:$vmid/$file";
741 sub verify_media_type
{
742 my ($opt, $vtype, $media) = @_;
747 if ($media eq 'disk') {
749 } elsif ($media eq 'cdrom') {
752 die "internal error";
755 return if ($vtype eq $etype);
757 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
760 sub cleanup_drive_path
{
761 my ($opt, $storecfg, $drive) = @_;
763 # try to convert filesystem paths to volume IDs
765 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
766 ($drive->{file
} !~ m
|^/dev/.+|) &&
767 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
768 ($drive->{file
} !~ m/^\d+$/)) {
769 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
770 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
771 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
772 verify_media_type
($opt, $vtype, $drive->{media
});
773 $drive->{file
} = $volid;
776 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
779 sub create_conf_nolock
{
780 my ($vmid, $settings) = @_;
782 my $filename = config_file
($vmid);
784 die "configuration file '$filename' already exists\n" if -f
$filename;
786 my $defaults = load_defaults
();
788 $settings->{name
} = "vm$vmid" if !$settings->{name
};
789 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
792 foreach my $opt (keys %$settings) {
793 next if !$confdesc->{$opt};
795 my $value = $settings->{$opt};
798 $data .= "$opt: $value\n";
801 PVE
::Tools
::file_set_contents
($filename, $data);
804 sub parse_hotplug_features
{
809 return $res if $data eq '0';
811 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
813 foreach my $feature (PVE
::Tools
::split_list
($data)) {
814 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
817 warn "ignoring unknown hotplug feature '$feature'\n";
823 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
824 sub pve_verify_hotplug_features
{
825 my ($value, $noerr) = @_;
827 return $value if parse_hotplug_features
($value);
829 return undef if $noerr;
831 die "unable to parse hotplug option\n";
834 my $parse_size = sub {
837 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
838 my ($size, $unit) = ($1, $3);
841 $size = $size * 1024;
842 } elsif ($unit eq 'M') {
843 $size = $size * 1024 * 1024;
844 } elsif ($unit eq 'G') {
845 $size = $size * 1024 * 1024 * 1024;
851 my $format_size = sub {
856 my $kb = int($size/1024);
857 return $size if $kb*1024 != $size;
859 my $mb = int($kb/1024);
860 return "${kb}K" if $mb*1024 != $kb;
862 my $gb = int($mb/1024);
863 return "${mb}M" if $gb*1024 != $mb;
868 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
869 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
870 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
871 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
874 my ($key, $data) = @_;
878 # $key may be undefined - used to verify JSON parameters
879 if (!defined($key)) {
880 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
882 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
883 $res->{interface
} = $1;
889 foreach my $p (split (/,/, $data)) {
890 next if $p =~ m/^\s*$/;
892 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues)=(.+)$/) {
893 my ($k, $v) = ($1, $2);
895 $k = 'file' if $k eq 'volume';
897 return undef if defined $res->{$k};
899 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
900 return undef if !$v || $v !~ m/^\d+/;
902 $v = sprintf("%.3f", $v / (1024*1024));
906 if (!$res->{file
} && $p !~ m/=/) {
914 return undef if !$res->{file
};
916 return undef if $res->{cache
} &&
917 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
918 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
919 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
920 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
921 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
922 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
923 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
924 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
925 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
926 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
927 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
928 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
929 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
930 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
931 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
933 return undef if $res->{mbps_rd
} && $res->{mbps
};
934 return undef if $res->{mbps_wr
} && $res->{mbps
};
936 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
937 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
938 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
939 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
940 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
941 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
943 return undef if $res->{iops_rd
} && $res->{iops
};
944 return undef if $res->{iops_wr
} && $res->{iops
};
947 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
948 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
949 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
950 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
951 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
952 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
956 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
959 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
960 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
961 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
962 return undef if $res->{interface
} eq 'virtio';
965 # rerror does not work with scsi drives
966 if ($res->{rerror
}) {
967 return undef if $res->{interface
} eq 'scsi';
973 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
976 my ($vmid, $drive) = @_;
979 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
980 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
983 if ($drive->{size
}) {
984 $opts .= ",size=" . &$format_size($drive->{size
});
987 return "$drive->{file}$opts";
991 my($fh, $noerr) = @_;
994 my $SG_GET_VERSION_NUM = 0x2282;
996 my $versionbuf = "\x00" x
8;
997 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
999 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1002 my $version = unpack("I", $versionbuf);
1003 if ($version < 30000) {
1004 die "scsi generic interface too old\n" if !$noerr;
1008 my $buf = "\x00" x
36;
1009 my $sensebuf = "\x00" x
8;
1010 my $cmd = pack("C x3 C x1", 0x12, 36);
1012 # see /usr/include/scsi/sg.h
1013 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1015 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1016 length($sensebuf), 0, length($buf), $buf,
1017 $cmd, $sensebuf, 6000);
1019 $ret = ioctl($fh, $SG_IO, $packet);
1021 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1025 my @res = unpack($sg_io_hdr_t, $packet);
1026 if ($res[17] || $res[18]) {
1027 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1032 (my $byte0, my $byte1, $res->{vendor
},
1033 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1035 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1036 $res->{type
} = $byte0 & 31;
1044 my $fh = IO
::File-
>new("+<$path") || return undef;
1045 my $res = scsi_inquiry
($fh, 1);
1051 sub machine_type_is_q35
{
1054 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1057 sub print_tabletdevice_full
{
1060 my $q35 = machine_type_is_q35
($conf);
1062 # we use uhci for old VMs because tablet driver was buggy in older qemu
1063 my $usbbus = $q35 ?
"ehci" : "uhci";
1065 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1068 sub print_drivedevice_full
{
1069 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1074 if ($drive->{interface
} eq 'virtio') {
1075 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1076 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1077 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1078 } elsif ($drive->{interface
} eq 'scsi') {
1080 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1081 my $unit = $drive->{index} % $maxdev;
1082 my $devicetype = 'hd';
1084 if (drive_is_cdrom
($drive)) {
1087 if ($drive->{file
} =~ m
|^/|) {
1088 $path = $drive->{file
};
1090 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1093 if($path =~ m/^iscsi\:\/\
//){
1094 $devicetype = 'generic';
1096 if (my $info = path_is_scsi
($path)) {
1097 if ($info->{type
} == 0) {
1098 $devicetype = 'block';
1099 } elsif ($info->{type
} == 1) { # tape
1100 $devicetype = 'generic';
1106 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1107 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1109 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1112 } elsif ($drive->{interface
} eq 'ide'){
1114 my $controller = int($drive->{index} / $maxdev);
1115 my $unit = $drive->{index} % $maxdev;
1116 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1118 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 } elsif ($drive->{interface
} eq 'sata'){
1120 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1121 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1122 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1123 } elsif ($drive->{interface
} eq 'usb') {
1125 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1127 die "unsupported interface type";
1130 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1135 sub get_initiator_name
{
1138 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1139 while (defined(my $line = <$fh>)) {
1140 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1149 sub print_drive_full
{
1150 my ($storecfg, $vmid, $drive) = @_;
1153 my $volid = $drive->{file
};
1156 if (drive_is_cdrom
($drive)) {
1157 $path = get_iso_path
($storecfg, $vmid, $volid);
1159 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1161 $path = PVE
::Storage
::path
($storecfg, $volid);
1162 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1163 $format = qemu_img_format
($scfg, $volname);
1170 foreach my $o (@qemu_drive_options) {
1171 next if $o eq 'bootindex';
1172 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1175 $opts .= ",format=$format" if $format && !$drive->{format
};
1177 foreach my $o (qw(bps bps_rd bps_wr)) {
1178 my $v = $drive->{"m$o"};
1179 $opts .= ",$o=" . int($v*1024*1024) if $v;
1182 my $cache_direct = 0;
1184 if (my $cache = $drive->{cache
}) {
1185 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1186 } elsif (!drive_is_cdrom
($drive)) {
1187 $opts .= ",cache=none";
1191 # aio native works only with O_DIRECT
1192 if (!$drive->{aio
}) {
1194 $opts .= ",aio=native";
1196 $opts .= ",aio=threads";
1200 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1201 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1203 my $pathinfo = $path ?
"file=$path," : '';
1205 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1208 sub print_netdevice_full
{
1209 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1211 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1213 my $device = $net->{model
};
1214 if ($net->{model
} eq 'virtio') {
1215 $device = 'virtio-net-pci';
1218 my $pciaddr = print_pci_addr
("$netid", $bridges);
1219 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1220 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1221 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1222 my $vectors = $net->{queues
} * 2 + 2;
1223 $tmpstr .= ",vectors=$vectors,mq=on";
1225 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1229 sub print_netdev_full
{
1230 my ($vmid, $conf, $net, $netid) = @_;
1233 if ($netid =~ m/^net(\d+)$/) {
1237 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1239 my $ifname = "tap${vmid}i$i";
1241 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1242 die "interface name '$ifname' is too long (max 15 character)\n"
1243 if length($ifname) >= 16;
1245 my $vhostparam = '';
1246 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1248 my $vmname = $conf->{name
} || "vm$vmid";
1252 if ($net->{bridge
}) {
1253 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1255 $netdev = "type=user,id=$netid,hostname=$vmname";
1258 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1263 sub drive_is_cdrom
{
1266 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1275 foreach my $kvp (split(/,/, $data)) {
1277 if ($kvp =~ m/^memory=(\S+)$/) {
1278 $res->{memory
} = $1;
1279 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1280 $res->{policy
} = $1;
1281 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1282 $res->{cpus
}->{start
} = $1;
1283 $res->{cpus
}->{end
} = $3;
1284 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1285 $res->{hostnodes
}->{start
} = $1;
1286 $res->{hostnodes
}->{end
} = $3;
1298 return undef if !$value;
1301 my @list = split(/,/, $value);
1305 foreach my $kv (@list) {
1307 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1310 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1313 my $pcidevices = lspci
($2);
1314 $res->{pciid
} = $pcidevices->{$2};
1316 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1317 $res->{driver
} = $1;
1318 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1319 $res->{rombar
} = $1;
1320 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1321 $res->{'x-vga'} = $1;
1322 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1323 $res->{pcie
} = 1 if $1 == 1;
1325 warn "unknown hostpci setting '$kv'\n";
1329 return undef if !$found;
1334 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1340 foreach my $kvp (split(/,/, $data)) {
1342 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1344 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1345 $res->{model
} = $model;
1346 $res->{macaddr
} = $mac;
1347 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1348 $res->{bridge
} = $1;
1349 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1350 $res->{queues
} = $1;
1351 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1353 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1355 } elsif ($kvp =~ m/^firewall=([01])$/) {
1356 $res->{firewall
} = $1;
1357 } elsif ($kvp =~ m/^link_down=([01])$/) {
1358 $res->{link_down
} = $1;
1365 return undef if !$res->{model
};
1373 my $res = "$net->{model}";
1374 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1375 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1376 $res .= ",rate=$net->{rate}" if $net->{rate
};
1377 $res .= ",tag=$net->{tag}" if $net->{tag
};
1378 $res .= ",firewall=1" if $net->{firewall
};
1379 $res .= ",link_down=1" if $net->{link_down
};
1380 $res .= ",queues=$net->{queues}" if $net->{queues
};
1385 sub add_random_macs
{
1386 my ($settings) = @_;
1388 foreach my $opt (keys %$settings) {
1389 next if $opt !~ m/^net(\d+)$/;
1390 my $net = parse_net
($settings->{$opt});
1392 $settings->{$opt} = print_net
($net);
1396 sub add_unused_volume
{
1397 my ($config, $volid) = @_;
1400 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1401 my $test = "unused$ind";
1402 if (my $vid = $config->{$test}) {
1403 return if $vid eq $volid; # do not add duplicates
1409 die "To many unused volume - please delete them first.\n" if !$key;
1411 $config->{$key} = $volid;
1416 sub vm_is_volid_owner
{
1417 my ($storecfg, $vmid, $volid) = @_;
1419 if ($volid !~ m
|^/|) {
1421 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1422 if ($owner && ($owner == $vmid)) {
1430 sub vmconfig_delete_pending_option
{
1431 my ($conf, $key) = @_;
1433 delete $conf->{pending
}->{$key};
1434 my $pending_delete_hash = { $key => 1 };
1435 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1436 $pending_delete_hash->{$opt} = 1;
1438 $conf->{pending
}->{delete} = join(',', keys %$pending_delete_hash);
1441 sub vmconfig_undelete_pending_option
{
1442 my ($conf, $key) = @_;
1444 my $pending_delete_hash = {};
1445 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1446 $pending_delete_hash->{$opt} = 1;
1448 delete $pending_delete_hash->{$key};
1450 my @keylist = keys %$pending_delete_hash;
1451 if (scalar(@keylist)) {
1452 $conf->{pending
}->{delete} = join(',', @keylist);
1454 delete $conf->{pending
}->{delete};
1458 sub vmconfig_register_unused_drive
{
1459 my ($storecfg, $vmid, $conf, $drive) = @_;
1461 if (!drive_is_cdrom
($drive)) {
1462 my $volid = $drive->{file
};
1463 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1464 add_unused_volume
($conf, $volid, $vmid);
1469 sub vmconfig_cleanup_pending
{
1472 # remove pending changes when nothing changed
1474 foreach my $opt (keys %{$conf->{pending
}}) {
1475 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1477 delete $conf->{pending
}->{$opt};
1481 # remove delete if option is not set
1482 my $pending_delete_hash = {};
1483 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1484 if (defined($conf->{$opt})) {
1485 $pending_delete_hash->{$opt} = 1;
1491 my @keylist = keys %$pending_delete_hash;
1492 if (scalar(@keylist)) {
1493 $conf->{pending
}->{delete} = join(',', @keylist);
1495 delete $conf->{pending
}->{delete};
1501 my $valid_smbios1_options = {
1502 manufacturer
=> '\S+',
1506 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1511 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1517 foreach my $kvp (split(/,/, $data)) {
1518 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1519 my ($k, $v) = split(/=/, $kvp);
1520 return undef if !defined($k) || !defined($v);
1521 return undef if !$valid_smbios1_options->{$k};
1522 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1533 foreach my $k (keys %$smbios1) {
1534 next if !defined($smbios1->{$k});
1535 next if !$valid_smbios1_options->{$k};
1536 $data .= ',' if $data;
1537 $data .= "$k=$smbios1->{$k}";
1542 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1543 sub verify_smbios1
{
1544 my ($value, $noerr) = @_;
1546 return $value if parse_smbios1
($value);
1548 return undef if $noerr;
1550 die "unable to parse smbios (type 1) options\n";
1553 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1554 sub verify_bootdisk
{
1555 my ($value, $noerr) = @_;
1557 return $value if valid_drivename
($value);
1559 return undef if $noerr;
1561 die "invalid boot disk '$value'\n";
1564 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1566 my ($value, $noerr) = @_;
1568 return $value if parse_numa
($value);
1570 return undef if $noerr;
1572 die "unable to parse numa options\n";
1575 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1577 my ($value, $noerr) = @_;
1579 return $value if parse_net
($value);
1581 return undef if $noerr;
1583 die "unable to parse network options\n";
1586 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1588 my ($value, $noerr) = @_;
1590 return $value if parse_drive
(undef, $value);
1592 return undef if $noerr;
1594 die "unable to parse drive options\n";
1597 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1598 sub verify_hostpci
{
1599 my ($value, $noerr) = @_;
1601 return $value if parse_hostpci
($value);
1603 return undef if $noerr;
1605 die "unable to parse pci id\n";
1608 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1609 sub verify_watchdog
{
1610 my ($value, $noerr) = @_;
1612 return $value if parse_watchdog
($value);
1614 return undef if $noerr;
1616 die "unable to parse watchdog options\n";
1619 sub parse_watchdog
{
1622 return undef if !$value;
1626 foreach my $p (split(/,/, $value)) {
1627 next if $p =~ m/^\s*$/;
1629 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1631 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1632 $res->{action
} = $2;
1641 sub parse_usb_device
{
1644 return undef if !$value;
1646 my @dl = split(/,/, $value);
1650 foreach my $v (@dl) {
1651 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1653 $res->{vendorid
} = $2;
1654 $res->{productid
} = $4;
1655 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1657 $res->{hostbus
} = $1;
1658 $res->{hostport
} = $2;
1659 } elsif ($v =~ m/^spice$/) {
1666 return undef if !$found;
1671 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1672 sub verify_usb_device
{
1673 my ($value, $noerr) = @_;
1675 return $value if parse_usb_device
($value);
1677 return undef if $noerr;
1679 die "unable to parse usb device\n";
1682 # add JSON properties for create and set function
1683 sub json_config_properties
{
1686 foreach my $opt (keys %$confdesc) {
1687 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1688 $prop->{$opt} = $confdesc->{$opt};
1695 my ($key, $value) = @_;
1697 die "unknown setting '$key'\n" if !$confdesc->{$key};
1699 my $type = $confdesc->{$key}->{type
};
1701 if (!defined($value)) {
1702 die "got undefined value\n";
1705 if ($value =~ m/[\n\r]/) {
1706 die "property contains a line feed\n";
1709 if ($type eq 'boolean') {
1710 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1711 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1712 die "type check ('boolean') failed - got '$value'\n";
1713 } elsif ($type eq 'integer') {
1714 return int($1) if $value =~ m/^(\d+)$/;
1715 die "type check ('integer') failed - got '$value'\n";
1716 } elsif ($type eq 'number') {
1717 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1718 die "type check ('number') failed - got '$value'\n";
1719 } elsif ($type eq 'string') {
1720 if (my $fmt = $confdesc->{$key}->{format
}) {
1721 if ($fmt eq 'pve-qm-drive') {
1722 # special case - we need to pass $key to parse_drive()
1723 my $drive = parse_drive
($key, $value);
1724 return $value if $drive;
1725 die "unable to parse drive options\n";
1727 PVE
::JSONSchema
::check_format
($fmt, $value);
1730 $value =~ s/^\"(.*)\"$/$1/;
1733 die "internal error"
1737 sub lock_config_full
{
1738 my ($vmid, $timeout, $code, @param) = @_;
1740 my $filename = config_file_lock
($vmid);
1742 my $res = lock_file
($filename, $timeout, $code, @param);
1749 sub lock_config_mode
{
1750 my ($vmid, $timeout, $shared, $code, @param) = @_;
1752 my $filename = config_file_lock
($vmid);
1754 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1762 my ($vmid, $code, @param) = @_;
1764 return lock_config_full
($vmid, 10, $code, @param);
1767 sub cfs_config_path
{
1768 my ($vmid, $node) = @_;
1770 $node = $nodename if !$node;
1771 return "nodes/$node/qemu-server/$vmid.conf";
1774 sub check_iommu_support
{
1775 #fixme : need to check IOMMU support
1776 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1784 my ($vmid, $node) = @_;
1786 my $cfspath = cfs_config_path
($vmid, $node);
1787 return "/etc/pve/$cfspath";
1790 sub config_file_lock
{
1793 return "$lock_dir/lock-$vmid.conf";
1799 my $conf = config_file
($vmid);
1800 utime undef, undef, $conf;
1804 my ($storecfg, $vmid, $keep_empty_config) = @_;
1806 my $conffile = config_file
($vmid);
1808 my $conf = load_config
($vmid);
1812 # only remove disks owned by this VM
1813 foreach_drive
($conf, sub {
1814 my ($ds, $drive) = @_;
1816 return if drive_is_cdrom
($drive);
1818 my $volid = $drive->{file
};
1820 return if !$volid || $volid =~ m
|^/|;
1822 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1823 return if !$path || !$owner || ($owner != $vmid);
1825 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1828 if ($keep_empty_config) {
1829 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1834 # also remove unused disk
1836 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1839 PVE
::Storage
::foreach_volid
($dl, sub {
1840 my ($volid, $sid, $volname, $d) = @_;
1841 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1851 my ($vmid, $node) = @_;
1853 my $cfspath = cfs_config_path
($vmid, $node);
1855 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1857 die "no such VM ('$vmid')\n" if !defined($conf);
1862 sub parse_vm_config
{
1863 my ($filename, $raw) = @_;
1865 return undef if !defined($raw);
1868 digest
=> Digest
::SHA
::sha1_hex
($raw),
1873 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1874 || die "got strange filename '$filename'";
1882 my @lines = split(/\n/, $raw);
1883 foreach my $line (@lines) {
1884 next if $line =~ m/^\s*$/;
1886 if ($line =~ m/^\[PENDING\]\s*$/i) {
1887 $section = 'pending';
1888 $conf->{description
} = $descr if $descr;
1890 $conf = $res->{$section} = {};
1893 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1895 $conf->{description
} = $descr if $descr;
1897 $conf = $res->{snapshots
}->{$section} = {};
1901 if ($line =~ m/^\#(.*)\s*$/) {
1902 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1906 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1907 $descr .= PVE
::Tools
::decode_text
($2);
1908 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1909 $conf->{snapstate
} = $1;
1910 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1913 $conf->{$key} = $value;
1914 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1916 if ($section eq 'pending') {
1917 $conf->{delete} = $value; # we parse this later
1919 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1921 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1924 eval { $value = check_type
($key, $value); };
1926 warn "vm $vmid - unable to parse value of '$key' - $@";
1928 my $fmt = $confdesc->{$key}->{format
};
1929 if ($fmt && $fmt eq 'pve-qm-drive') {
1930 my $v = parse_drive
($key, $value);
1931 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1932 $v->{file
} = $volid;
1933 $value = print_drive
($vmid, $v);
1935 warn "vm $vmid - unable to parse value of '$key'\n";
1940 if ($key eq 'cdrom') {
1941 $conf->{ide2
} = $value;
1943 $conf->{$key} = $value;
1949 $conf->{description
} = $descr if $descr;
1951 delete $res->{snapstate
}; # just to be sure
1956 sub write_vm_config
{
1957 my ($filename, $conf) = @_;
1959 delete $conf->{snapstate
}; # just to be sure
1961 if ($conf->{cdrom
}) {
1962 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1963 $conf->{ide2
} = $conf->{cdrom
};
1964 delete $conf->{cdrom
};
1967 # we do not use 'smp' any longer
1968 if ($conf->{sockets
}) {
1969 delete $conf->{smp
};
1970 } elsif ($conf->{smp
}) {
1971 $conf->{sockets
} = $conf->{smp
};
1972 delete $conf->{cores
};
1973 delete $conf->{smp
};
1976 my $used_volids = {};
1978 my $cleanup_config = sub {
1979 my ($cref, $pending, $snapname) = @_;
1981 foreach my $key (keys %$cref) {
1982 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1983 $key eq 'snapstate' || $key eq 'pending';
1984 my $value = $cref->{$key};
1985 if ($key eq 'delete') {
1986 die "propertry 'delete' is only allowed in [PENDING]\n"
1988 # fixme: check syntax?
1991 eval { $value = check_type
($key, $value); };
1992 die "unable to parse value of '$key' - $@" if $@;
1994 $cref->{$key} = $value;
1996 if (!$snapname && valid_drivename
($key)) {
1997 my $drive = parse_drive
($key, $value);
1998 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2003 &$cleanup_config($conf);
2005 &$cleanup_config($conf->{pending
}, 1);
2007 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2008 die "internal error" if $snapname eq 'pending';
2009 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2012 # remove 'unusedX' settings if we re-add a volume
2013 foreach my $key (keys %$conf) {
2014 my $value = $conf->{$key};
2015 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2016 delete $conf->{$key};
2020 my $generate_raw_config = sub {
2025 # add description as comment to top of file
2026 my $descr = $conf->{description
} || '';
2027 foreach my $cl (split(/\n/, $descr)) {
2028 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2031 foreach my $key (sort keys %$conf) {
2032 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2033 $raw .= "$key: $conf->{$key}\n";
2038 my $raw = &$generate_raw_config($conf);
2040 if (scalar(keys %{$conf->{pending
}})){
2041 $raw .= "\n[PENDING]\n";
2042 $raw .= &$generate_raw_config($conf->{pending
});
2045 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2046 $raw .= "\n[$snapname]\n";
2047 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2053 sub update_config_nolock
{
2054 my ($vmid, $conf, $skiplock) = @_;
2056 check_lock
($conf) if !$skiplock;
2058 my $cfspath = cfs_config_path
($vmid);
2060 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2064 my ($vmid, $conf, $skiplock) = @_;
2066 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2073 # we use static defaults from our JSON schema configuration
2074 foreach my $key (keys %$confdesc) {
2075 if (defined(my $default = $confdesc->{$key}->{default})) {
2076 $res->{$key} = $default;
2080 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2081 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2087 my $vmlist = PVE
::Cluster
::get_vmlist
();
2089 return $res if !$vmlist || !$vmlist->{ids
};
2090 my $ids = $vmlist->{ids
};
2092 foreach my $vmid (keys %$ids) {
2093 my $d = $ids->{$vmid};
2094 next if !$d->{node
} || $d->{node
} ne $nodename;
2095 next if !$d->{type
} || $d->{type
} ne 'qemu';
2096 $res->{$vmid}->{exists} = 1;
2101 # test if VM uses local resources (to prevent migration)
2102 sub check_local_resources
{
2103 my ($conf, $noerr) = @_;
2107 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2108 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2110 foreach my $k (keys %$conf) {
2111 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2112 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2115 die "VM uses local resources\n" if $loc_res && !$noerr;
2120 # check if used storages are available on all nodes (use by migrate)
2121 sub check_storage_availability
{
2122 my ($storecfg, $conf, $node) = @_;
2124 foreach_drive
($conf, sub {
2125 my ($ds, $drive) = @_;
2127 my $volid = $drive->{file
};
2130 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2133 # check if storage is available on both nodes
2134 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2135 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2139 # list nodes where all VM images are available (used by has_feature API)
2141 my ($conf, $storecfg) = @_;
2143 my $nodelist = PVE
::Cluster
::get_nodelist
();
2144 my $nodehash = { map { $_ => 1 } @$nodelist };
2145 my $nodename = PVE
::INotify
::nodename
();
2147 foreach_drive
($conf, sub {
2148 my ($ds, $drive) = @_;
2150 my $volid = $drive->{file
};
2153 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2155 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2156 if ($scfg->{disable
}) {
2158 } elsif (my $avail = $scfg->{nodes
}) {
2159 foreach my $node (keys %$nodehash) {
2160 delete $nodehash->{$node} if !$avail->{$node};
2162 } elsif (!$scfg->{shared
}) {
2163 foreach my $node (keys %$nodehash) {
2164 delete $nodehash->{$node} if $node ne $nodename
2176 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2180 my ($pidfile, $pid) = @_;
2182 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2186 return undef if !$line;
2187 my @param = split(/\0/, $line);
2189 my $cmd = $param[0];
2190 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2192 for (my $i = 0; $i < scalar (@param); $i++) {
2195 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2196 my $p = $param[$i+1];
2197 return 1 if $p && ($p eq $pidfile);
2206 my ($vmid, $nocheck, $node) = @_;
2208 my $filename = config_file
($vmid, $node);
2210 die "unable to find configuration file for VM $vmid - no such machine\n"
2211 if !$nocheck && ! -f
$filename;
2213 my $pidfile = pidfile_name
($vmid);
2215 if (my $fd = IO
::File-
>new("<$pidfile")) {
2220 my $mtime = $st->mtime;
2221 if ($mtime > time()) {
2222 warn "file '$filename' modified in future\n";
2225 if ($line =~ m/^(\d+)$/) {
2227 if (check_cmdline
($pidfile, $pid)) {
2228 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2240 my $vzlist = config_list
();
2242 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2244 while (defined(my $de = $fd->read)) {
2245 next if $de !~ m/^(\d+)\.pid$/;
2247 next if !defined($vzlist->{$vmid});
2248 if (my $pid = check_running
($vmid)) {
2249 $vzlist->{$vmid}->{pid
} = $pid;
2257 my ($storecfg, $conf) = @_;
2259 my $bootdisk = $conf->{bootdisk
};
2260 return undef if !$bootdisk;
2261 return undef if !valid_drivename
($bootdisk);
2263 return undef if !$conf->{$bootdisk};
2265 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2266 return undef if !defined($drive);
2268 return undef if drive_is_cdrom
($drive);
2270 my $volid = $drive->{file
};
2271 return undef if !$volid;
2273 return $drive->{size
};
2276 my $last_proc_pid_stat;
2278 # get VM status information
2279 # This must be fast and should not block ($full == false)
2280 # We only query KVM using QMP if $full == true (this can be slow)
2282 my ($opt_vmid, $full) = @_;
2286 my $storecfg = PVE
::Storage
::config
();
2288 my $list = vzlist
();
2289 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2291 my $cpucount = $cpuinfo->{cpus
} || 1;
2293 foreach my $vmid (keys %$list) {
2294 next if $opt_vmid && ($vmid ne $opt_vmid);
2296 my $cfspath = cfs_config_path
($vmid);
2297 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2300 $d->{pid
} = $list->{$vmid}->{pid
};
2302 # fixme: better status?
2303 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2305 my $size = disksize
($storecfg, $conf);
2306 if (defined($size)) {
2307 $d->{disk
} = 0; # no info available
2308 $d->{maxdisk
} = $size;
2314 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2315 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2316 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2318 $d->{name
} = $conf->{name
} || "VM $vmid";
2319 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2321 if ($conf->{balloon
}) {
2322 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2323 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2334 $d->{diskwrite
} = 0;
2336 $d->{template
} = is_template
($conf);
2341 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2342 foreach my $dev (keys %$netdev) {
2343 next if $dev !~ m/^tap([1-9]\d*)i/;
2345 my $d = $res->{$vmid};
2348 $d->{netout
} += $netdev->{$dev}->{receive
};
2349 $d->{netin
} += $netdev->{$dev}->{transmit
};
2352 my $ctime = gettimeofday
;
2354 foreach my $vmid (keys %$list) {
2356 my $d = $res->{$vmid};
2357 my $pid = $d->{pid
};
2360 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2361 next if !$pstat; # not running
2363 my $used = $pstat->{utime} + $pstat->{stime
};
2365 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2367 if ($pstat->{vsize
}) {
2368 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2371 my $old = $last_proc_pid_stat->{$pid};
2373 $last_proc_pid_stat->{$pid} = {
2381 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2383 if ($dtime > 1000) {
2384 my $dutime = $used - $old->{used
};
2386 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2387 $last_proc_pid_stat->{$pid} = {
2393 $d->{cpu
} = $old->{cpu
};
2397 return $res if !$full;
2399 my $qmpclient = PVE
::QMPClient-
>new();
2401 my $ballooncb = sub {
2402 my ($vmid, $resp) = @_;
2404 my $info = $resp->{'return'};
2405 return if !$info->{max_mem
};
2407 my $d = $res->{$vmid};
2409 # use memory assigned to VM
2410 $d->{maxmem
} = $info->{max_mem
};
2411 $d->{balloon
} = $info->{actual
};
2413 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2414 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2415 $d->{freemem
} = $info->{free_mem
};
2420 my $blockstatscb = sub {
2421 my ($vmid, $resp) = @_;
2422 my $data = $resp->{'return'} || [];
2423 my $totalrdbytes = 0;
2424 my $totalwrbytes = 0;
2425 for my $blockstat (@$data) {
2426 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2427 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2429 $res->{$vmid}->{diskread
} = $totalrdbytes;
2430 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2433 my $statuscb = sub {
2434 my ($vmid, $resp) = @_;
2436 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2437 # this fails if ballon driver is not loaded, so this must be
2438 # the last commnand (following command are aborted if this fails).
2439 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2441 my $status = 'unknown';
2442 if (!defined($status = $resp->{'return'}->{status
})) {
2443 warn "unable to get VM status\n";
2447 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2450 foreach my $vmid (keys %$list) {
2451 next if $opt_vmid && ($vmid ne $opt_vmid);
2452 next if !$res->{$vmid}->{pid
}; # not running
2453 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2456 $qmpclient->queue_execute(undef, 1);
2458 foreach my $vmid (keys %$list) {
2459 next if $opt_vmid && ($vmid ne $opt_vmid);
2460 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2467 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2470 my $current_size = 1024;
2471 my $dimm_size = 512;
2472 return if $current_size == $memory;
2474 for (my $j = 0; $j < 8; $j++) {
2475 for (my $i = 0; $i < 32; $i++) {
2476 my $name = "dimm${dimm_id}";
2478 my $numanode = $i % $sockets;
2479 $current_size += $dimm_size;
2480 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2481 return $current_size if $current_size >= $memory;
2488 my ($conf, $func) = @_;
2490 foreach my $ds (keys %$conf) {
2491 next if !valid_drivename
($ds);
2493 my $drive = parse_drive
($ds, $conf->{$ds});
2496 &$func($ds, $drive);
2501 my ($conf, $func) = @_;
2505 my $test_volid = sub {
2506 my ($volid, $is_cdrom) = @_;
2510 $volhash->{$volid} = $is_cdrom || 0;
2513 foreach_drive
($conf, sub {
2514 my ($ds, $drive) = @_;
2515 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2518 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2519 my $snap = $conf->{snapshots
}->{$snapname};
2520 &$test_volid($snap->{vmstate
}, 0);
2521 foreach_drive
($snap, sub {
2522 my ($ds, $drive) = @_;
2523 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2527 foreach my $volid (keys %$volhash) {
2528 &$func($volid, $volhash->{$volid});
2532 sub vga_conf_has_spice
{
2535 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2540 sub config_to_command
{
2541 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2544 my $globalFlags = [];
2545 my $machineFlags = [];
2551 my $kvmver = kvm_user_version
();
2552 my $vernum = 0; # unknown
2553 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2554 $vernum = $1*1000000+$2*1000;
2555 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2556 $vernum = $1*1000000+$2*1000+$3;
2559 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2561 my $have_ovz = -f
'/proc/vz/vestat';
2563 my $q35 = machine_type_is_q35
($conf);
2564 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2565 my $machine_type = $forcemachine || $conf->{machine
};
2567 my $cpuunits = defined($conf->{cpuunits
}) ?
2568 $conf->{cpuunits
} : $defaults->{cpuunits
};
2570 push @$cmd, '/usr/bin/systemd-run';
2571 push @$cmd, '--scope';
2572 push @$cmd, '--slice', "qemu";
2573 push @$cmd, '--unit', $vmid;
2574 push @$cmd, '-p', "CPUShares=$cpuunits";
2575 if ($conf->{cpulimit
}) {
2576 my $cpulimit = int($conf->{cpulimit
} * 100);
2577 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2580 push @$cmd, '/usr/bin/kvm';
2582 push @$cmd, '-id', $vmid;
2586 my $qmpsocket = qmp_socket
($vmid);
2587 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2588 push @$cmd, '-mon', "chardev=qmp,mode=control";
2590 my $socket = vnc_socket
($vmid);
2591 push @$cmd, '-vnc', "unix:$socket,x509,password";
2593 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2595 push @$cmd, '-daemonize';
2597 if ($conf->{smbios1
}) {
2598 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2602 # the q35 chipset support native usb2, so we enable usb controller
2603 # by default for this machine type
2604 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2606 $pciaddr = print_pci_addr
("piix3", $bridges);
2607 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2610 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2611 next if !$conf->{"usb$i"};
2614 # include usb device config
2615 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2618 my $vga = $conf->{vga
};
2620 my $qxlnum = vga_conf_has_spice
($vga);
2621 $vga = 'qxl' if $qxlnum;
2624 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2625 $conf->{ostype
} eq 'win7' ||
2626 $conf->{ostype
} eq 'w2k8')) {
2633 # enable absolute mouse coordinates (needed by vnc)
2635 if (defined($conf->{tablet
})) {
2636 $tablet = $conf->{tablet
};
2638 $tablet = $defaults->{tablet
};
2639 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2640 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2643 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2646 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2647 my $d = parse_hostpci
($conf->{"hostpci$i"});
2650 my $pcie = $d->{pcie
};
2652 die "q35 machine model is not enabled" if !$q35;
2653 $pciaddr = print_pcie_addr
("hostpci$i");
2655 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2658 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2659 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2660 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2661 if ($xvga && $xvga ne '') {
2662 push @$cpuFlags, 'kvm=off';
2665 $driver = "vfio-pci" if $xvga ne '';
2666 my $pcidevices = $d->{pciid
};
2667 my $multifunction = 1 if @$pcidevices > 1;
2670 foreach my $pcidevice (@$pcidevices) {
2672 my $id = "hostpci$i";
2673 $id .= ".$j" if $multifunction;
2674 my $addr = $pciaddr;
2675 $addr .= ".$j" if $multifunction;
2676 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2679 $devicestr .= "$rombar$xvga";
2680 $devicestr .= ",multifunction=on" if $multifunction;
2683 push @$devices, '-device', $devicestr;
2689 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2690 my $d = parse_usb_device
($conf->{"usb$i"});
2692 if ($d->{vendorid
} && $d->{productid
}) {
2693 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2694 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2695 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2696 } elsif ($d->{spice
}) {
2697 # usb redir support for spice
2698 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2699 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2704 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2705 if (my $path = $conf->{"serial$i"}) {
2706 if ($path eq 'socket') {
2707 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2708 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2709 push @$devices, '-device', "isa-serial,chardev=serial$i";
2711 die "no such serial device\n" if ! -c
$path;
2712 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2713 push @$devices, '-device', "isa-serial,chardev=serial$i";
2719 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2720 if (my $path = $conf->{"parallel$i"}) {
2721 die "no such parallel device\n" if ! -c
$path;
2722 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2723 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2724 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2728 my $vmname = $conf->{name
} || "vm$vmid";
2730 push @$cmd, '-name', $vmname;
2733 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2734 $sockets = $conf->{sockets
} if $conf->{sockets
};
2736 my $cores = $conf->{cores
} || 1;
2738 my $maxcpus = $sockets * $cores;
2740 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2742 my $allowed_vcpus = $cpuinfo->{cpus
};
2744 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2745 if ($allowed_vcpus < $maxcpus);
2747 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2749 push @$cmd, '-nodefaults';
2751 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2753 my $bootindex_hash = {};
2755 foreach my $o (split(//, $bootorder)) {
2756 $bootindex_hash->{$o} = $i*100;
2760 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2762 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2764 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2766 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2769 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2771 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2772 my $useLocaltime = $conf->{localtime};
2774 if (my $ost = $conf->{ostype
}) {
2775 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2777 if ($ost =~ m/^w/) { # windows
2778 $useLocaltime = 1 if !defined($conf->{localtime});
2780 # use time drift fix when acpi is enabled
2781 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2782 $tdf = 1 if !defined($conf->{tdf
});
2786 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2788 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2789 push @$cmd, '-no-hpet';
2790 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2791 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2792 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2793 push @$cpuFlags , 'hv_time' if !$nokvm;
2796 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2800 if ($ost eq 'win7' || $ost eq 'win8') {
2801 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2805 push @$rtcFlags, 'driftfix=slew' if $tdf;
2808 push @$machineFlags, 'accel=tcg';
2810 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2813 if ($machine_type) {
2814 push @$machineFlags, "type=${machine_type}";
2817 if ($conf->{startdate
}) {
2818 push @$rtcFlags, "base=$conf->{startdate}";
2819 } elsif ($useLocaltime) {
2820 push @$rtcFlags, 'base=localtime';
2823 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2824 $cpu = $conf->{cpu
} if $conf->{cpu
};
2826 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2828 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2830 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2832 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2834 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2836 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2837 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2840 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2842 push @$cmd, '-cpu', "$cpu,enforce";
2844 my $memory = $conf->{memory
} || $defaults->{memory
};
2845 my $static_memory = 0;
2846 my $dimm_memory = 0;
2848 if ($hotplug_features->{memory
}) {
2849 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2850 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2851 $static_memory = $STATICMEM;
2852 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2853 $dimm_memory = $memory - $static_memory;
2854 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2858 $static_memory = $memory;
2859 push @$cmd, '-m', $static_memory;
2862 if ($conf->{numa
}) {
2864 my $numa_totalmemory = undef;
2865 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2866 next if !$conf->{"numa$i"};
2867 my $numa = parse_numa
($conf->{"numa$i"});
2870 die "missing numa node$i memory value\n" if !$numa->{memory
};
2871 my $numa_memory = $numa->{memory
};
2872 $numa_totalmemory += $numa_memory;
2873 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2876 my $cpus_start = $numa->{cpus
}->{start
};
2877 die "missing numa node$i cpus\n" if !defined($cpus_start);
2878 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2879 my $cpus = $cpus_start;
2880 if (defined($cpus_end)) {
2881 $cpus .= "-$cpus_end";
2882 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2886 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2887 if (defined($hostnodes_start)) {
2888 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2889 my $hostnodes = $hostnodes_start;
2890 if (defined($hostnodes_end)) {
2891 $hostnodes .= "-$hostnodes_end";
2892 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2895 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2896 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2897 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2901 my $policy = $numa->{policy
};
2902 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2903 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2906 push @$cmd, '-object', $numa_object;
2907 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2910 die "total memory for NUMA nodes must be equal to vm static memory\n"
2911 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2913 #if no custom tology, we split memory and cores across numa nodes
2914 if(!$numa_totalmemory) {
2916 my $numa_memory = ($static_memory / $sockets) . "M";
2918 for (my $i = 0; $i < $sockets; $i++) {
2920 my $cpustart = ($cores * $i);
2921 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2922 my $cpus = $cpustart;
2923 $cpus .= "-$cpuend" if $cpuend;
2925 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2926 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2931 if ($hotplug_features->{memory
}) {
2932 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2933 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2934 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2935 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2937 #if dimm_memory is not aligned to dimm map
2938 if($current_size > $memory) {
2939 $conf->{memory
} = $current_size;
2940 update_config_nolock
($vmid, $conf, 1);
2945 push @$cmd, '-S' if $conf->{freeze
};
2947 # set keyboard layout
2948 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2949 push @$cmd, '-k', $kb if $kb;
2952 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2953 #push @$cmd, '-soundhw', 'es1370';
2954 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2956 if($conf->{agent
}) {
2957 my $qgasocket = qmp_socket
($vmid, 1);
2958 my $pciaddr = print_pci_addr
("qga0", $bridges);
2959 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2960 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2961 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2968 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2969 for(my $i = 1; $i < $qxlnum; $i++){
2970 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2971 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2974 # assume other OS works like Linux
2975 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2976 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2980 my $pciaddr = print_pci_addr
("spice", $bridges);
2982 my $nodename = PVE
::INotify
::nodename
();
2983 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
2984 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
2986 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2988 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
2989 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2990 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2993 # enable balloon by default, unless explicitly disabled
2994 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2995 $pciaddr = print_pci_addr
("balloon0", $bridges);
2996 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2999 if ($conf->{watchdog
}) {
3000 my $wdopts = parse_watchdog
($conf->{watchdog
});
3001 $pciaddr = print_pci_addr
("watchdog", $bridges);
3002 my $watchdog = $wdopts->{model
} || 'i6300esb';
3003 push @$devices, '-device', "$watchdog$pciaddr";
3004 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3008 my $scsicontroller = {};
3009 my $ahcicontroller = {};
3010 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3012 # Add iscsi initiator name if available
3013 if (my $initiator = get_initiator_name
()) {
3014 push @$devices, '-iscsi', "initiator-name=$initiator";
3017 foreach_drive
($conf, sub {
3018 my ($ds, $drive) = @_;
3020 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3021 push @$vollist, $drive->{file
};
3024 $use_virtio = 1 if $ds =~ m/^virtio/;
3026 if (drive_is_cdrom
($drive)) {
3027 if ($bootindex_hash->{d
}) {
3028 $drive->{bootindex
} = $bootindex_hash->{d
};
3029 $bootindex_hash->{d
} += 1;
3032 if ($bootindex_hash->{c
}) {
3033 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3034 $bootindex_hash->{c
} += 1;
3038 if($drive->{interface
} eq 'virtio'){
3039 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3042 if ($drive->{interface
} eq 'scsi') {
3044 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3046 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3047 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3050 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3051 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3052 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3056 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3057 $queues = ",num_queues=$drive->{queues}";
3060 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3061 $scsicontroller->{$controller}=1;
3064 if ($drive->{interface
} eq 'sata') {
3065 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3066 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3067 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3068 $ahcicontroller->{$controller}=1;
3071 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3072 push @$devices, '-drive',$drive_cmd;
3073 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3076 for (my $i = 0; $i < $MAX_NETS; $i++) {
3077 next if !$conf->{"net$i"};
3078 my $d = parse_net
($conf->{"net$i"});
3081 $use_virtio = 1 if $d->{model
} eq 'virtio';
3083 if ($bootindex_hash->{n
}) {
3084 $d->{bootindex
} = $bootindex_hash->{n
};
3085 $bootindex_hash->{n
} += 1;
3088 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3089 push @$devices, '-netdev', $netdevfull;
3091 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3092 push @$devices, '-device', $netdevicefull;
3097 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3102 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3104 while (my ($k, $v) = each %$bridges) {
3105 $pciaddr = print_pci_addr
("pci.$k");
3106 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3111 if ($conf->{args
}) {
3112 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3116 push @$cmd, @$devices;
3117 push @$cmd, '-rtc', join(',', @$rtcFlags)
3118 if scalar(@$rtcFlags);
3119 push @$cmd, '-machine', join(',', @$machineFlags)
3120 if scalar(@$machineFlags);
3121 push @$cmd, '-global', join(',', @$globalFlags)
3122 if scalar(@$globalFlags);
3124 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3129 return "${var_run_tmpdir}/$vmid.vnc";
3135 my $res = vm_mon_cmd
($vmid, 'query-spice');
3137 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3141 my ($vmid, $qga) = @_;
3142 my $sockettype = $qga ?
'qga' : 'qmp';
3143 return "${var_run_tmpdir}/$vmid.$sockettype";
3148 return "${var_run_tmpdir}/$vmid.pid";
3151 sub vm_devices_list
{
3154 my $res = vm_mon_cmd
($vmid, 'query-pci');
3156 foreach my $pcibus (@$res) {
3157 foreach my $device (@{$pcibus->{devices
}}) {
3158 next if !$device->{'qdev_id'};
3159 if ($device->{'pci_bridge'}) {
3160 $devices->{$device->{'qdev_id'}} = 1;
3161 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3162 next if !$bridge_device->{'qdev_id'};
3163 $devices->{$bridge_device->{'qdev_id'}} = 1;
3164 $devices->{$device->{'qdev_id'}}++;
3167 $devices->{$device->{'qdev_id'}} = 1;
3172 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3173 foreach my $block (@$resblock) {
3174 if($block->{device
} =~ m/^drive-(\S+)/){
3179 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3180 foreach my $mice (@$resmice) {
3181 if ($mice->{name
} eq 'QEMU HID Tablet') {
3182 $devices->{tablet
} = 1;
3191 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3193 my $q35 = machine_type_is_q35
($conf);
3195 my $devices_list = vm_devices_list
($vmid);
3196 return 1 if defined($devices_list->{$deviceid});
3198 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3200 if ($deviceid eq 'tablet') {
3202 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3204 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3206 qemu_iothread_add
($vmid, $deviceid, $device);
3208 qemu_driveadd
($storecfg, $vmid, $device);
3209 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3211 qemu_deviceadd
($vmid, $devicefull);
3212 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3214 eval { qemu_drivedel
($vmid, $deviceid); };
3219 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3222 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3223 my $pciaddr = print_pci_addr
($deviceid);
3224 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3226 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3228 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3229 qemu_iothread_add
($vmid, $deviceid, $device);
3230 $devicefull .= ",iothread=iothread-$deviceid";
3233 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3234 $devicefull .= ",num_queues=$device->{queues}";
3237 qemu_deviceadd
($vmid, $devicefull);
3238 qemu_deviceaddverify
($vmid, $deviceid);
3240 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3242 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3243 qemu_driveadd
($storecfg, $vmid, $device);
3245 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3246 eval { qemu_deviceadd
($vmid, $devicefull); };
3248 eval { qemu_drivedel
($vmid, $deviceid); };
3253 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3255 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3256 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3257 qemu_deviceadd
($vmid, $netdevicefull);
3258 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3260 eval { qemu_netdevdel
($vmid, $deviceid); };
3265 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3268 my $pciaddr = print_pci_addr
($deviceid);
3269 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3271 qemu_deviceadd
($vmid, $devicefull);
3272 qemu_deviceaddverify
($vmid, $deviceid);
3275 die "can't hotplug device '$deviceid'\n";
3281 # fixme: this should raise exceptions on error!
3282 sub vm_deviceunplug
{
3283 my ($vmid, $conf, $deviceid) = @_;
3285 my $devices_list = vm_devices_list
($vmid);
3286 return 1 if !defined($devices_list->{$deviceid});
3288 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3290 if ($deviceid eq 'tablet') {
3292 qemu_devicedel
($vmid, $deviceid);
3294 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3296 qemu_devicedel
($vmid, $deviceid);
3297 qemu_devicedelverify
($vmid, $deviceid);
3298 qemu_drivedel
($vmid, $deviceid);
3299 qemu_iothread_del
($conf, $vmid, $deviceid);
3301 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3303 qemu_devicedel
($vmid, $deviceid);
3304 qemu_devicedelverify
($vmid, $deviceid);
3305 qemu_iothread_del
($conf, $vmid, $deviceid);
3307 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3309 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3310 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3311 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3313 qemu_devicedel
($vmid, $deviceid);
3314 qemu_drivedel
($vmid, $deviceid);
3315 qemu_deletescsihw
($conf, $vmid, $deviceid);
3317 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3319 qemu_devicedel
($vmid, $deviceid);
3320 qemu_devicedelverify
($vmid, $deviceid);
3321 qemu_netdevdel
($vmid, $deviceid);
3324 die "can't unplug device '$deviceid'\n";
3330 sub qemu_deviceadd
{
3331 my ($vmid, $devicefull) = @_;
3333 $devicefull = "driver=".$devicefull;
3334 my %options = split(/[=,]/, $devicefull);
3336 vm_mon_cmd
($vmid, "device_add" , %options);
3339 sub qemu_devicedel
{
3340 my ($vmid, $deviceid) = @_;
3342 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3345 sub qemu_iothread_add
{
3346 my($vmid, $deviceid, $device) = @_;
3348 if ($device->{iothread
}) {
3349 my $iothreads = vm_iothreads_list
($vmid);
3350 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3354 sub qemu_iothread_del
{
3355 my($conf, $vmid, $deviceid) = @_;
3357 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3358 if ($device->{iothread
}) {
3359 my $iothreads = vm_iothreads_list
($vmid);
3360 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3364 sub qemu_objectadd
{
3365 my($vmid, $objectid, $qomtype) = @_;
3367 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3372 sub qemu_objectdel
{
3373 my($vmid, $objectid) = @_;
3375 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3381 my ($storecfg, $vmid, $device) = @_;
3383 my $drive = print_drive_full
($storecfg, $vmid, $device);
3384 $drive =~ s/\\/\\\\/g;
3385 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3387 # If the command succeeds qemu prints: "OK
"
3388 return 1 if $ret =~ m/OK/s;
3390 die "adding drive failed
: $ret\n";
3394 my($vmid, $deviceid) = @_;
3396 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3399 return 1 if $ret eq "";
3401 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3402 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3404 die "deleting drive
$deviceid failed
: $ret\n";
3407 sub qemu_deviceaddverify {
3408 my ($vmid, $deviceid) = @_;
3410 for (my $i = 0; $i <= 5; $i++) {
3411 my $devices_list = vm_devices_list($vmid);
3412 return 1 if defined($devices_list->{$deviceid});
3416 die "error on hotplug device
'$deviceid'\n";
3420 sub qemu_devicedelverify {
3421 my ($vmid, $deviceid) = @_;
3423 # need to verify that the device is correctly removed as device_del
3424 # is async and empty return is not reliable
3426 for (my $i = 0; $i <= 5; $i++) {
3427 my $devices_list = vm_devices_list($vmid);
3428 return 1 if !defined($devices_list->{$deviceid});
3432 die "error on hot-unplugging device
'$deviceid'\n";
3435 sub qemu_findorcreatescsihw {
3436 my ($storecfg, $conf, $vmid, $device) = @_;
3438 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3440 my $scsihwid="$controller_prefix$controller";
3441 my $devices_list = vm_devices_list($vmid);
3443 if(!defined($devices_list->{$scsihwid})) {
3444 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3450 sub qemu_deletescsihw {
3451 my ($conf, $vmid, $opt) = @_;
3453 my $device = parse_drive($opt, $conf->{$opt});
3455 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3456 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3460 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3462 my $devices_list = vm_devices_list($vmid);
3463 foreach my $opt (keys %{$devices_list}) {
3464 if (PVE::QemuServer::valid_drivename($opt)) {
3465 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3466 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3472 my $scsihwid="scsihw
$controller";
3474 vm_deviceunplug($vmid, $conf, $scsihwid);
3479 sub qemu_add_pci_bridge {
3480 my ($storecfg, $conf, $vmid, $device) = @_;
3486 print_pci_addr($device, $bridges);
3488 while (my ($k, $v) = each %$bridges) {
3491 return 1 if !defined($bridgeid) || $bridgeid < 1;
3493 my $bridge = "pci
.$bridgeid";
3494 my $devices_list = vm_devices_list($vmid);
3496 if (!defined($devices_list->{$bridge})) {
3497 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3503 sub qemu_set_link_status {
3504 my ($vmid, $device, $up) = @_;
3506 vm_mon_cmd($vmid, "set_link
", name => $device,
3507 up => $up ? JSON::true : JSON::false);
3510 sub qemu_netdevadd {
3511 my ($vmid, $conf, $device, $deviceid) = @_;
3513 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3514 my %options = split(/[=,]/, $netdev);
3516 vm_mon_cmd($vmid, "netdev_add
", %options);
3520 sub qemu_netdevdel {
3521 my ($vmid, $deviceid) = @_;
3523 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3526 sub qemu_cpu_hotplug {
3527 my ($vmid, $conf, $vcpus) = @_;
3530 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3531 $sockets = $conf->{sockets} if $conf->{sockets};
3532 my $cores = $conf->{cores} || 1;
3533 my $maxcpus = $sockets * $cores;
3535 $vcpus = $maxcpus if !$vcpus;
3537 die "you can
't add more vcpus than maxcpus\n"
3538 if $vcpus > $maxcpus;
3540 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3541 die "online cpu unplug is not yet possible\n"
3542 if $vcpus < $currentvcpus;
3544 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3545 die "vcpus in running vm is different than configuration\n"
3546 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3548 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3549 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3553 sub qemu_memory_hotplug {
3554 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3556 return $value if !check_running($vmid);
3558 my $memory = $conf->{memory} || $defaults->{memory};
3559 $value = $defaults->{memory} if !$value;
3560 return $value if $value == $memory;
3562 my $static_memory = $STATICMEM;
3563 my $dimm_memory = $memory - $static_memory;
3565 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3566 die "memory unplug
is not yet available
" if $value < $memory;
3567 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3571 $sockets = $conf->{sockets} if $conf->{sockets};
3573 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3574 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3576 return if $current_size <= $conf->{memory};
3578 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3580 eval { qemu_objectdel($vmid, "mem-
$name"); };
3584 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3586 eval { qemu_objectdel($vmid, "mem-
$name"); };
3589 #update conf after each succesful module hotplug
3590 $conf->{memory} = $current_size;
3591 update_config_nolock($vmid, $conf, 1);
3595 sub qemu_block_set_io_throttle {
3596 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3598 return if !check_running($vmid) ;
3600 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));
3604 # old code, only used to shutdown old VM after update
3606 my ($fh, $timeout) = @_;
3608 my $sel = new IO::Select;
3615 while (scalar (@ready = $sel->can_read($timeout))) {
3617 if ($count = $fh->sysread($buf, 8192)) {
3618 if ($buf =~ /^(.*)\(qemu\) $/s) {
3625 if (!defined($count)) {
3632 die "monitor
read timeout
\n" if !scalar(@ready);
3637 # old code, only used to shutdown old VM after update
3638 sub vm_monitor_command {
3639 my ($vmid, $cmdstr, $nocheck) = @_;
3644 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3646 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3648 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3649 die "unable to
connect to VM
$vmid socket - $!\n";
3653 # hack: migrate sometime blocks the monitor (when migrate_downtime
3655 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3656 $timeout = 60*60; # 1 hour
3660 my $data = __read_avail($sock, $timeout);
3662 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3663 die "got unexpected qemu monitor banner
\n";
3666 my $sel = new IO::Select;
3669 if (!scalar(my @ready = $sel->can_write($timeout))) {
3670 die "monitor
write error
- timeout
";
3673 my $fullcmd = "$cmdstr\r";
3675 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3678 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3679 die "monitor
write error
- $!";
3682 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3686 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3687 $timeout = 60*60; # 1 hour
3688 } elsif ($cmdstr =~ m/^(eject|change)/) {
3689 $timeout = 60; # note: cdrom mount command is slow
3691 if ($res = __read_avail($sock, $timeout)) {
3693 my @lines = split("\r?
\n", $res);
3695 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3697 $res = join("\n", @lines);
3705 syslog("err
", "VM
$vmid monitor command failed
- $err");
3712 sub qemu_block_resize {
3713 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3715 my $running = check_running($vmid);
3717 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3719 return if !$running;
3721 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3725 sub qemu_volume_snapshot {
3726 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3728 my $running = check_running($vmid);
3730 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3731 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3733 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3737 sub qemu_volume_snapshot_delete {
3738 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3740 my $running = check_running($vmid);
3742 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3744 return if !$running;
3746 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3749 sub set_migration_caps {
3755 "auto-converge
" => 1,
3757 "x-rdma-pin-all
" => 0,
3761 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3763 for my $supported_capability (@$supported_capabilities) {
3765 capability => $supported_capability->{capability},
3766 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3770 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3773 my $fast_plug_option = {
3781 # hotplug changes in [PENDING]
3782 # $selection hash can be used to only apply specified options, for
3783 # example: { cores => 1 } (only apply changed 'cores')
3784 # $errors ref is used to return error messages
3785 sub vmconfig_hotplug_pending {
3786 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3788 my $defaults = load_defaults();
3790 # commit values which do not have any impact on running VM first
3791 # Note: those option cannot raise errors, we we do not care about
3792 # $selection and always apply them.
3794 my $add_error = sub {
3795 my ($opt, $msg) = @_;
3796 $errors->{$opt} = "hotplug problem
- $msg";
3800 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3801 if ($fast_plug_option->{$opt}) {
3802 $conf->{$opt} = $conf->{pending}->{$opt};
3803 delete $conf->{pending}->{$opt};
3809 update_config_nolock($vmid, $conf, 1);
3810 $conf = load_config($vmid); # update/reload
3813 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3815 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3816 foreach my $opt (@delete) {
3817 next if $selection && !$selection->{$opt};
3819 if ($opt eq 'hotplug') {
3820 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3821 } elsif ($opt eq 'tablet') {
3822 die "skip
\n" if !$hotplug_features->{usb};
3823 if ($defaults->{tablet}) {
3824 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3826 vm_deviceunplug($vmid, $conf, $opt);
3828 } elsif ($opt eq 'vcpus') {
3829 die "skip
\n" if !$hotplug_features->{cpu};
3830 qemu_cpu_hotplug($vmid, $conf, undef);
3831 } elsif ($opt eq 'balloon') {
3832 # enable balloon device is not hotpluggable
3833 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3834 } elsif ($fast_plug_option->{$opt}) {
3836 } elsif ($opt =~ m/^net(\d+)$/) {
3837 die "skip
\n" if !$hotplug_features->{network};
3838 vm_deviceunplug($vmid, $conf, $opt);
3839 } elsif (valid_drivename($opt)) {
3840 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3841 vm_deviceunplug($vmid, $conf, $opt);
3842 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3843 } elsif ($opt =~ m/^memory$/) {
3844 die "skip
\n" if !$hotplug_features->{memory};
3845 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3846 } elsif ($opt eq 'cpuunits') {
3847 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3848 } elsif ($opt eq 'cpulimit') {
3849 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3855 &$add_error($opt, $err) if $err ne "skip
\n";
3857 # save new config if hotplug was successful
3858 delete $conf->{$opt};
3859 vmconfig_undelete_pending_option($conf, $opt);
3860 update_config_nolock($vmid, $conf, 1);
3861 $conf = load_config($vmid); # update/reload
3865 foreach my $opt (keys %{$conf->{pending}}) {
3866 next if $selection && !$selection->{$opt};
3867 my $value = $conf->{pending}->{$opt};
3869 if ($opt eq 'hotplug') {
3870 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3871 } elsif ($opt eq 'tablet') {
3872 die "skip
\n" if !$hotplug_features->{usb};
3874 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3875 } elsif ($value == 0) {
3876 vm_deviceunplug($vmid, $conf, $opt);
3878 } elsif ($opt eq 'vcpus') {
3879 die "skip
\n" if !$hotplug_features->{cpu};
3880 qemu_cpu_hotplug($vmid, $conf, $value);
3881 } elsif ($opt eq 'balloon') {
3882 # enable/disable balloning device is not hotpluggable
3883 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3884 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3885 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3887 # allow manual ballooning if shares is set to zero
3888 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3889 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3890 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3892 } elsif ($opt =~ m/^net(\d+)$/) {
3893 # some changes can be done without hotplug
3894 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3895 $vmid, $opt, $value);
3896 } elsif (valid_drivename($opt)) {
3897 # some changes can be done without hotplug
3898 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3899 $vmid, $opt, $value, 1);
3900 } elsif ($opt =~ m/^memory$/) { #dimms
3901 die "skip
\n" if !$hotplug_features->{memory};
3902 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3903 } elsif ($opt eq 'cpuunits') {
3904 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
3905 } elsif ($opt eq 'cpulimit') {
3906 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
3907 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
3909 die "skip
\n"; # skip non-hot-pluggable options
3913 &$add_error($opt, $err) if $err ne "skip
\n";
3915 # save new config if hotplug was successful
3916 $conf->{$opt} = $value;
3917 delete $conf->{pending}->{$opt};
3918 update_config_nolock($vmid, $conf, 1);
3919 $conf = load_config($vmid); # update/reload
3924 sub vmconfig_apply_pending {
3925 my ($vmid, $conf, $storecfg) = @_;
3929 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3930 foreach my $opt (@delete) { # delete
3931 die "internal error
" if $opt =~ m/^unused/;
3932 $conf = load_config($vmid); # update/reload
3933 if (!defined($conf->{$opt})) {
3934 vmconfig_undelete_pending_option($conf, $opt);
3935 update_config_nolock($vmid, $conf, 1);
3936 } elsif (valid_drivename($opt)) {
3937 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3938 vmconfig_undelete_pending_option($conf, $opt);
3939 delete $conf->{$opt};
3940 update_config_nolock($vmid, $conf, 1);
3942 vmconfig_undelete_pending_option($conf, $opt);
3943 delete $conf->{$opt};
3944 update_config_nolock($vmid, $conf, 1);
3948 $conf = load_config($vmid); # update/reload
3950 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3951 $conf = load_config($vmid); # update/reload
3953 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
3954 # skip if nothing changed
3955 } elsif (valid_drivename($opt)) {
3956 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
3957 if defined($conf->{$opt});
3958 $conf->{$opt} = $conf->{pending}->{$opt};
3960 $conf->{$opt} = $conf->{pending}->{$opt};
3963 delete $conf->{pending}->{$opt};
3964 update_config_nolock($vmid, $conf, 1);
3968 my $safe_num_ne = sub {
3971 return 0 if !defined($a) && !defined($b);
3972 return 1 if !defined($a);
3973 return 1 if !defined($b);
3978 my $safe_string_ne = sub {
3981 return 0 if !defined($a) && !defined($b);
3982 return 1 if !defined($a);
3983 return 1 if !defined($b);
3988 sub vmconfig_update_net {
3989 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
3991 my $newnet = parse_net($value);
3993 if ($conf->{$opt}) {
3994 my $oldnet = parse_net($conf->{$opt});
3996 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
3997 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
3998 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
3999 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4001 # for non online change, we try to hot-unplug
4002 die "skip
\n" if !$hotplug;
4003 vm_deviceunplug($vmid, $conf, $opt);
4006 die "internal error
" if $opt !~ m/net(\d+)/;
4007 my $iface = "tap
${vmid
}i
$1";
4009 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4010 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4013 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4014 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4015 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4016 PVE::Network::tap_unplug($iface);
4017 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4020 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4021 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4029 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4035 sub vmconfig_update_disk {
4036 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4038 # fixme: do we need force?
4040 my $drive = parse_drive($opt, $value);
4042 if ($conf->{$opt}) {
4044 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4046 my $media = $drive->{media} || 'disk';
4047 my $oldmedia = $old_drive->{media} || 'disk';
4048 die "unable to change media type
\n" if $media ne $oldmedia;
4050 if (!drive_is_cdrom($old_drive)) {
4052 if ($drive->{file} ne $old_drive->{file}) {
4054 die "skip
\n" if !$hotplug;
4056 # unplug and register as unused
4057 vm_deviceunplug($vmid, $conf, $opt);
4058 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4061 # update existing disk
4063 # skip non hotpluggable value
4064 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4065 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4066 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4067 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4072 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4073 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4074 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4075 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4076 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4077 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4078 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4079 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4080 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4081 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4082 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4083 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4085 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4086 ($drive->{mbps} || 0)*1024*1024,
4087 ($drive->{mbps_rd} || 0)*1024*1024,
4088 ($drive->{mbps_wr} || 0)*1024*1024,
4089 $drive->{iops} || 0,
4090 $drive->{iops_rd} || 0,
4091 $drive->{iops_wr} || 0,
4092 ($drive->{mbps_max} || 0)*1024*1024,
4093 ($drive->{mbps_rd_max} || 0)*1024*1024,
4094 ($drive->{mbps_wr_max} || 0)*1024*1024,
4095 $drive->{iops_max} || 0,
4096 $drive->{iops_rd_max} || 0,
4097 $drive->{iops_wr_max} || 0);
4106 if ($drive->{file} eq 'none') {
4107 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4109 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4110 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4111 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4119 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4121 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4125 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4127 lock_config($vmid, sub {
4128 my $conf = load_config($vmid, $migratedfrom);
4130 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4132 check_lock($conf) if !$skiplock;
4134 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4136 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4137 vmconfig_apply_pending($vmid, $conf, $storecfg);
4138 $conf = load_config($vmid); # update/reload
4141 my $defaults = load_defaults();
4143 # set environment variable useful inside network script
4144 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4146 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4148 my $migrate_port = 0;
4151 if ($statefile eq 'tcp') {
4152 my $localip = "localhost
";
4153 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4154 my $nodename = PVE::INotify::nodename();
4155 if ($datacenterconf->{migration_unsecure}) {
4156 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4158 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4159 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4160 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4161 push @$cmd, '-incoming', $migrate_uri;
4164 push @$cmd, '-loadstate', $statefile;
4171 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4172 my $d = parse_hostpci($conf->{"hostpci
$i"});
4174 my $pcidevices = $d->{pciid};
4175 foreach my $pcidevice (@$pcidevices) {
4176 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4178 my $info = pci_device_info("0000:$pciid");
4179 die "IOMMU
not present
\n" if !check_iommu_support();
4180 die "no pci device info
for device
'$pciid'\n" if !$info;
4182 if ($d->{driver} && $d->{driver} eq "vfio
") {
4183 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4185 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4188 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4192 PVE::Storage::activate_volumes($storecfg, $vollist);
4194 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4197 die "start failed: $err" if $err;
4199 print "migration listens on $migrate_uri\n" if $migrate_uri;
4201 if ($statefile && $statefile ne 'tcp
') {
4202 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4206 if ($migratedfrom) {
4209 set_migration_caps($vmid);
4214 print "spice listens on port $spice_port\n";
4215 if ($spice_ticket) {
4216 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4217 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4223 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4224 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4225 if $conf->{balloon};
4228 foreach my $opt (keys %$conf) {
4229 next if $opt !~ m/^net\d+$/;
4230 my $nicconf = parse_net($conf->{$opt});
4231 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4235 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4236 path => "machine/peripheral/balloon0",
4237 property => "guest-stats-polling-interval",
4238 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4244 my ($vmid, $execute, %params) = @_;
4246 my $cmd = { execute => $execute, arguments => \%params };
4247 vm_qmp_command($vmid, $cmd);
4250 sub vm_mon_cmd_nocheck {
4251 my ($vmid, $execute, %params) = @_;
4253 my $cmd = { execute => $execute, arguments => \%params };
4254 vm_qmp_command($vmid, $cmd, 1);
4257 sub vm_qmp_command {
4258 my ($vmid, $cmd, $nocheck) = @_;
4263 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4264 $timeout = $cmd->{arguments}->{timeout};
4265 delete $cmd->{arguments}->{timeout};
4269 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4270 my $sname = qmp_socket($vmid);
4271 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4272 my $qmpclient = PVE::QMPClient->new();
4274 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4275 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4276 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4277 if scalar(%{$cmd->{arguments}});
4278 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4280 die "unable to
open monitor
socket\n";
4284 syslog("err
", "VM
$vmid qmp command failed
- $err");
4291 sub vm_human_monitor_command {
4292 my ($vmid, $cmdline) = @_;
4297 execute => 'human-monitor-command',
4298 arguments => { 'command-line' => $cmdline},
4301 return vm_qmp_command($vmid, $cmd);
4304 sub vm_commandline {
4305 my ($storecfg, $vmid) = @_;
4307 my $conf = load_config($vmid);
4309 my $defaults = load_defaults();
4311 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4313 return join(' ', @$cmd);
4317 my ($vmid, $skiplock) = @_;
4319 lock_config($vmid, sub {
4321 my $conf = load_config($vmid);
4323 check_lock($conf) if !$skiplock;
4325 vm_mon_cmd($vmid, "system_reset
");
4329 sub get_vm_volumes {
4333 foreach_volid($conf, sub {
4334 my ($volid, $is_cdrom) = @_;
4336 return if $volid =~ m|^/|;
4338 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4341 push @$vollist, $volid;
4347 sub vm_stop_cleanup {
4348 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4353 my $vollist = get_vm_volumes($conf);
4354 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4357 foreach my $ext (qw(mon qmp pid vnc qga)) {
4358 unlink "/var/run/qemu-server/${vmid}.$ext";
4361 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4363 warn $@ if $@; # avoid errors - just warn
4366 # Note: use $nockeck to skip tests if VM configuration file exists.
4367 # We need that when migration VMs to other nodes (files already moved)
4368 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4370 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4372 $force = 1 if !defined($force) && !$shutdown;
4375 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4376 kill 15, $pid if $pid;
4377 my $conf = load_config
($vmid, $migratedfrom);
4378 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4382 lock_config
($vmid, sub {
4384 my $pid = check_running
($vmid, $nocheck);
4389 $conf = load_config
($vmid);
4390 check_lock
($conf) if !$skiplock;
4391 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4392 my $opts = parse_startup
($conf->{startup
});
4393 $timeout = $opts->{down
} if $opts->{down
};
4397 $timeout = 60 if !defined($timeout);
4401 if (defined($conf) && $conf->{agent
}) {
4402 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4404 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4407 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4414 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4419 if ($count >= $timeout) {
4421 warn "VM still running - terminating now with SIGTERM\n";
4424 die "VM quit/powerdown failed - got timeout\n";
4427 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4432 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4435 die "VM quit/powerdown failed\n";
4443 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4448 if ($count >= $timeout) {
4449 warn "VM still running - terminating now with SIGKILL\n";
4454 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4459 my ($vmid, $skiplock) = @_;
4461 lock_config
($vmid, sub {
4463 my $conf = load_config
($vmid);
4465 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4467 vm_mon_cmd
($vmid, "stop");
4472 my ($vmid, $skiplock) = @_;
4474 lock_config
($vmid, sub {
4476 my $conf = load_config
($vmid);
4478 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4480 vm_mon_cmd
($vmid, "cont");
4485 my ($vmid, $skiplock, $key) = @_;
4487 lock_config
($vmid, sub {
4489 my $conf = load_config
($vmid);
4491 # there is no qmp command, so we use the human monitor command
4492 vm_human_monitor_command
($vmid, "sendkey $key");
4497 my ($storecfg, $vmid, $skiplock) = @_;
4499 lock_config
($vmid, sub {
4501 my $conf = load_config
($vmid);
4503 check_lock
($conf) if !$skiplock;
4505 if (!check_running
($vmid)) {
4506 destroy_vm
($storecfg, $vmid);
4508 die "VM $vmid is running - destroy failed\n";
4516 my ($filename, $buf) = @_;
4518 my $fh = IO
::File-
>new($filename, "w");
4519 return undef if !$fh;
4521 my $res = print $fh $buf;
4528 sub pci_device_info
{
4533 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4534 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4536 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4537 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4539 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4540 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4542 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4543 return undef if !defined($product) || $product !~ s/^0x//;
4548 product
=> $product,
4554 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4563 my $name = $dev->{name
};
4565 my $fn = "$pcisysfs/devices/$name/reset";
4567 return file_write
($fn, "1");
4570 sub pci_dev_bind_to_stub
{
4573 my $name = $dev->{name
};
4575 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4576 return 1 if -d
$testdir;
4578 my $data = "$dev->{vendor} $dev->{product}";
4579 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4581 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4582 if (!file_write
($fn, $name)) {
4583 return undef if -f
$fn;
4586 $fn = "$pcisysfs/drivers/pci-stub/bind";
4587 if (! -d
$testdir) {
4588 return undef if !file_write
($fn, $name);
4594 sub pci_dev_bind_to_vfio
{
4597 my $name = $dev->{name
};
4599 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4601 if (!-d
$vfio_basedir) {
4602 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4604 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4606 my $testdir = "$vfio_basedir/$name";
4607 return 1 if -d
$testdir;
4609 my $data = "$dev->{vendor} $dev->{product}";
4610 return undef if !file_write
("$vfio_basedir/new_id", $data);
4612 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4613 if (!file_write
($fn, $name)) {
4614 return undef if -f
$fn;
4617 $fn = "$vfio_basedir/bind";
4618 if (! -d
$testdir) {
4619 return undef if !file_write
($fn, $name);
4625 sub pci_dev_group_bind_to_vfio
{
4628 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4630 if (!-d
$vfio_basedir) {
4631 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4633 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4635 # get IOMMU group devices
4636 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4637 my @devs = grep /^0000:/, readdir($D);
4640 foreach my $pciid (@devs) {
4641 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4643 # pci bridges, switches or root ports are not supported
4644 # they have a pci_bus subdirectory so skip them
4645 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4647 my $info = pci_device_info
($1);
4648 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4654 sub print_pci_addr
{
4655 my ($id, $bridges) = @_;
4659 piix3
=> { bus
=> 0, addr
=> 1 },
4660 #addr2 : first videocard
4661 balloon0
=> { bus
=> 0, addr
=> 3 },
4662 watchdog
=> { bus
=> 0, addr
=> 4 },
4663 scsihw0
=> { bus
=> 0, addr
=> 5 },
4664 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4665 scsihw1
=> { bus
=> 0, addr
=> 6 },
4666 ahci0
=> { bus
=> 0, addr
=> 7 },
4667 qga0
=> { bus
=> 0, addr
=> 8 },
4668 spice
=> { bus
=> 0, addr
=> 9 },
4669 virtio0
=> { bus
=> 0, addr
=> 10 },
4670 virtio1
=> { bus
=> 0, addr
=> 11 },
4671 virtio2
=> { bus
=> 0, addr
=> 12 },
4672 virtio3
=> { bus
=> 0, addr
=> 13 },
4673 virtio4
=> { bus
=> 0, addr
=> 14 },
4674 virtio5
=> { bus
=> 0, addr
=> 15 },
4675 hostpci0
=> { bus
=> 0, addr
=> 16 },
4676 hostpci1
=> { bus
=> 0, addr
=> 17 },
4677 net0
=> { bus
=> 0, addr
=> 18 },
4678 net1
=> { bus
=> 0, addr
=> 19 },
4679 net2
=> { bus
=> 0, addr
=> 20 },
4680 net3
=> { bus
=> 0, addr
=> 21 },
4681 net4
=> { bus
=> 0, addr
=> 22 },
4682 net5
=> { bus
=> 0, addr
=> 23 },
4683 vga1
=> { bus
=> 0, addr
=> 24 },
4684 vga2
=> { bus
=> 0, addr
=> 25 },
4685 vga3
=> { bus
=> 0, addr
=> 26 },
4686 hostpci2
=> { bus
=> 0, addr
=> 27 },
4687 hostpci3
=> { bus
=> 0, addr
=> 28 },
4688 #addr29 : usb-host (pve-usb.cfg)
4689 'pci.1' => { bus
=> 0, addr
=> 30 },
4690 'pci.2' => { bus
=> 0, addr
=> 31 },
4691 'net6' => { bus
=> 1, addr
=> 1 },
4692 'net7' => { bus
=> 1, addr
=> 2 },
4693 'net8' => { bus
=> 1, addr
=> 3 },
4694 'net9' => { bus
=> 1, addr
=> 4 },
4695 'net10' => { bus
=> 1, addr
=> 5 },
4696 'net11' => { bus
=> 1, addr
=> 6 },
4697 'net12' => { bus
=> 1, addr
=> 7 },
4698 'net13' => { bus
=> 1, addr
=> 8 },
4699 'net14' => { bus
=> 1, addr
=> 9 },
4700 'net15' => { bus
=> 1, addr
=> 10 },
4701 'net16' => { bus
=> 1, addr
=> 11 },
4702 'net17' => { bus
=> 1, addr
=> 12 },
4703 'net18' => { bus
=> 1, addr
=> 13 },
4704 'net19' => { bus
=> 1, addr
=> 14 },
4705 'net20' => { bus
=> 1, addr
=> 15 },
4706 'net21' => { bus
=> 1, addr
=> 16 },
4707 'net22' => { bus
=> 1, addr
=> 17 },
4708 'net23' => { bus
=> 1, addr
=> 18 },
4709 'net24' => { bus
=> 1, addr
=> 19 },
4710 'net25' => { bus
=> 1, addr
=> 20 },
4711 'net26' => { bus
=> 1, addr
=> 21 },
4712 'net27' => { bus
=> 1, addr
=> 22 },
4713 'net28' => { bus
=> 1, addr
=> 23 },
4714 'net29' => { bus
=> 1, addr
=> 24 },
4715 'net30' => { bus
=> 1, addr
=> 25 },
4716 'net31' => { bus
=> 1, addr
=> 26 },
4717 'virtio6' => { bus
=> 2, addr
=> 1 },
4718 'virtio7' => { bus
=> 2, addr
=> 2 },
4719 'virtio8' => { bus
=> 2, addr
=> 3 },
4720 'virtio9' => { bus
=> 2, addr
=> 4 },
4721 'virtio10' => { bus
=> 2, addr
=> 5 },
4722 'virtio11' => { bus
=> 2, addr
=> 6 },
4723 'virtio12' => { bus
=> 2, addr
=> 7 },
4724 'virtio13' => { bus
=> 2, addr
=> 8 },
4725 'virtio14' => { bus
=> 2, addr
=> 9 },
4726 'virtio15' => { bus
=> 2, addr
=> 10 },
4727 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4728 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4729 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4730 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4731 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4732 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4733 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4734 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4735 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4736 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4737 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4738 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4739 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4740 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4741 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4742 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4743 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4744 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4745 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4746 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4747 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4748 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4749 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4750 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4751 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4752 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4753 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4754 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4755 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4756 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4757 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4761 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4762 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4763 my $bus = $devices->{$id}->{bus
};
4764 $res = ",bus=pci.$bus,addr=$addr";
4765 $bridges->{$bus} = 1 if $bridges;
4771 sub print_pcie_addr
{
4776 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4777 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4778 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4779 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4782 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4783 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4784 my $bus = $devices->{$id}->{bus
};
4785 $res = ",bus=$bus,addr=$addr";
4791 # vzdump restore implementaion
4793 sub tar_archive_read_firstfile
{
4794 my $archive = shift;
4796 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4798 # try to detect archive type first
4799 my $pid = open (TMP
, "tar tf '$archive'|") ||
4800 die "unable to open file '$archive'\n";
4801 my $firstfile = <TMP
>;
4805 die "ERROR: archive contaions no data\n" if !$firstfile;
4811 sub tar_restore_cleanup
{
4812 my ($storecfg, $statfile) = @_;
4814 print STDERR
"starting cleanup\n";
4816 if (my $fd = IO
::File-
>new($statfile, "r")) {
4817 while (defined(my $line = <$fd>)) {
4818 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4821 if ($volid =~ m
|^/|) {
4822 unlink $volid || die 'unlink failed\n';
4824 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4826 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4828 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4830 print STDERR
"unable to parse line in statfile - $line";
4837 sub restore_archive
{
4838 my ($archive, $vmid, $user, $opts) = @_;
4840 my $format = $opts->{format
};
4843 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4844 $format = 'tar' if !$format;
4846 } elsif ($archive =~ m/\.tar$/) {
4847 $format = 'tar' if !$format;
4848 } elsif ($archive =~ m/.tar.lzo$/) {
4849 $format = 'tar' if !$format;
4851 } elsif ($archive =~ m/\.vma$/) {
4852 $format = 'vma' if !$format;
4853 } elsif ($archive =~ m/\.vma\.gz$/) {
4854 $format = 'vma' if !$format;
4856 } elsif ($archive =~ m/\.vma\.lzo$/) {
4857 $format = 'vma' if !$format;
4860 $format = 'vma' if !$format; # default
4863 # try to detect archive format
4864 if ($format eq 'tar') {
4865 return restore_tar_archive
($archive, $vmid, $user, $opts);
4867 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4871 sub restore_update_config_line
{
4872 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4874 return if $line =~ m/^\#qmdump\#/;
4875 return if $line =~ m/^\#vzdump\#/;
4876 return if $line =~ m/^lock:/;
4877 return if $line =~ m/^unused\d+:/;
4878 return if $line =~ m/^parent:/;
4879 return if $line =~ m/^template:/; # restored VM is never a template
4881 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4882 # try to convert old 1.X settings
4883 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4884 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4885 my ($model, $macaddr) = split(/\=/, $devconfig);
4886 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4889 bridge
=> "vmbr$ind",
4890 macaddr
=> $macaddr,
4892 my $netstr = print_net
($net);
4894 print $outfd "net$cookie->{netcount}: $netstr\n";
4895 $cookie->{netcount
}++;
4897 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4898 my ($id, $netstr) = ($1, $2);
4899 my $net = parse_net
($netstr);
4900 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4901 $netstr = print_net
($net);
4902 print $outfd "$id: $netstr\n";
4903 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4906 if ($line =~ m/backup=no/) {
4907 print $outfd "#$line";
4908 } elsif ($virtdev && $map->{$virtdev}) {
4909 my $di = parse_drive
($virtdev, $value);
4910 delete $di->{format
}; # format can change on restore
4911 $di->{file
} = $map->{$virtdev};
4912 $value = print_drive
($vmid, $di);
4913 print $outfd "$virtdev: $value\n";
4923 my ($cfg, $vmid) = @_;
4925 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4927 my $volid_hash = {};
4928 foreach my $storeid (keys %$info) {
4929 foreach my $item (@{$info->{$storeid}}) {
4930 next if !($item->{volid
} && $item->{size
});
4931 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4932 $volid_hash->{$item->{volid
}} = $item;
4939 sub get_used_paths
{
4940 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
4944 my $scan_config = sub {
4945 my ($cref, $snapname) = @_;
4947 foreach my $key (keys %$cref) {
4948 my $value = $cref->{$key};
4949 if (valid_drivename
($key)) {
4950 next if $skip_drive && $key eq $skip_drive;
4951 my $drive = parse_drive
($key, $value);
4952 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
4953 if ($drive->{file
} =~ m!^/!) {
4954 $used_path->{$drive->{file
}}++; # = 1;
4956 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
4958 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
4960 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
4961 $used_path->{$path}++; # = 1;
4967 &$scan_config($conf);
4971 if ($scan_snapshots) {
4972 foreach my $snapname (keys %{$conf->{snapshots
}}) {
4973 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
4980 sub update_disksize
{
4981 my ($vmid, $conf, $volid_hash) = @_;
4987 # Note: it is allowed to define multiple storages with same path (alias), so
4988 # we need to check both 'volid' and real 'path' (two different volid can point
4989 # to the same path).
4994 foreach my $opt (keys %$conf) {
4995 if (valid_drivename
($opt)) {
4996 my $drive = parse_drive
($opt, $conf->{$opt});
4997 my $volid = $drive->{file
};
5000 $used->{$volid} = 1;
5001 if ($volid_hash->{$volid} &&
5002 (my $path = $volid_hash->{$volid}->{path
})) {
5003 $usedpath->{$path} = 1;
5006 next if drive_is_cdrom
($drive);
5007 next if !$volid_hash->{$volid};
5009 $drive->{size
} = $volid_hash->{$volid}->{size
};
5010 my $new = print_drive
($vmid, $drive);
5011 if ($new ne $conf->{$opt}) {
5013 $conf->{$opt} = $new;
5018 # remove 'unusedX' entry if volume is used
5019 foreach my $opt (keys %$conf) {
5020 next if $opt !~ m/^unused\d+$/;
5021 my $volid = $conf->{$opt};
5022 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5023 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5025 delete $conf->{$opt};
5029 foreach my $volid (sort keys %$volid_hash) {
5030 next if $volid =~ m/vm-$vmid-state-/;
5031 next if $used->{$volid};
5032 my $path = $volid_hash->{$volid}->{path
};
5033 next if !$path; # just to be sure
5034 next if $usedpath->{$path};
5036 add_unused_volume
($conf, $volid);
5037 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5044 my ($vmid, $nolock) = @_;
5046 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5048 my $volid_hash = scan_volids
($cfg, $vmid);
5050 my $updatefn = sub {
5053 my $conf = load_config
($vmid);
5058 foreach my $volid (keys %$volid_hash) {
5059 my $info = $volid_hash->{$volid};
5060 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5063 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5065 update_config_nolock
($vmid, $conf, 1) if $changes;
5068 if (defined($vmid)) {
5072 lock_config
($vmid, $updatefn, $vmid);
5075 my $vmlist = config_list
();
5076 foreach my $vmid (keys %$vmlist) {
5080 lock_config
($vmid, $updatefn, $vmid);
5086 sub restore_vma_archive
{
5087 my ($archive, $vmid, $user, $opts, $comp) = @_;
5089 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5090 my $readfrom = $archive;
5095 my $qarchive = PVE
::Tools
::shellquote
($archive);
5096 if ($comp eq 'gzip') {
5097 $uncomp = "zcat $qarchive|";
5098 } elsif ($comp eq 'lzop') {
5099 $uncomp = "lzop -d -c $qarchive|";
5101 die "unknown compression method '$comp'\n";
5106 my $tmpdir = "/var/tmp/vzdumptmp$$";
5109 # disable interrupts (always do cleanups)
5110 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5111 warn "got interrupt - ignored\n";
5114 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5115 POSIX
::mkfifo
($mapfifo, 0600);
5118 my $openfifo = sub {
5119 open($fifofh, '>', $mapfifo) || die $!;
5122 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5129 my $rpcenv = PVE
::RPCEnvironment
::get
();
5131 my $conffile = config_file
($vmid);
5132 my $tmpfn = "$conffile.$$.tmp";
5134 # Note: $oldconf is undef if VM does not exists
5135 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5137 my $print_devmap = sub {
5138 my $virtdev_hash = {};
5140 my $cfgfn = "$tmpdir/qemu-server.conf";
5142 # we can read the config - that is already extracted
5143 my $fh = IO
::File-
>new($cfgfn, "r") ||
5144 "unable to read qemu-server.conf - $!\n";
5146 while (defined(my $line = <$fh>)) {
5147 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5148 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5149 die "archive does not contain data for drive '$virtdev'\n"
5150 if !$devinfo->{$devname};
5151 if (defined($opts->{storage
})) {
5152 $storeid = $opts->{storage
} || 'local';
5153 } elsif (!$storeid) {
5156 $format = 'raw' if !$format;
5157 $devinfo->{$devname}->{devname
} = $devname;
5158 $devinfo->{$devname}->{virtdev
} = $virtdev;
5159 $devinfo->{$devname}->{format
} = $format;
5160 $devinfo->{$devname}->{storeid
} = $storeid;
5162 # check permission on storage
5163 my $pool = $opts->{pool
}; # todo: do we need that?
5164 if ($user ne 'root@pam') {
5165 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5168 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5172 foreach my $devname (keys %$devinfo) {
5173 die "found no device mapping information for device '$devname'\n"
5174 if !$devinfo->{$devname}->{virtdev
};
5177 my $cfg = cfs_read_file
('storage.cfg');
5179 # create empty/temp config
5181 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5182 foreach_drive
($oldconf, sub {
5183 my ($ds, $drive) = @_;
5185 return if drive_is_cdrom
($drive);
5187 my $volid = $drive->{file
};
5189 return if !$volid || $volid =~ m
|^/|;
5191 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5192 return if !$path || !$owner || ($owner != $vmid);
5194 # Note: only delete disk we want to restore
5195 # other volumes will become unused
5196 if ($virtdev_hash->{$ds}) {
5197 PVE
::Storage
::vdisk_free
($cfg, $volid);
5203 foreach my $virtdev (sort keys %$virtdev_hash) {
5204 my $d = $virtdev_hash->{$virtdev};
5205 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5206 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5208 # test if requested format is supported
5209 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5210 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5211 $d->{format
} = $defFormat if !$supported;
5213 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5214 $d->{format
}, undef, $alloc_size);
5215 print STDERR
"new volume ID is '$volid'\n";
5216 $d->{volid
} = $volid;
5217 my $path = PVE
::Storage
::path
($cfg, $volid);
5219 my $write_zeros = 1;
5220 # fixme: what other storages types initialize volumes with zero?
5221 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5222 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5226 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5228 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5229 $map->{$virtdev} = $volid;
5232 $fh->seek(0, 0) || die "seek failed - $!\n";
5234 my $outfd = new IO
::File
($tmpfn, "w") ||
5235 die "unable to write config for VM $vmid\n";
5237 my $cookie = { netcount
=> 0 };
5238 while (defined(my $line = <$fh>)) {
5239 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5248 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5249 die "interrupted by signal\n";
5251 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5253 $oldtimeout = alarm($timeout);
5260 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5261 my ($dev_id, $size, $devname) = ($1, $2, $3);
5262 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5263 } elsif ($line =~ m/^CTIME: /) {
5264 # we correctly received the vma config, so we can disable
5265 # the timeout now for disk allocation (set to 10 minutes, so
5266 # that we always timeout if something goes wrong)
5269 print $fifofh "done\n";
5270 my $tmp = $oldtimeout || 0;
5271 $oldtimeout = undef;
5277 print "restore vma archive: $cmd\n";
5278 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5282 alarm($oldtimeout) if $oldtimeout;
5290 my $cfg = cfs_read_file
('storage.cfg');
5291 foreach my $devname (keys %$devinfo) {
5292 my $volid = $devinfo->{$devname}->{volid
};
5295 if ($volid =~ m
|^/|) {
5296 unlink $volid || die 'unlink failed\n';
5298 PVE
::Storage
::vdisk_free
($cfg, $volid);
5300 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5302 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5309 rename($tmpfn, $conffile) ||
5310 die "unable to commit configuration file '$conffile'\n";
5312 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5314 eval { rescan
($vmid, 1); };
5318 sub restore_tar_archive
{
5319 my ($archive, $vmid, $user, $opts) = @_;
5321 if ($archive ne '-') {
5322 my $firstfile = tar_archive_read_firstfile
($archive);
5323 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5324 if $firstfile ne 'qemu-server.conf';
5327 my $storecfg = cfs_read_file
('storage.cfg');
5329 # destroy existing data - keep empty config
5330 my $vmcfgfn = config_file
($vmid);
5331 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5333 my $tocmd = "/usr/lib/qemu-server/qmextract";
5335 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5336 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5337 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5338 $tocmd .= ' --info' if $opts->{info
};
5340 # tar option "xf" does not autodetect compression when read from STDIN,
5341 # so we pipe to zcat
5342 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5343 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5345 my $tmpdir = "/var/tmp/vzdumptmp$$";
5348 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5349 local $ENV{VZDUMP_VMID
} = $vmid;
5350 local $ENV{VZDUMP_USER
} = $user;
5352 my $conffile = config_file
($vmid);
5353 my $tmpfn = "$conffile.$$.tmp";
5355 # disable interrupts (always do cleanups)
5356 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5357 print STDERR
"got interrupt - ignored\n";
5362 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5363 die "interrupted by signal\n";
5366 if ($archive eq '-') {
5367 print "extracting archive from STDIN\n";
5368 run_command
($cmd, input
=> "<&STDIN");
5370 print "extracting archive '$archive'\n";
5374 return if $opts->{info
};
5378 my $statfile = "$tmpdir/qmrestore.stat";
5379 if (my $fd = IO
::File-
>new($statfile, "r")) {
5380 while (defined (my $line = <$fd>)) {
5381 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5382 $map->{$1} = $2 if $1;
5384 print STDERR
"unable to parse line in statfile - $line\n";
5390 my $confsrc = "$tmpdir/qemu-server.conf";
5392 my $srcfd = new IO
::File
($confsrc, "r") ||
5393 die "unable to open file '$confsrc'\n";
5395 my $outfd = new IO
::File
($tmpfn, "w") ||
5396 die "unable to write config for VM $vmid\n";
5398 my $cookie = { netcount
=> 0 };
5399 while (defined (my $line = <$srcfd>)) {
5400 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5412 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5419 rename $tmpfn, $conffile ||
5420 die "unable to commit configuration file '$conffile'\n";
5422 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5424 eval { rescan
($vmid, 1); };
5429 # Internal snapshots
5431 # NOTE: Snapshot create/delete involves several non-atomic
5432 # action, and can take a long time.
5433 # So we try to avoid locking the file and use 'lock' variable
5434 # inside the config file instead.
5436 my $snapshot_copy_config = sub {
5437 my ($source, $dest) = @_;
5439 foreach my $k (keys %$source) {
5440 next if $k eq 'snapshots';
5441 next if $k eq 'snapstate';
5442 next if $k eq 'snaptime';
5443 next if $k eq 'vmstate';
5444 next if $k eq 'lock';
5445 next if $k eq 'digest';
5446 next if $k eq 'description';
5447 next if $k =~ m/^unused\d+$/;
5449 $dest->{$k} = $source->{$k};
5453 my $snapshot_apply_config = sub {
5454 my ($conf, $snap) = @_;
5456 # copy snapshot list
5458 snapshots
=> $conf->{snapshots
},
5461 # keep description and list of unused disks
5462 foreach my $k (keys %$conf) {
5463 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5464 $newconf->{$k} = $conf->{$k};
5467 &$snapshot_copy_config($snap, $newconf);
5472 sub foreach_writable_storage
{
5473 my ($conf, $func) = @_;
5477 foreach my $ds (keys %$conf) {
5478 next if !valid_drivename
($ds);
5480 my $drive = parse_drive
($ds, $conf->{$ds});
5482 next if drive_is_cdrom
($drive);
5484 my $volid = $drive->{file
};
5486 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5487 $sidhash->{$sid} = $sid if $sid;
5490 foreach my $sid (sort keys %$sidhash) {
5495 my $alloc_vmstate_volid = sub {
5496 my ($storecfg, $vmid, $conf, $snapname) = @_;
5498 # Note: we try to be smart when selecting a $target storage
5502 # search shared storage first
5503 foreach_writable_storage
($conf, sub {
5505 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5506 return if !$scfg->{shared
};
5508 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5512 # now search local storage
5513 foreach_writable_storage
($conf, sub {
5515 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5516 return if $scfg->{shared
};
5518 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5522 $target = 'local' if !$target;
5524 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5525 # we abort live save after $conf->{memory}, so we need at max twice that space
5526 my $size = $conf->{memory
}*2 + $driver_state_size;
5528 my $name = "vm-$vmid-state-$snapname";
5529 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5530 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5531 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5536 my $snapshot_prepare = sub {
5537 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5541 my $updatefn = sub {
5543 my $conf = load_config
($vmid);
5545 die "you can't take a snapshot if it's a template\n"
5546 if is_template
($conf);
5550 $conf->{lock} = 'snapshot';
5552 die "snapshot name '$snapname' already used\n"
5553 if defined($conf->{snapshots
}->{$snapname});
5555 my $storecfg = PVE
::Storage
::config
();
5556 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5558 $snap = $conf->{snapshots
}->{$snapname} = {};
5560 if ($save_vmstate && check_running
($vmid)) {
5561 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5564 &$snapshot_copy_config($conf, $snap);
5566 $snap->{snapstate
} = "prepare";
5567 $snap->{snaptime
} = time();
5568 $snap->{description
} = $comment if $comment;
5570 # always overwrite machine if we save vmstate. This makes sure we
5571 # can restore it later using correct machine type
5572 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5574 update_config_nolock
($vmid, $conf, 1);
5577 lock_config
($vmid, $updatefn);
5582 my $snapshot_commit = sub {
5583 my ($vmid, $snapname) = @_;
5585 my $updatefn = sub {
5587 my $conf = load_config
($vmid);
5589 die "missing snapshot lock\n"
5590 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5592 my $has_machine_config = defined($conf->{machine
});
5594 my $snap = $conf->{snapshots
}->{$snapname};
5596 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5598 die "wrong snapshot state\n"
5599 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5601 delete $snap->{snapstate
};
5602 delete $conf->{lock};
5604 my $newconf = &$snapshot_apply_config($conf, $snap);
5606 delete $newconf->{machine
} if !$has_machine_config;
5608 $newconf->{parent
} = $snapname;
5610 update_config_nolock
($vmid, $newconf, 1);
5613 lock_config
($vmid, $updatefn);
5616 sub snapshot_rollback
{
5617 my ($vmid, $snapname) = @_;
5621 my $storecfg = PVE
::Storage
::config
();
5623 my $conf = load_config
($vmid);
5625 my $get_snapshot_config = sub {
5627 die "you can't rollback if vm is a template\n" if is_template
($conf);
5629 my $res = $conf->{snapshots
}->{$snapname};
5631 die "snapshot '$snapname' does not exist\n" if !defined($res);
5636 my $snap = &$get_snapshot_config();
5638 foreach_drive
($snap, sub {
5639 my ($ds, $drive) = @_;
5641 return if drive_is_cdrom
($drive);
5643 my $volid = $drive->{file
};
5645 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5648 my $updatefn = sub {
5650 $conf = load_config
($vmid);
5652 $snap = &$get_snapshot_config();
5654 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5655 if $snap->{snapstate
};
5659 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5662 die "unable to rollback vm $vmid: vm is running\n"
5663 if check_running
($vmid);
5666 $conf->{lock} = 'rollback';
5668 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5669 delete $conf->{lock};
5675 my $has_machine_config = defined($conf->{machine
});
5677 # copy snapshot config to current config
5678 $conf = &$snapshot_apply_config($conf, $snap);
5679 $conf->{parent
} = $snapname;
5681 # Note: old code did not store 'machine', so we try to be smart
5682 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5683 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5684 # we remove the 'machine' configuration if not explicitly specified
5685 # in the original config.
5686 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5689 update_config_nolock
($vmid, $conf, 1);
5691 if (!$prepare && $snap->{vmstate
}) {
5692 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5693 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5697 lock_config
($vmid, $updatefn);
5699 foreach_drive
($snap, sub {
5700 my ($ds, $drive) = @_;
5702 return if drive_is_cdrom
($drive);
5704 my $volid = $drive->{file
};
5705 my $device = "drive-$ds";
5707 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5711 lock_config
($vmid, $updatefn);
5714 my $savevm_wait = sub {
5718 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5719 if (!$stat->{status
}) {
5720 die "savevm not active\n";
5721 } elsif ($stat->{status
} eq 'active') {
5724 } elsif ($stat->{status
} eq 'completed') {
5727 die "query-savevm returned status '$stat->{status}'\n";
5732 sub do_snapshots_with_qemu
{
5733 my ($storecfg, $volid) = @_;
5735 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5737 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5741 if ($volid =~ m/\.(qcow2|qed)$/){
5748 sub snapshot_create
{
5749 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5751 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5753 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5755 my $config = load_config
($vmid);
5757 my $running = check_running
($vmid);
5759 my $freezefs = $running && $config->{agent
};
5760 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5765 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5766 warn "guest-fsfreeze-freeze problems - $@" if $@;
5770 # create internal snapshots of all drives
5772 my $storecfg = PVE
::Storage
::config
();
5775 if ($snap->{vmstate
}) {
5776 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5777 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5778 &$savevm_wait($vmid);
5780 vm_mon_cmd
($vmid, "savevm-start");
5784 foreach_drive
($snap, sub {
5785 my ($ds, $drive) = @_;
5787 return if drive_is_cdrom
($drive);
5789 my $volid = $drive->{file
};
5790 my $device = "drive-$ds";
5792 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5793 $drivehash->{$ds} = 1;
5799 eval { vm_mon_cmd
($vmid, "savevm-end") };
5803 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5804 warn "guest-fsfreeze-thaw problems - $@" if $@;
5807 # savevm-end is async, we need to wait
5809 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5810 if (!$stat->{bytes
}) {
5813 print "savevm not yet finished\n";
5821 warn "snapshot create failed: starting cleanup\n";
5822 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5827 &$snapshot_commit($vmid, $snapname);
5830 # Note: $drivehash is only set when called from snapshot_create.
5831 sub snapshot_delete
{
5832 my ($vmid, $snapname, $force, $drivehash) = @_;
5839 my $unlink_parent = sub {
5840 my ($confref, $new_parent) = @_;
5842 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5844 $confref->{parent
} = $new_parent;
5846 delete $confref->{parent
};
5851 my $updatefn = sub {
5852 my ($remove_drive) = @_;
5854 my $conf = load_config
($vmid);
5858 die "you can't delete a snapshot if vm is a template\n"
5859 if is_template
($conf);
5862 $snap = $conf->{snapshots
}->{$snapname};
5864 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5866 # remove parent refs
5868 &$unlink_parent($conf, $snap->{parent
});
5869 foreach my $sn (keys %{$conf->{snapshots
}}) {
5870 next if $sn eq $snapname;
5871 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5875 if ($remove_drive) {
5876 if ($remove_drive eq 'vmstate') {
5877 delete $snap->{$remove_drive};
5879 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5880 my $volid = $drive->{file
};
5881 delete $snap->{$remove_drive};
5882 add_unused_volume
($conf, $volid);
5887 $snap->{snapstate
} = 'delete';
5889 delete $conf->{snapshots
}->{$snapname};
5890 delete $conf->{lock} if $drivehash;
5891 foreach my $volid (@$unused) {
5892 add_unused_volume
($conf, $volid);
5896 update_config_nolock
($vmid, $conf, 1);
5899 lock_config
($vmid, $updatefn);
5901 # now remove vmstate file
5903 my $storecfg = PVE
::Storage
::config
();
5905 if ($snap->{vmstate
}) {
5906 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5908 die $err if !$force;
5911 # save changes (remove vmstate from snapshot)
5912 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5915 # now remove all internal snapshots
5916 foreach_drive
($snap, sub {
5917 my ($ds, $drive) = @_;
5919 return if drive_is_cdrom
($drive);
5921 my $volid = $drive->{file
};
5922 my $device = "drive-$ds";
5924 if (!$drivehash || $drivehash->{$ds}) {
5925 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
5927 die $err if !$force;
5932 # save changes (remove drive fron snapshot)
5933 lock_config
($vmid, $updatefn, $ds) if !$force;
5934 push @$unused, $volid;
5937 # now cleanup config
5939 lock_config
($vmid, $updatefn);
5943 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
5946 foreach_drive
($conf, sub {
5947 my ($ds, $drive) = @_;
5949 return if drive_is_cdrom
($drive);
5950 my $volid = $drive->{file
};
5951 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
5954 return $err ?
0 : 1;
5957 sub template_create
{
5958 my ($vmid, $conf, $disk) = @_;
5960 my $storecfg = PVE
::Storage
::config
();
5962 foreach_drive
($conf, sub {
5963 my ($ds, $drive) = @_;
5965 return if drive_is_cdrom
($drive);
5966 return if $disk && $ds ne $disk;
5968 my $volid = $drive->{file
};
5969 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5971 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5972 $drive->{file
} = $voliddst;
5973 $conf->{$ds} = print_drive
($vmid, $drive);
5974 update_config_nolock
($vmid, $conf, 1);
5981 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
5984 sub qemu_img_convert
{
5985 my ($src_volid, $dst_volid, $size, $snapname) = @_;
5987 my $storecfg = PVE
::Storage
::config
();
5988 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5989 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5991 if ($src_storeid && $dst_storeid) {
5992 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5993 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5995 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5996 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5998 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5999 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6002 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6003 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6004 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6008 if($line =~ m/\((\S+)\/100\
%\)/){
6010 my $transferred = int($size * $percent / 100);
6011 my $remaining = $size - $transferred;
6013 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6018 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6020 die "copy failed: $err" if $err;
6024 sub qemu_img_format
{
6025 my ($scfg, $volname) = @_;
6027 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6034 sub qemu_drive_mirror
{
6035 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6037 my $storecfg = PVE
::Storage
::config
();
6038 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6040 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6042 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6044 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6046 #drive-mirror is doing lseek on source image before starting, and this can take a lot of time for big nfs volume
6047 #during this time, qmp socket is hanging
6048 #http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg01838.html
6049 #so we need to setup a big timeout
6050 my $opts = { timeout
=> 14400, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6051 $opts->{format
} = $format if $format;
6053 print "drive mirror is starting : this step can take some minutes/hours, depend of disk size and storage speed\n";
6055 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6058 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6059 my $stat = @$stats[0];
6060 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6061 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6063 my $busy = $stat->{busy
};
6064 my $ready = $stat->{ready
};
6066 if (my $total = $stat->{len
}) {
6067 my $transferred = $stat->{offset
} || 0;
6068 my $remaining = $total - $transferred;
6069 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6071 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6075 if ($stat->{ready
} eq 'true') {
6077 last if $vmiddst != $vmid;
6079 # try to switch the disk if source and destination are on the same guest
6080 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6082 die $@ if $@ !~ m/cannot be completed/;
6091 my $cancel_job = sub {
6092 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6094 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6095 my $stat = @$stats[0];
6102 eval { &$cancel_job(); };
6103 die "mirroring error: $err";
6106 if ($vmiddst != $vmid) {
6107 # if we clone a disk for a new target vm, we don't switch the disk
6108 &$cancel_job(); # so we call block-job-cancel
6113 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6114 $newvmid, $storage, $format, $full, $newvollist) = @_;
6119 print "create linked clone of drive $drivename ($drive->{file})\n";
6120 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6121 push @$newvollist, $newvolid;
6123 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6124 $storeid = $storage if $storage;
6126 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6128 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6129 $format = qemu_img_format
($scfg, $volname);
6132 # test if requested format is supported - else use default
6133 my $supported = grep { $_ eq $format } @$validFormats;
6134 $format = $defFormat if !$supported;
6136 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6138 print "create full clone of drive $drivename ($drive->{file})\n";
6139 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6140 push @$newvollist, $newvolid;
6142 if (!$running || $snapname) {
6143 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6145 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6149 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6152 $disk->{format
} = undef;
6153 $disk->{file
} = $newvolid;
6154 $disk->{size
} = $size;
6159 # this only works if VM is running
6160 sub get_current_qemu_machine
{
6163 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6164 my $res = vm_qmp_command
($vmid, $cmd);
6166 my ($current, $default);
6167 foreach my $e (@$res) {
6168 $default = $e->{name
} if $e->{'is-default'};
6169 $current = $e->{name
} if $e->{'is-current'};
6172 # fallback to the default machine if current is not supported by qemu
6173 return $current || $default || 'pc';
6176 sub qemu_machine_feature_enabled
{
6177 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6182 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6184 $current_major = $3;
6185 $current_minor = $4;
6187 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6189 $current_major = $1;
6190 $current_minor = $2;
6193 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6202 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6203 my (undef, $id, $function) = @_;
6204 my $res = { id
=> $id, function
=> $function};
6205 push @{$devices->{$id}}, $res;
6211 sub vm_iothreads_list
{
6214 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6217 foreach my $iothread (@$res) {
6218 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6225 my ($conf, $drive) = @_;
6229 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6231 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6237 my $controller = int($drive->{index} / $maxdev);
6238 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6240 return ($maxdev, $controller, $controller_prefix);