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 split_flagged_list
{
1431 my $text = shift || '';
1432 $text =~ s/[,;]/ /g;
1434 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1437 sub join_flagged_list
{
1438 my ($how, $lst) = @_;
1439 join $how, map { $lst->{$_} . $_ } keys %$lst;
1442 sub vmconfig_delete_pending_option
{
1443 my ($conf, $key, $force) = @_;
1445 delete $conf->{pending
}->{$key};
1446 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1447 $pending_delete_hash->{$key} = $force ?
'!' : '';
1448 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1451 sub vmconfig_undelete_pending_option
{
1452 my ($conf, $key) = @_;
1454 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1455 delete $pending_delete_hash->{$key};
1457 if (%$pending_delete_hash) {
1458 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1460 delete $conf->{pending
}->{delete};
1464 sub vmconfig_register_unused_drive
{
1465 my ($storecfg, $vmid, $conf, $drive) = @_;
1467 if (!drive_is_cdrom
($drive)) {
1468 my $volid = $drive->{file
};
1469 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1470 add_unused_volume
($conf, $volid, $vmid);
1475 sub vmconfig_cleanup_pending
{
1478 # remove pending changes when nothing changed
1480 foreach my $opt (keys %{$conf->{pending
}}) {
1481 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1483 delete $conf->{pending
}->{$opt};
1487 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1488 my $pending_delete_hash = {};
1489 while (my ($opt, $force) = each %$current_delete_hash) {
1490 if (defined($conf->{$opt})) {
1491 $pending_delete_hash->{$opt} = $force;
1497 if (%$pending_delete_hash) {
1498 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1500 delete $conf->{pending
}->{delete};
1506 my $valid_smbios1_options = {
1507 manufacturer
=> '\S+',
1511 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1516 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1522 foreach my $kvp (split(/,/, $data)) {
1523 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1524 my ($k, $v) = split(/=/, $kvp);
1525 return undef if !defined($k) || !defined($v);
1526 return undef if !$valid_smbios1_options->{$k};
1527 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1538 foreach my $k (keys %$smbios1) {
1539 next if !defined($smbios1->{$k});
1540 next if !$valid_smbios1_options->{$k};
1541 $data .= ',' if $data;
1542 $data .= "$k=$smbios1->{$k}";
1547 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1548 sub verify_smbios1
{
1549 my ($value, $noerr) = @_;
1551 return $value if parse_smbios1
($value);
1553 return undef if $noerr;
1555 die "unable to parse smbios (type 1) options\n";
1558 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1559 sub verify_bootdisk
{
1560 my ($value, $noerr) = @_;
1562 return $value if valid_drivename
($value);
1564 return undef if $noerr;
1566 die "invalid boot disk '$value'\n";
1569 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1571 my ($value, $noerr) = @_;
1573 return $value if parse_numa
($value);
1575 return undef if $noerr;
1577 die "unable to parse numa options\n";
1580 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1582 my ($value, $noerr) = @_;
1584 return $value if parse_net
($value);
1586 return undef if $noerr;
1588 die "unable to parse network options\n";
1591 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1593 my ($value, $noerr) = @_;
1595 return $value if parse_drive
(undef, $value);
1597 return undef if $noerr;
1599 die "unable to parse drive options\n";
1602 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1603 sub verify_hostpci
{
1604 my ($value, $noerr) = @_;
1606 return $value if parse_hostpci
($value);
1608 return undef if $noerr;
1610 die "unable to parse pci id\n";
1613 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1614 sub verify_watchdog
{
1615 my ($value, $noerr) = @_;
1617 return $value if parse_watchdog
($value);
1619 return undef if $noerr;
1621 die "unable to parse watchdog options\n";
1624 sub parse_watchdog
{
1627 return undef if !$value;
1631 foreach my $p (split(/,/, $value)) {
1632 next if $p =~ m/^\s*$/;
1634 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1636 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1637 $res->{action
} = $2;
1646 sub parse_usb_device
{
1649 return undef if !$value;
1651 my @dl = split(/,/, $value);
1655 foreach my $v (@dl) {
1656 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1658 $res->{vendorid
} = $2;
1659 $res->{productid
} = $4;
1660 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1662 $res->{hostbus
} = $1;
1663 $res->{hostport
} = $2;
1664 } elsif ($v =~ m/^spice$/) {
1671 return undef if !$found;
1676 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1677 sub verify_usb_device
{
1678 my ($value, $noerr) = @_;
1680 return $value if parse_usb_device
($value);
1682 return undef if $noerr;
1684 die "unable to parse usb device\n";
1687 # add JSON properties for create and set function
1688 sub json_config_properties
{
1691 foreach my $opt (keys %$confdesc) {
1692 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1693 $prop->{$opt} = $confdesc->{$opt};
1700 my ($key, $value) = @_;
1702 die "unknown setting '$key'\n" if !$confdesc->{$key};
1704 my $type = $confdesc->{$key}->{type
};
1706 if (!defined($value)) {
1707 die "got undefined value\n";
1710 if ($value =~ m/[\n\r]/) {
1711 die "property contains a line feed\n";
1714 if ($type eq 'boolean') {
1715 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1716 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1717 die "type check ('boolean') failed - got '$value'\n";
1718 } elsif ($type eq 'integer') {
1719 return int($1) if $value =~ m/^(\d+)$/;
1720 die "type check ('integer') failed - got '$value'\n";
1721 } elsif ($type eq 'number') {
1722 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1723 die "type check ('number') failed - got '$value'\n";
1724 } elsif ($type eq 'string') {
1725 if (my $fmt = $confdesc->{$key}->{format
}) {
1726 if ($fmt eq 'pve-qm-drive') {
1727 # special case - we need to pass $key to parse_drive()
1728 my $drive = parse_drive
($key, $value);
1729 return $value if $drive;
1730 die "unable to parse drive options\n";
1732 PVE
::JSONSchema
::check_format
($fmt, $value);
1735 $value =~ s/^\"(.*)\"$/$1/;
1738 die "internal error"
1742 sub lock_config_full
{
1743 my ($vmid, $timeout, $code, @param) = @_;
1745 my $filename = config_file_lock
($vmid);
1747 my $res = lock_file
($filename, $timeout, $code, @param);
1754 sub lock_config_mode
{
1755 my ($vmid, $timeout, $shared, $code, @param) = @_;
1757 my $filename = config_file_lock
($vmid);
1759 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1767 my ($vmid, $code, @param) = @_;
1769 return lock_config_full
($vmid, 10, $code, @param);
1772 sub cfs_config_path
{
1773 my ($vmid, $node) = @_;
1775 $node = $nodename if !$node;
1776 return "nodes/$node/qemu-server/$vmid.conf";
1779 sub check_iommu_support
{
1780 #fixme : need to check IOMMU support
1781 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1789 my ($vmid, $node) = @_;
1791 my $cfspath = cfs_config_path
($vmid, $node);
1792 return "/etc/pve/$cfspath";
1795 sub config_file_lock
{
1798 return "$lock_dir/lock-$vmid.conf";
1804 my $conf = config_file
($vmid);
1805 utime undef, undef, $conf;
1809 my ($storecfg, $vmid, $keep_empty_config) = @_;
1811 my $conffile = config_file
($vmid);
1813 my $conf = load_config
($vmid);
1817 # only remove disks owned by this VM
1818 foreach_drive
($conf, sub {
1819 my ($ds, $drive) = @_;
1821 return if drive_is_cdrom
($drive);
1823 my $volid = $drive->{file
};
1825 return if !$volid || $volid =~ m
|^/|;
1827 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1828 return if !$path || !$owner || ($owner != $vmid);
1830 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1833 if ($keep_empty_config) {
1834 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1839 # also remove unused disk
1841 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1844 PVE
::Storage
::foreach_volid
($dl, sub {
1845 my ($volid, $sid, $volname, $d) = @_;
1846 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1856 my ($vmid, $node) = @_;
1858 my $cfspath = cfs_config_path
($vmid, $node);
1860 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1862 die "no such VM ('$vmid')\n" if !defined($conf);
1867 sub parse_vm_config
{
1868 my ($filename, $raw) = @_;
1870 return undef if !defined($raw);
1873 digest
=> Digest
::SHA
::sha1_hex
($raw),
1878 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1879 || die "got strange filename '$filename'";
1887 my @lines = split(/\n/, $raw);
1888 foreach my $line (@lines) {
1889 next if $line =~ m/^\s*$/;
1891 if ($line =~ m/^\[PENDING\]\s*$/i) {
1892 $section = 'pending';
1893 if (defined($descr)) {
1895 $conf->{description
} = $descr;
1898 $conf = $res->{$section} = {};
1901 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1903 if (defined($descr)) {
1905 $conf->{description
} = $descr;
1908 $conf = $res->{snapshots
}->{$section} = {};
1912 if ($line =~ m/^\#(.*)\s*$/) {
1913 $descr = '' if !defined($descr);
1914 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1918 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1919 $descr = '' if !defined($descr);
1920 $descr .= PVE
::Tools
::decode_text
($2);
1921 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1922 $conf->{snapstate
} = $1;
1923 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1926 $conf->{$key} = $value;
1927 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1929 if ($section eq 'pending') {
1930 $conf->{delete} = $value; # we parse this later
1932 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1934 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1937 eval { $value = check_type
($key, $value); };
1939 warn "vm $vmid - unable to parse value of '$key' - $@";
1941 my $fmt = $confdesc->{$key}->{format
};
1942 if ($fmt && $fmt eq 'pve-qm-drive') {
1943 my $v = parse_drive
($key, $value);
1944 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1945 $v->{file
} = $volid;
1946 $value = print_drive
($vmid, $v);
1948 warn "vm $vmid - unable to parse value of '$key'\n";
1953 if ($key eq 'cdrom') {
1954 $conf->{ide2
} = $value;
1956 $conf->{$key} = $value;
1962 if (defined($descr)) {
1964 $conf->{description
} = $descr;
1966 delete $res->{snapstate
}; # just to be sure
1971 sub write_vm_config
{
1972 my ($filename, $conf) = @_;
1974 delete $conf->{snapstate
}; # just to be sure
1976 if ($conf->{cdrom
}) {
1977 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1978 $conf->{ide2
} = $conf->{cdrom
};
1979 delete $conf->{cdrom
};
1982 # we do not use 'smp' any longer
1983 if ($conf->{sockets
}) {
1984 delete $conf->{smp
};
1985 } elsif ($conf->{smp
}) {
1986 $conf->{sockets
} = $conf->{smp
};
1987 delete $conf->{cores
};
1988 delete $conf->{smp
};
1991 my $used_volids = {};
1993 my $cleanup_config = sub {
1994 my ($cref, $pending, $snapname) = @_;
1996 foreach my $key (keys %$cref) {
1997 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1998 $key eq 'snapstate' || $key eq 'pending';
1999 my $value = $cref->{$key};
2000 if ($key eq 'delete') {
2001 die "propertry 'delete' is only allowed in [PENDING]\n"
2003 # fixme: check syntax?
2006 eval { $value = check_type
($key, $value); };
2007 die "unable to parse value of '$key' - $@" if $@;
2009 $cref->{$key} = $value;
2011 if (!$snapname && valid_drivename
($key)) {
2012 my $drive = parse_drive
($key, $value);
2013 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2018 &$cleanup_config($conf);
2020 &$cleanup_config($conf->{pending
}, 1);
2022 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2023 die "internal error" if $snapname eq 'pending';
2024 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2027 # remove 'unusedX' settings if we re-add a volume
2028 foreach my $key (keys %$conf) {
2029 my $value = $conf->{$key};
2030 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2031 delete $conf->{$key};
2035 my $generate_raw_config = sub {
2036 my ($conf, $pending) = @_;
2040 # add description as comment to top of file
2041 if (defined(my $descr = $conf->{description
})) {
2043 foreach my $cl (split(/\n/, $descr)) {
2044 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2047 $raw .= "#\n" if $pending;
2051 foreach my $key (sort keys %$conf) {
2052 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2053 $raw .= "$key: $conf->{$key}\n";
2058 my $raw = &$generate_raw_config($conf);
2060 if (scalar(keys %{$conf->{pending
}})){
2061 $raw .= "\n[PENDING]\n";
2062 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2065 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2066 $raw .= "\n[$snapname]\n";
2067 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2073 sub update_config_nolock
{
2074 my ($vmid, $conf, $skiplock) = @_;
2076 check_lock
($conf) if !$skiplock;
2078 my $cfspath = cfs_config_path
($vmid);
2080 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2084 my ($vmid, $conf, $skiplock) = @_;
2086 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2093 # we use static defaults from our JSON schema configuration
2094 foreach my $key (keys %$confdesc) {
2095 if (defined(my $default = $confdesc->{$key}->{default})) {
2096 $res->{$key} = $default;
2100 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2101 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2107 my $vmlist = PVE
::Cluster
::get_vmlist
();
2109 return $res if !$vmlist || !$vmlist->{ids
};
2110 my $ids = $vmlist->{ids
};
2112 foreach my $vmid (keys %$ids) {
2113 my $d = $ids->{$vmid};
2114 next if !$d->{node
} || $d->{node
} ne $nodename;
2115 next if !$d->{type
} || $d->{type
} ne 'qemu';
2116 $res->{$vmid}->{exists} = 1;
2121 # test if VM uses local resources (to prevent migration)
2122 sub check_local_resources
{
2123 my ($conf, $noerr) = @_;
2127 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2128 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2130 foreach my $k (keys %$conf) {
2131 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2132 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2135 die "VM uses local resources\n" if $loc_res && !$noerr;
2140 # check if used storages are available on all nodes (use by migrate)
2141 sub check_storage_availability
{
2142 my ($storecfg, $conf, $node) = @_;
2144 foreach_drive
($conf, sub {
2145 my ($ds, $drive) = @_;
2147 my $volid = $drive->{file
};
2150 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2153 # check if storage is available on both nodes
2154 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2155 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2159 # list nodes where all VM images are available (used by has_feature API)
2161 my ($conf, $storecfg) = @_;
2163 my $nodelist = PVE
::Cluster
::get_nodelist
();
2164 my $nodehash = { map { $_ => 1 } @$nodelist };
2165 my $nodename = PVE
::INotify
::nodename
();
2167 foreach_drive
($conf, sub {
2168 my ($ds, $drive) = @_;
2170 my $volid = $drive->{file
};
2173 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2175 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2176 if ($scfg->{disable
}) {
2178 } elsif (my $avail = $scfg->{nodes
}) {
2179 foreach my $node (keys %$nodehash) {
2180 delete $nodehash->{$node} if !$avail->{$node};
2182 } elsif (!$scfg->{shared
}) {
2183 foreach my $node (keys %$nodehash) {
2184 delete $nodehash->{$node} if $node ne $nodename
2196 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2200 my ($pidfile, $pid) = @_;
2202 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2206 return undef if !$line;
2207 my @param = split(/\0/, $line);
2209 my $cmd = $param[0];
2210 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2212 for (my $i = 0; $i < scalar (@param); $i++) {
2215 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2216 my $p = $param[$i+1];
2217 return 1 if $p && ($p eq $pidfile);
2226 my ($vmid, $nocheck, $node) = @_;
2228 my $filename = config_file
($vmid, $node);
2230 die "unable to find configuration file for VM $vmid - no such machine\n"
2231 if !$nocheck && ! -f
$filename;
2233 my $pidfile = pidfile_name
($vmid);
2235 if (my $fd = IO
::File-
>new("<$pidfile")) {
2240 my $mtime = $st->mtime;
2241 if ($mtime > time()) {
2242 warn "file '$filename' modified in future\n";
2245 if ($line =~ m/^(\d+)$/) {
2247 if (check_cmdline
($pidfile, $pid)) {
2248 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2260 my $vzlist = config_list
();
2262 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2264 while (defined(my $de = $fd->read)) {
2265 next if $de !~ m/^(\d+)\.pid$/;
2267 next if !defined($vzlist->{$vmid});
2268 if (my $pid = check_running
($vmid)) {
2269 $vzlist->{$vmid}->{pid
} = $pid;
2277 my ($storecfg, $conf) = @_;
2279 my $bootdisk = $conf->{bootdisk
};
2280 return undef if !$bootdisk;
2281 return undef if !valid_drivename
($bootdisk);
2283 return undef if !$conf->{$bootdisk};
2285 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2286 return undef if !defined($drive);
2288 return undef if drive_is_cdrom
($drive);
2290 my $volid = $drive->{file
};
2291 return undef if !$volid;
2293 return $drive->{size
};
2296 my $last_proc_pid_stat;
2298 # get VM status information
2299 # This must be fast and should not block ($full == false)
2300 # We only query KVM using QMP if $full == true (this can be slow)
2302 my ($opt_vmid, $full) = @_;
2306 my $storecfg = PVE
::Storage
::config
();
2308 my $list = vzlist
();
2309 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2311 my $cpucount = $cpuinfo->{cpus
} || 1;
2313 foreach my $vmid (keys %$list) {
2314 next if $opt_vmid && ($vmid ne $opt_vmid);
2316 my $cfspath = cfs_config_path
($vmid);
2317 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2320 $d->{pid
} = $list->{$vmid}->{pid
};
2322 # fixme: better status?
2323 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2325 my $size = disksize
($storecfg, $conf);
2326 if (defined($size)) {
2327 $d->{disk
} = 0; # no info available
2328 $d->{maxdisk
} = $size;
2334 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2335 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2336 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2338 $d->{name
} = $conf->{name
} || "VM $vmid";
2339 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2341 if ($conf->{balloon
}) {
2342 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2343 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2354 $d->{diskwrite
} = 0;
2356 $d->{template
} = is_template
($conf);
2361 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2362 foreach my $dev (keys %$netdev) {
2363 next if $dev !~ m/^tap([1-9]\d*)i/;
2365 my $d = $res->{$vmid};
2368 $d->{netout
} += $netdev->{$dev}->{receive
};
2369 $d->{netin
} += $netdev->{$dev}->{transmit
};
2372 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2373 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2378 my $ctime = gettimeofday
;
2380 foreach my $vmid (keys %$list) {
2382 my $d = $res->{$vmid};
2383 my $pid = $d->{pid
};
2386 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2387 next if !$pstat; # not running
2389 my $used = $pstat->{utime} + $pstat->{stime
};
2391 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2393 if ($pstat->{vsize
}) {
2394 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2397 my $old = $last_proc_pid_stat->{$pid};
2399 $last_proc_pid_stat->{$pid} = {
2407 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2409 if ($dtime > 1000) {
2410 my $dutime = $used - $old->{used
};
2412 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2413 $last_proc_pid_stat->{$pid} = {
2419 $d->{cpu
} = $old->{cpu
};
2423 return $res if !$full;
2425 my $qmpclient = PVE
::QMPClient-
>new();
2427 my $ballooncb = sub {
2428 my ($vmid, $resp) = @_;
2430 my $info = $resp->{'return'};
2431 return if !$info->{max_mem
};
2433 my $d = $res->{$vmid};
2435 # use memory assigned to VM
2436 $d->{maxmem
} = $info->{max_mem
};
2437 $d->{balloon
} = $info->{actual
};
2439 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2440 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2441 $d->{freemem
} = $info->{free_mem
};
2444 $d->{ballooninfo
} = $info;
2447 my $blockstatscb = sub {
2448 my ($vmid, $resp) = @_;
2449 my $data = $resp->{'return'} || [];
2450 my $totalrdbytes = 0;
2451 my $totalwrbytes = 0;
2453 for my $blockstat (@$data) {
2454 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2455 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2457 $blockstat->{device
} =~ s/drive-//;
2458 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2460 $res->{$vmid}->{diskread
} = $totalrdbytes;
2461 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2464 my $statuscb = sub {
2465 my ($vmid, $resp) = @_;
2467 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2468 # this fails if ballon driver is not loaded, so this must be
2469 # the last commnand (following command are aborted if this fails).
2470 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2472 my $status = 'unknown';
2473 if (!defined($status = $resp->{'return'}->{status
})) {
2474 warn "unable to get VM status\n";
2478 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2481 foreach my $vmid (keys %$list) {
2482 next if $opt_vmid && ($vmid ne $opt_vmid);
2483 next if !$res->{$vmid}->{pid
}; # not running
2484 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2487 $qmpclient->queue_execute(undef, 1);
2489 foreach my $vmid (keys %$list) {
2490 next if $opt_vmid && ($vmid ne $opt_vmid);
2491 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2498 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2501 my $current_size = 1024;
2502 my $dimm_size = 512;
2503 return if $current_size == $memory;
2505 for (my $j = 0; $j < 8; $j++) {
2506 for (my $i = 0; $i < 32; $i++) {
2507 my $name = "dimm${dimm_id}";
2509 my $numanode = $i % $sockets;
2510 $current_size += $dimm_size;
2511 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2512 return $current_size if $current_size >= $memory;
2518 sub foreach_reverse_dimm
{
2519 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2522 my $current_size = 4177920;
2523 my $dimm_size = 65536;
2524 return if $current_size == $memory;
2526 for (my $j = 0; $j < 8; $j++) {
2527 for (my $i = 0; $i < 32; $i++) {
2528 my $name = "dimm${dimm_id}";
2530 my $numanode = $i % $sockets;
2531 $current_size -= $dimm_size;
2532 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2533 return $current_size if $current_size <= $memory;
2540 my ($conf, $func) = @_;
2542 foreach my $ds (keys %$conf) {
2543 next if !valid_drivename
($ds);
2545 my $drive = parse_drive
($ds, $conf->{$ds});
2548 &$func($ds, $drive);
2553 my ($conf, $func) = @_;
2557 my $test_volid = sub {
2558 my ($volid, $is_cdrom) = @_;
2562 $volhash->{$volid} = $is_cdrom || 0;
2565 foreach_drive
($conf, sub {
2566 my ($ds, $drive) = @_;
2567 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2570 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2571 my $snap = $conf->{snapshots
}->{$snapname};
2572 &$test_volid($snap->{vmstate
}, 0);
2573 foreach_drive
($snap, sub {
2574 my ($ds, $drive) = @_;
2575 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2579 foreach my $volid (keys %$volhash) {
2580 &$func($volid, $volhash->{$volid});
2584 sub vga_conf_has_spice
{
2587 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2592 sub config_to_command
{
2593 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2596 my $globalFlags = [];
2597 my $machineFlags = [];
2603 my $kvmver = kvm_user_version
();
2604 my $vernum = 0; # unknown
2605 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2606 $vernum = $1*1000000+$2*1000;
2607 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2608 $vernum = $1*1000000+$2*1000+$3;
2611 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2613 my $have_ovz = -f
'/proc/vz/vestat';
2615 my $q35 = machine_type_is_q35
($conf);
2616 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2617 my $machine_type = $forcemachine || $conf->{machine
};
2619 my $cpuunits = defined($conf->{cpuunits
}) ?
2620 $conf->{cpuunits
} : $defaults->{cpuunits
};
2622 push @$cmd, '/usr/bin/systemd-run';
2623 push @$cmd, '--scope';
2624 push @$cmd, '--slice', "qemu";
2625 push @$cmd, '--unit', $vmid;
2626 push @$cmd, '-p', "CPUShares=$cpuunits";
2627 if ($conf->{cpulimit
}) {
2628 my $cpulimit = int($conf->{cpulimit
} * 100);
2629 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2632 push @$cmd, '/usr/bin/kvm';
2634 push @$cmd, '-id', $vmid;
2638 my $qmpsocket = qmp_socket
($vmid);
2639 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2640 push @$cmd, '-mon', "chardev=qmp,mode=control";
2642 my $socket = vnc_socket
($vmid);
2643 push @$cmd, '-vnc', "unix:$socket,x509,password";
2645 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2647 push @$cmd, '-daemonize';
2649 if ($conf->{smbios1
}) {
2650 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2654 # the q35 chipset support native usb2, so we enable usb controller
2655 # by default for this machine type
2656 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2658 $pciaddr = print_pci_addr
("piix3", $bridges);
2659 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2662 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2663 next if !$conf->{"usb$i"};
2666 # include usb device config
2667 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2670 my $vga = $conf->{vga
};
2672 my $qxlnum = vga_conf_has_spice
($vga);
2673 $vga = 'qxl' if $qxlnum;
2676 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2677 $conf->{ostype
} eq 'win7' ||
2678 $conf->{ostype
} eq 'w2k8')) {
2685 # enable absolute mouse coordinates (needed by vnc)
2687 if (defined($conf->{tablet
})) {
2688 $tablet = $conf->{tablet
};
2690 $tablet = $defaults->{tablet
};
2691 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2692 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2695 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2698 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2699 my $d = parse_hostpci
($conf->{"hostpci$i"});
2702 my $pcie = $d->{pcie
};
2704 die "q35 machine model is not enabled" if !$q35;
2705 $pciaddr = print_pcie_addr
("hostpci$i");
2707 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2710 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2711 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2712 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2713 if ($xvga && $xvga ne '') {
2714 push @$cpuFlags, 'kvm=off';
2717 $driver = "vfio-pci" if $xvga ne '';
2718 my $pcidevices = $d->{pciid
};
2719 my $multifunction = 1 if @$pcidevices > 1;
2722 foreach my $pcidevice (@$pcidevices) {
2724 my $id = "hostpci$i";
2725 $id .= ".$j" if $multifunction;
2726 my $addr = $pciaddr;
2727 $addr .= ".$j" if $multifunction;
2728 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2731 $devicestr .= "$rombar$xvga";
2732 $devicestr .= ",multifunction=on" if $multifunction;
2735 push @$devices, '-device', $devicestr;
2741 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2742 my $d = parse_usb_device
($conf->{"usb$i"});
2744 if ($d->{vendorid
} && $d->{productid
}) {
2745 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2746 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2747 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2748 } elsif ($d->{spice
}) {
2749 # usb redir support for spice
2750 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2751 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2756 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2757 if (my $path = $conf->{"serial$i"}) {
2758 if ($path eq 'socket') {
2759 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2760 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2761 push @$devices, '-device', "isa-serial,chardev=serial$i";
2763 die "no such serial device\n" if ! -c
$path;
2764 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2765 push @$devices, '-device', "isa-serial,chardev=serial$i";
2771 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2772 if (my $path = $conf->{"parallel$i"}) {
2773 die "no such parallel device\n" if ! -c
$path;
2774 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2775 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2776 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2780 my $vmname = $conf->{name
} || "vm$vmid";
2782 push @$cmd, '-name', $vmname;
2785 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2786 $sockets = $conf->{sockets
} if $conf->{sockets
};
2788 my $cores = $conf->{cores
} || 1;
2790 my $maxcpus = $sockets * $cores;
2792 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2794 my $allowed_vcpus = $cpuinfo->{cpus
};
2796 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2797 if ($allowed_vcpus < $maxcpus);
2799 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2801 push @$cmd, '-nodefaults';
2803 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2805 my $bootindex_hash = {};
2807 foreach my $o (split(//, $bootorder)) {
2808 $bootindex_hash->{$o} = $i*100;
2812 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2814 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2816 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2818 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2821 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2823 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2824 my $useLocaltime = $conf->{localtime};
2826 if (my $ost = $conf->{ostype
}) {
2827 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2829 if ($ost =~ m/^w/) { # windows
2830 $useLocaltime = 1 if !defined($conf->{localtime});
2832 # use time drift fix when acpi is enabled
2833 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2834 $tdf = 1 if !defined($conf->{tdf
});
2838 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2840 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2841 push @$cmd, '-no-hpet';
2842 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2843 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2844 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2845 push @$cpuFlags , 'hv_time' if !$nokvm;
2848 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2852 if ($ost eq 'win7' || $ost eq 'win8') {
2853 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2857 push @$rtcFlags, 'driftfix=slew' if $tdf;
2860 push @$machineFlags, 'accel=tcg';
2862 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2865 if ($machine_type) {
2866 push @$machineFlags, "type=${machine_type}";
2869 if ($conf->{startdate
}) {
2870 push @$rtcFlags, "base=$conf->{startdate}";
2871 } elsif ($useLocaltime) {
2872 push @$rtcFlags, 'base=localtime';
2875 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2876 $cpu = $conf->{cpu
} if $conf->{cpu
};
2878 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2880 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2882 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2884 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2886 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2888 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2890 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2891 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2894 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2896 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2898 push @$cmd, '-cpu', $cpu;
2900 my $memory = $conf->{memory
} || $defaults->{memory
};
2901 my $static_memory = 0;
2902 my $dimm_memory = 0;
2904 if ($hotplug_features->{memory
}) {
2905 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2906 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2907 $static_memory = $STATICMEM;
2908 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2909 $dimm_memory = $memory - $static_memory;
2910 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2914 $static_memory = $memory;
2915 push @$cmd, '-m', $static_memory;
2918 if ($conf->{numa
}) {
2920 my $numa_totalmemory = undef;
2921 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2922 next if !$conf->{"numa$i"};
2923 my $numa = parse_numa
($conf->{"numa$i"});
2926 die "missing numa node$i memory value\n" if !$numa->{memory
};
2927 my $numa_memory = $numa->{memory
};
2928 $numa_totalmemory += $numa_memory;
2929 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2932 my $cpus_start = $numa->{cpus
}->{start
};
2933 die "missing numa node$i cpus\n" if !defined($cpus_start);
2934 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2935 my $cpus = $cpus_start;
2936 if (defined($cpus_end)) {
2937 $cpus .= "-$cpus_end";
2938 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2942 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2943 if (defined($hostnodes_start)) {
2944 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2945 my $hostnodes = $hostnodes_start;
2946 if (defined($hostnodes_end)) {
2947 $hostnodes .= "-$hostnodes_end";
2948 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2951 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2952 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2953 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2957 my $policy = $numa->{policy
};
2958 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2959 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2962 push @$cmd, '-object', $numa_object;
2963 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2966 die "total memory for NUMA nodes must be equal to vm static memory\n"
2967 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2969 #if no custom tology, we split memory and cores across numa nodes
2970 if(!$numa_totalmemory) {
2972 my $numa_memory = ($static_memory / $sockets) . "M";
2974 for (my $i = 0; $i < $sockets; $i++) {
2976 my $cpustart = ($cores * $i);
2977 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2978 my $cpus = $cpustart;
2979 $cpus .= "-$cpuend" if $cpuend;
2981 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2982 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2987 if ($hotplug_features->{memory
}) {
2988 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2989 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2990 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2991 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2993 #if dimm_memory is not aligned to dimm map
2994 if($current_size > $memory) {
2995 $conf->{memory
} = $current_size;
2996 update_config_nolock
($vmid, $conf, 1);
3001 push @$cmd, '-S' if $conf->{freeze
};
3003 # set keyboard layout
3004 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3005 push @$cmd, '-k', $kb if $kb;
3008 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3009 #push @$cmd, '-soundhw', 'es1370';
3010 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3012 if($conf->{agent
}) {
3013 my $qgasocket = qmp_socket
($vmid, 1);
3014 my $pciaddr = print_pci_addr
("qga0", $bridges);
3015 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3016 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3017 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3024 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3025 for(my $i = 1; $i < $qxlnum; $i++){
3026 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3027 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3030 # assume other OS works like Linux
3031 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3032 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3036 my $pciaddr = print_pci_addr
("spice", $bridges);
3038 my $nodename = PVE
::INotify
::nodename
();
3039 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3040 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3042 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3044 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3045 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3046 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3049 # enable balloon by default, unless explicitly disabled
3050 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3051 $pciaddr = print_pci_addr
("balloon0", $bridges);
3052 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3055 if ($conf->{watchdog
}) {
3056 my $wdopts = parse_watchdog
($conf->{watchdog
});
3057 $pciaddr = print_pci_addr
("watchdog", $bridges);
3058 my $watchdog = $wdopts->{model
} || 'i6300esb';
3059 push @$devices, '-device', "$watchdog$pciaddr";
3060 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3064 my $scsicontroller = {};
3065 my $ahcicontroller = {};
3066 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3068 # Add iscsi initiator name if available
3069 if (my $initiator = get_initiator_name
()) {
3070 push @$devices, '-iscsi', "initiator-name=$initiator";
3073 foreach_drive
($conf, sub {
3074 my ($ds, $drive) = @_;
3076 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3077 push @$vollist, $drive->{file
};
3080 $use_virtio = 1 if $ds =~ m/^virtio/;
3082 if (drive_is_cdrom
($drive)) {
3083 if ($bootindex_hash->{d
}) {
3084 $drive->{bootindex
} = $bootindex_hash->{d
};
3085 $bootindex_hash->{d
} += 1;
3088 if ($bootindex_hash->{c
}) {
3089 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3090 $bootindex_hash->{c
} += 1;
3094 if($drive->{interface
} eq 'virtio'){
3095 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3098 if ($drive->{interface
} eq 'scsi') {
3100 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3102 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3103 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3106 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3107 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3108 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3112 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3113 $queues = ",num_queues=$drive->{queues}";
3116 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3117 $scsicontroller->{$controller}=1;
3120 if ($drive->{interface
} eq 'sata') {
3121 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3122 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3123 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3124 $ahcicontroller->{$controller}=1;
3127 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3128 push @$devices, '-drive',$drive_cmd;
3129 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3132 for (my $i = 0; $i < $MAX_NETS; $i++) {
3133 next if !$conf->{"net$i"};
3134 my $d = parse_net
($conf->{"net$i"});
3137 $use_virtio = 1 if $d->{model
} eq 'virtio';
3139 if ($bootindex_hash->{n
}) {
3140 $d->{bootindex
} = $bootindex_hash->{n
};
3141 $bootindex_hash->{n
} += 1;
3144 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3145 push @$devices, '-netdev', $netdevfull;
3147 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3148 push @$devices, '-device', $netdevicefull;
3153 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3158 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3160 while (my ($k, $v) = each %$bridges) {
3161 $pciaddr = print_pci_addr
("pci.$k");
3162 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3167 if ($conf->{args
}) {
3168 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3172 push @$cmd, @$devices;
3173 push @$cmd, '-rtc', join(',', @$rtcFlags)
3174 if scalar(@$rtcFlags);
3175 push @$cmd, '-machine', join(',', @$machineFlags)
3176 if scalar(@$machineFlags);
3177 push @$cmd, '-global', join(',', @$globalFlags)
3178 if scalar(@$globalFlags);
3180 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3185 return "${var_run_tmpdir}/$vmid.vnc";
3191 my $res = vm_mon_cmd
($vmid, 'query-spice');
3193 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3197 my ($vmid, $qga) = @_;
3198 my $sockettype = $qga ?
'qga' : 'qmp';
3199 return "${var_run_tmpdir}/$vmid.$sockettype";
3204 return "${var_run_tmpdir}/$vmid.pid";
3207 sub vm_devices_list
{
3210 my $res = vm_mon_cmd
($vmid, 'query-pci');
3212 foreach my $pcibus (@$res) {
3213 foreach my $device (@{$pcibus->{devices
}}) {
3214 next if !$device->{'qdev_id'};
3215 if ($device->{'pci_bridge'}) {
3216 $devices->{$device->{'qdev_id'}} = 1;
3217 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3218 next if !$bridge_device->{'qdev_id'};
3219 $devices->{$bridge_device->{'qdev_id'}} = 1;
3220 $devices->{$device->{'qdev_id'}}++;
3223 $devices->{$device->{'qdev_id'}} = 1;
3228 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3229 foreach my $block (@$resblock) {
3230 if($block->{device
} =~ m/^drive-(\S+)/){
3235 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3236 foreach my $mice (@$resmice) {
3237 if ($mice->{name
} eq 'QEMU HID Tablet') {
3238 $devices->{tablet
} = 1;
3247 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3249 my $q35 = machine_type_is_q35
($conf);
3251 my $devices_list = vm_devices_list
($vmid);
3252 return 1 if defined($devices_list->{$deviceid});
3254 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3256 if ($deviceid eq 'tablet') {
3258 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3260 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3262 qemu_iothread_add
($vmid, $deviceid, $device);
3264 qemu_driveadd
($storecfg, $vmid, $device);
3265 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3267 qemu_deviceadd
($vmid, $devicefull);
3268 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3270 eval { qemu_drivedel
($vmid, $deviceid); };
3275 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3278 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3279 my $pciaddr = print_pci_addr
($deviceid);
3280 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3282 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3284 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3285 qemu_iothread_add
($vmid, $deviceid, $device);
3286 $devicefull .= ",iothread=iothread-$deviceid";
3289 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3290 $devicefull .= ",num_queues=$device->{queues}";
3293 qemu_deviceadd
($vmid, $devicefull);
3294 qemu_deviceaddverify
($vmid, $deviceid);
3296 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3298 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3299 qemu_driveadd
($storecfg, $vmid, $device);
3301 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3302 eval { qemu_deviceadd
($vmid, $devicefull); };
3304 eval { qemu_drivedel
($vmid, $deviceid); };
3309 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3311 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3312 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3313 qemu_deviceadd
($vmid, $netdevicefull);
3314 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3316 eval { qemu_netdevdel
($vmid, $deviceid); };
3321 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3324 my $pciaddr = print_pci_addr
($deviceid);
3325 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3327 qemu_deviceadd
($vmid, $devicefull);
3328 qemu_deviceaddverify
($vmid, $deviceid);
3331 die "can't hotplug device '$deviceid'\n";
3337 # fixme: this should raise exceptions on error!
3338 sub vm_deviceunplug
{
3339 my ($vmid, $conf, $deviceid) = @_;
3341 my $devices_list = vm_devices_list
($vmid);
3342 return 1 if !defined($devices_list->{$deviceid});
3344 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3346 if ($deviceid eq 'tablet') {
3348 qemu_devicedel
($vmid, $deviceid);
3350 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3352 qemu_devicedel
($vmid, $deviceid);
3353 qemu_devicedelverify
($vmid, $deviceid);
3354 qemu_drivedel
($vmid, $deviceid);
3355 qemu_iothread_del
($conf, $vmid, $deviceid);
3357 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3359 qemu_devicedel
($vmid, $deviceid);
3360 qemu_devicedelverify
($vmid, $deviceid);
3361 qemu_iothread_del
($conf, $vmid, $deviceid);
3363 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3365 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3366 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3367 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3369 qemu_devicedel
($vmid, $deviceid);
3370 qemu_drivedel
($vmid, $deviceid);
3371 qemu_deletescsihw
($conf, $vmid, $deviceid);
3373 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3375 qemu_devicedel
($vmid, $deviceid);
3376 qemu_devicedelverify
($vmid, $deviceid);
3377 qemu_netdevdel
($vmid, $deviceid);
3380 die "can't unplug device '$deviceid'\n";
3386 sub qemu_deviceadd
{
3387 my ($vmid, $devicefull) = @_;
3389 $devicefull = "driver=".$devicefull;
3390 my %options = split(/[=,]/, $devicefull);
3392 vm_mon_cmd
($vmid, "device_add" , %options);
3395 sub qemu_devicedel
{
3396 my ($vmid, $deviceid) = @_;
3398 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3401 sub qemu_iothread_add
{
3402 my($vmid, $deviceid, $device) = @_;
3404 if ($device->{iothread
}) {
3405 my $iothreads = vm_iothreads_list
($vmid);
3406 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3410 sub qemu_iothread_del
{
3411 my($conf, $vmid, $deviceid) = @_;
3413 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3414 if ($device->{iothread
}) {
3415 my $iothreads = vm_iothreads_list
($vmid);
3416 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3420 sub qemu_objectadd
{
3421 my($vmid, $objectid, $qomtype) = @_;
3423 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3428 sub qemu_objectdel
{
3429 my($vmid, $objectid) = @_;
3431 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3437 my ($storecfg, $vmid, $device) = @_;
3439 my $drive = print_drive_full
($storecfg, $vmid, $device);
3440 $drive =~ s/\\/\\\\/g;
3441 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3443 # If the command succeeds qemu prints: "OK
"
3444 return 1 if $ret =~ m/OK/s;
3446 die "adding drive failed
: $ret\n";
3450 my($vmid, $deviceid) = @_;
3452 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3455 return 1 if $ret eq "";
3457 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3458 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3460 die "deleting drive
$deviceid failed
: $ret\n";
3463 sub qemu_deviceaddverify {
3464 my ($vmid, $deviceid) = @_;
3466 for (my $i = 0; $i <= 5; $i++) {
3467 my $devices_list = vm_devices_list($vmid);
3468 return 1 if defined($devices_list->{$deviceid});
3472 die "error on hotplug device
'$deviceid'\n";
3476 sub qemu_devicedelverify {
3477 my ($vmid, $deviceid) = @_;
3479 # need to verify that the device is correctly removed as device_del
3480 # is async and empty return is not reliable
3482 for (my $i = 0; $i <= 5; $i++) {
3483 my $devices_list = vm_devices_list($vmid);
3484 return 1 if !defined($devices_list->{$deviceid});
3488 die "error on hot-unplugging device
'$deviceid'\n";
3491 sub qemu_findorcreatescsihw {
3492 my ($storecfg, $conf, $vmid, $device) = @_;
3494 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3496 my $scsihwid="$controller_prefix$controller";
3497 my $devices_list = vm_devices_list($vmid);
3499 if(!defined($devices_list->{$scsihwid})) {
3500 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3506 sub qemu_deletescsihw {
3507 my ($conf, $vmid, $opt) = @_;
3509 my $device = parse_drive($opt, $conf->{$opt});
3511 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3512 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3516 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3518 my $devices_list = vm_devices_list($vmid);
3519 foreach my $opt (keys %{$devices_list}) {
3520 if (PVE::QemuServer::valid_drivename($opt)) {
3521 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3522 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3528 my $scsihwid="scsihw
$controller";
3530 vm_deviceunplug($vmid, $conf, $scsihwid);
3535 sub qemu_add_pci_bridge {
3536 my ($storecfg, $conf, $vmid, $device) = @_;
3542 print_pci_addr($device, $bridges);
3544 while (my ($k, $v) = each %$bridges) {
3547 return 1 if !defined($bridgeid) || $bridgeid < 1;
3549 my $bridge = "pci
.$bridgeid";
3550 my $devices_list = vm_devices_list($vmid);
3552 if (!defined($devices_list->{$bridge})) {
3553 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3559 sub qemu_set_link_status {
3560 my ($vmid, $device, $up) = @_;
3562 vm_mon_cmd($vmid, "set_link
", name => $device,
3563 up => $up ? JSON::true : JSON::false);
3566 sub qemu_netdevadd {
3567 my ($vmid, $conf, $device, $deviceid) = @_;
3569 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3570 my %options = split(/[=,]/, $netdev);
3572 vm_mon_cmd($vmid, "netdev_add
", %options);
3576 sub qemu_netdevdel {
3577 my ($vmid, $deviceid) = @_;
3579 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3582 sub qemu_cpu_hotplug {
3583 my ($vmid, $conf, $vcpus) = @_;
3586 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3587 $sockets = $conf->{sockets} if $conf->{sockets};
3588 my $cores = $conf->{cores} || 1;
3589 my $maxcpus = $sockets * $cores;
3591 $vcpus = $maxcpus if !$vcpus;
3593 die "you can
't add more vcpus than maxcpus\n"
3594 if $vcpus > $maxcpus;
3596 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3597 die "online cpu unplug is not yet possible\n"
3598 if $vcpus < $currentvcpus;
3600 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3601 die "vcpus in running vm is different than configuration\n"
3602 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3604 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3605 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3609 sub qemu_memory_hotplug {
3610 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3612 return $value if !check_running($vmid);
3614 my $memory = $conf->{memory} || $defaults->{memory};
3615 $value = $defaults->{memory} if !$value;
3616 return $value if $value == $memory;
3618 my $static_memory = $STATICMEM;
3619 my $dimm_memory = $memory - $static_memory;
3621 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3622 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3626 $sockets = $conf->{sockets} if $conf->{sockets};
3628 if($value > $memory) {
3630 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3631 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3633 return if $current_size <= $conf->{memory};
3635 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3637 eval { qemu_objectdel($vmid, "mem-
$name"); };
3641 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3643 eval { qemu_objectdel($vmid, "mem-
$name"); };
3646 #update conf after each succesful module hotplug
3647 $conf->{memory} = $current_size;
3648 update_config_nolock($vmid, $conf, 1);
3653 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3654 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3656 return if $current_size >= $conf->{memory};
3657 print "try to unplug memory dimm
$name\n";
3661 eval { qemu_devicedel($vmid, $name) };
3663 my $dimm_list = qemu_dimm_list($vmid);
3664 last if !$dimm_list->{$name};
3665 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3669 #update conf after each succesful module unplug
3670 $conf->{memory} = $current_size;
3672 eval { qemu_objectdel($vmid, "mem-
$name"); };
3673 update_config_nolock($vmid, $conf, 1);
3678 sub qemu_dimm_list {
3681 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3684 foreach my $dimm (@$dimmarray) {
3686 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3687 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3688 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3689 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3690 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3695 sub qemu_block_set_io_throttle {
3696 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3698 return if !check_running($vmid) ;
3700 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));
3704 # old code, only used to shutdown old VM after update
3706 my ($fh, $timeout) = @_;
3708 my $sel = new IO::Select;
3715 while (scalar (@ready = $sel->can_read($timeout))) {
3717 if ($count = $fh->sysread($buf, 8192)) {
3718 if ($buf =~ /^(.*)\(qemu\) $/s) {
3725 if (!defined($count)) {
3732 die "monitor
read timeout
\n" if !scalar(@ready);
3737 # old code, only used to shutdown old VM after update
3738 sub vm_monitor_command {
3739 my ($vmid, $cmdstr, $nocheck) = @_;
3744 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3746 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3748 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3749 die "unable to
connect to VM
$vmid socket - $!\n";
3753 # hack: migrate sometime blocks the monitor (when migrate_downtime
3755 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3756 $timeout = 60*60; # 1 hour
3760 my $data = __read_avail($sock, $timeout);
3762 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3763 die "got unexpected qemu monitor banner
\n";
3766 my $sel = new IO::Select;
3769 if (!scalar(my @ready = $sel->can_write($timeout))) {
3770 die "monitor
write error
- timeout
";
3773 my $fullcmd = "$cmdstr\r";
3775 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3778 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3779 die "monitor
write error
- $!";
3782 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3786 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3787 $timeout = 60*60; # 1 hour
3788 } elsif ($cmdstr =~ m/^(eject|change)/) {
3789 $timeout = 60; # note: cdrom mount command is slow
3791 if ($res = __read_avail($sock, $timeout)) {
3793 my @lines = split("\r?
\n", $res);
3795 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3797 $res = join("\n", @lines);
3805 syslog("err
", "VM
$vmid monitor command failed
- $err");
3812 sub qemu_block_resize {
3813 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3815 my $running = check_running($vmid);
3817 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3819 return if !$running;
3821 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3825 sub qemu_volume_snapshot {
3826 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3828 my $running = check_running($vmid);
3830 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3831 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3833 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3837 sub qemu_volume_snapshot_delete {
3838 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3840 my $running = check_running($vmid);
3842 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3844 return if !$running;
3846 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3849 sub set_migration_caps {
3855 "auto-converge
" => 1,
3857 "x-rdma-pin-all
" => 0,
3861 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3863 for my $supported_capability (@$supported_capabilities) {
3865 capability => $supported_capability->{capability},
3866 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3870 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3873 my $fast_plug_option = {
3882 # hotplug changes in [PENDING]
3883 # $selection hash can be used to only apply specified options, for
3884 # example: { cores => 1 } (only apply changed 'cores')
3885 # $errors ref is used to return error messages
3886 sub vmconfig_hotplug_pending {
3887 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3889 my $defaults = load_defaults();
3891 # commit values which do not have any impact on running VM first
3892 # Note: those option cannot raise errors, we we do not care about
3893 # $selection and always apply them.
3895 my $add_error = sub {
3896 my ($opt, $msg) = @_;
3897 $errors->{$opt} = "hotplug problem
- $msg";
3901 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3902 if ($fast_plug_option->{$opt}) {
3903 $conf->{$opt} = $conf->{pending}->{$opt};
3904 delete $conf->{pending}->{$opt};
3910 update_config_nolock($vmid, $conf, 1);
3911 $conf = load_config($vmid); # update/reload
3914 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3916 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3917 while (my ($opt, $force) = each %$pending_delete_hash) {
3918 next if $selection && !$selection->{$opt};
3920 if ($opt eq 'hotplug') {
3921 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3922 } elsif ($opt eq 'tablet') {
3923 die "skip
\n" if !$hotplug_features->{usb};
3924 if ($defaults->{tablet}) {
3925 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3927 vm_deviceunplug($vmid, $conf, $opt);
3929 } elsif ($opt eq 'vcpus') {
3930 die "skip
\n" if !$hotplug_features->{cpu};
3931 qemu_cpu_hotplug($vmid, $conf, undef);
3932 } elsif ($opt eq 'balloon') {
3933 # enable balloon device is not hotpluggable
3934 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3935 } elsif ($fast_plug_option->{$opt}) {
3937 } elsif ($opt =~ m/^net(\d+)$/) {
3938 die "skip
\n" if !$hotplug_features->{network};
3939 vm_deviceunplug($vmid, $conf, $opt);
3940 } elsif (valid_drivename($opt)) {
3941 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3942 vm_deviceunplug($vmid, $conf, $opt);
3943 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3944 } elsif ($opt =~ m/^memory$/) {
3945 die "skip
\n" if !$hotplug_features->{memory};
3946 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3947 } elsif ($opt eq 'cpuunits') {
3948 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3949 } elsif ($opt eq 'cpulimit') {
3950 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3956 &$add_error($opt, $err) if $err ne "skip
\n";
3958 # save new config if hotplug was successful
3959 delete $conf->{$opt};
3960 vmconfig_undelete_pending_option($conf, $opt);
3961 update_config_nolock($vmid, $conf, 1);
3962 $conf = load_config($vmid); # update/reload
3966 foreach my $opt (keys %{$conf->{pending}}) {
3967 next if $selection && !$selection->{$opt};
3968 my $value = $conf->{pending}->{$opt};
3970 if ($opt eq 'hotplug') {
3971 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3972 } elsif ($opt eq 'tablet') {
3973 die "skip
\n" if !$hotplug_features->{usb};
3975 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3976 } elsif ($value == 0) {
3977 vm_deviceunplug($vmid, $conf, $opt);
3979 } elsif ($opt eq 'vcpus') {
3980 die "skip
\n" if !$hotplug_features->{cpu};
3981 qemu_cpu_hotplug($vmid, $conf, $value);
3982 } elsif ($opt eq 'balloon') {
3983 # enable/disable balloning device is not hotpluggable
3984 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3985 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3986 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3988 # allow manual ballooning if shares is set to zero
3989 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3990 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3991 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3993 } elsif ($opt =~ m/^net(\d+)$/) {
3994 # some changes can be done without hotplug
3995 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3996 $vmid, $opt, $value);
3997 } elsif (valid_drivename($opt)) {
3998 # some changes can be done without hotplug
3999 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4000 $vmid, $opt, $value, 1);
4001 } elsif ($opt =~ m/^memory$/) { #dimms
4002 die "skip
\n" if !$hotplug_features->{memory};
4003 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4004 } elsif ($opt eq 'cpuunits') {
4005 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4006 } elsif ($opt eq 'cpulimit') {
4007 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4008 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4010 die "skip
\n"; # skip non-hot-pluggable options
4014 &$add_error($opt, $err) if $err ne "skip
\n";
4016 # save new config if hotplug was successful
4017 $conf->{$opt} = $value;
4018 delete $conf->{pending}->{$opt};
4019 update_config_nolock($vmid, $conf, 1);
4020 $conf = load_config($vmid); # update/reload
4026 my ($vmid, $storecfg, $conf, $key, $volid) = @_;
4028 # check if the disk is really unused
4029 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4030 my $path = PVE::Storage::path($storecfg, $volid);
4032 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4033 if $used_paths->{$path};
4034 PVE::Storage::vdisk_free($storecfg, $volid);
4037 sub try_deallocate_drive {
4038 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4040 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4041 my $volid = $drive->{file};
4042 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4043 my $sid = PVE::Storage::parse_volume_id($volid);
4044 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4045 delete_drive($vmid, $storecfg, $conf, $key, $drive->{file});
4053 sub vmconfig_delete_or_detach_drive {
4054 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4056 my $drive = parse_drive($opt, $conf->{$opt});
4058 my $rpcenv = PVE::RPCEnvironment::get();
4059 my $authuser = $rpcenv->get_user();
4062 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4063 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4065 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4069 sub vmconfig_apply_pending {
4070 my ($vmid, $conf, $storecfg) = @_;
4074 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4075 while (my ($opt, $force) = each %$pending_delete_hash) {
4076 die "internal error
" if $opt =~ m/^unused/;
4077 $conf = load_config($vmid); # update/reload
4078 if (!defined($conf->{$opt})) {
4079 vmconfig_undelete_pending_option($conf, $opt);
4080 update_config_nolock($vmid, $conf, 1);
4081 } elsif (valid_drivename($opt)) {
4082 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4083 vmconfig_undelete_pending_option($conf, $opt);
4084 delete $conf->{$opt};
4085 update_config_nolock($vmid, $conf, 1);
4087 vmconfig_undelete_pending_option($conf, $opt);
4088 delete $conf->{$opt};
4089 update_config_nolock($vmid, $conf, 1);
4093 $conf = load_config($vmid); # update/reload
4095 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4096 $conf = load_config($vmid); # update/reload
4098 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4099 # skip if nothing changed
4100 } elsif (valid_drivename($opt)) {
4101 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4102 if defined($conf->{$opt});
4103 $conf->{$opt} = $conf->{pending}->{$opt};
4105 $conf->{$opt} = $conf->{pending}->{$opt};
4108 delete $conf->{pending}->{$opt};
4109 update_config_nolock($vmid, $conf, 1);
4113 my $safe_num_ne = sub {
4116 return 0 if !defined($a) && !defined($b);
4117 return 1 if !defined($a);
4118 return 1 if !defined($b);
4123 my $safe_string_ne = sub {
4126 return 0 if !defined($a) && !defined($b);
4127 return 1 if !defined($a);
4128 return 1 if !defined($b);
4133 sub vmconfig_update_net {
4134 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4136 my $newnet = parse_net($value);
4138 if ($conf->{$opt}) {
4139 my $oldnet = parse_net($conf->{$opt});
4141 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4142 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4143 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4144 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4146 # for non online change, we try to hot-unplug
4147 die "skip
\n" if !$hotplug;
4148 vm_deviceunplug($vmid, $conf, $opt);
4151 die "internal error
" if $opt !~ m/net(\d+)/;
4152 my $iface = "tap
${vmid
}i
$1";
4154 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4155 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4158 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4159 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4160 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4161 PVE::Network::tap_unplug($iface);
4162 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4165 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4166 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4174 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4180 sub vmconfig_update_disk {
4181 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4183 # fixme: do we need force?
4185 my $drive = parse_drive($opt, $value);
4187 if ($conf->{$opt}) {
4189 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4191 my $media = $drive->{media} || 'disk';
4192 my $oldmedia = $old_drive->{media} || 'disk';
4193 die "unable to change media type
\n" if $media ne $oldmedia;
4195 if (!drive_is_cdrom($old_drive)) {
4197 if ($drive->{file} ne $old_drive->{file}) {
4199 die "skip
\n" if !$hotplug;
4201 # unplug and register as unused
4202 vm_deviceunplug($vmid, $conf, $opt);
4203 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4206 # update existing disk
4208 # skip non hotpluggable value
4209 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4210 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4211 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4212 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4217 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4218 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4219 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4220 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4221 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4222 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4223 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4224 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4225 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4226 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4227 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4228 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4230 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4231 ($drive->{mbps} || 0)*1024*1024,
4232 ($drive->{mbps_rd} || 0)*1024*1024,
4233 ($drive->{mbps_wr} || 0)*1024*1024,
4234 $drive->{iops} || 0,
4235 $drive->{iops_rd} || 0,
4236 $drive->{iops_wr} || 0,
4237 ($drive->{mbps_max} || 0)*1024*1024,
4238 ($drive->{mbps_rd_max} || 0)*1024*1024,
4239 ($drive->{mbps_wr_max} || 0)*1024*1024,
4240 $drive->{iops_max} || 0,
4241 $drive->{iops_rd_max} || 0,
4242 $drive->{iops_wr_max} || 0);
4251 if ($drive->{file} eq 'none') {
4252 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4254 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4255 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4256 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4264 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4266 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4270 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4272 lock_config($vmid, sub {
4273 my $conf = load_config($vmid, $migratedfrom);
4275 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4277 check_lock($conf) if !$skiplock;
4279 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4281 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4282 vmconfig_apply_pending($vmid, $conf, $storecfg);
4283 $conf = load_config($vmid); # update/reload
4286 my $defaults = load_defaults();
4288 # set environment variable useful inside network script
4289 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4291 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4293 my $migrate_port = 0;
4296 if ($statefile eq 'tcp') {
4297 my $localip = "localhost
";
4298 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4299 my $nodename = PVE::INotify::nodename();
4300 if ($datacenterconf->{migration_unsecure}) {
4301 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4303 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4304 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4305 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4306 push @$cmd, '-incoming', $migrate_uri;
4309 push @$cmd, '-loadstate', $statefile;
4316 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4317 my $d = parse_hostpci($conf->{"hostpci
$i"});
4319 my $pcidevices = $d->{pciid};
4320 foreach my $pcidevice (@$pcidevices) {
4321 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4323 my $info = pci_device_info("0000:$pciid");
4324 die "IOMMU
not present
\n" if !check_iommu_support();
4325 die "no pci device info
for device
'$pciid'\n" if !$info;
4327 if ($d->{driver} && $d->{driver} eq "vfio
") {
4328 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4330 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4333 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4337 PVE::Storage::activate_volumes($storecfg, $vollist);
4339 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4342 die "start failed: $err" if $err;
4344 print "migration listens on $migrate_uri\n" if $migrate_uri;
4346 if ($statefile && $statefile ne 'tcp
') {
4347 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4351 if ($migratedfrom) {
4354 set_migration_caps($vmid);
4359 print "spice listens on port $spice_port\n";
4360 if ($spice_ticket) {
4361 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4362 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4368 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4369 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4370 if $conf->{balloon};
4373 foreach my $opt (keys %$conf) {
4374 next if $opt !~ m/^net\d+$/;
4375 my $nicconf = parse_net($conf->{$opt});
4376 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4380 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4381 path => "machine/peripheral/balloon0",
4382 property => "guest-stats-polling-interval",
4383 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4389 my ($vmid, $execute, %params) = @_;
4391 my $cmd = { execute => $execute, arguments => \%params };
4392 vm_qmp_command($vmid, $cmd);
4395 sub vm_mon_cmd_nocheck {
4396 my ($vmid, $execute, %params) = @_;
4398 my $cmd = { execute => $execute, arguments => \%params };
4399 vm_qmp_command($vmid, $cmd, 1);
4402 sub vm_qmp_command {
4403 my ($vmid, $cmd, $nocheck) = @_;
4408 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4409 $timeout = $cmd->{arguments}->{timeout};
4410 delete $cmd->{arguments}->{timeout};
4414 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4415 my $sname = qmp_socket($vmid);
4416 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4417 my $qmpclient = PVE::QMPClient->new();
4419 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4420 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4421 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4422 if scalar(%{$cmd->{arguments}});
4423 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4425 die "unable to
open monitor
socket\n";
4429 syslog("err
", "VM
$vmid qmp command failed
- $err");
4436 sub vm_human_monitor_command {
4437 my ($vmid, $cmdline) = @_;
4442 execute => 'human-monitor-command',
4443 arguments => { 'command-line' => $cmdline},
4446 return vm_qmp_command($vmid, $cmd);
4449 sub vm_commandline {
4450 my ($storecfg, $vmid) = @_;
4452 my $conf = load_config($vmid);
4454 my $defaults = load_defaults();
4456 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4458 return join(' ', @$cmd);
4462 my ($vmid, $skiplock) = @_;
4464 lock_config($vmid, sub {
4466 my $conf = load_config($vmid);
4468 check_lock($conf) if !$skiplock;
4470 vm_mon_cmd($vmid, "system_reset
");
4474 sub get_vm_volumes {
4478 foreach_volid($conf, sub {
4479 my ($volid, $is_cdrom) = @_;
4481 return if $volid =~ m|^/|;
4483 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4486 push @$vollist, $volid;
4492 sub vm_stop_cleanup {
4493 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4498 my $vollist = get_vm_volumes($conf);
4499 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4502 foreach my $ext (qw(mon qmp pid vnc qga)) {
4503 unlink "/var/run/qemu-server/${vmid}.$ext";
4506 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4508 warn $@ if $@; # avoid errors - just warn
4511 # Note: use $nockeck to skip tests if VM configuration file exists.
4512 # We need that when migration VMs to other nodes (files already moved)
4513 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4515 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4517 $force = 1 if !defined($force) && !$shutdown;
4520 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4521 kill 15, $pid if $pid;
4522 my $conf = load_config
($vmid, $migratedfrom);
4523 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4527 lock_config
($vmid, sub {
4529 my $pid = check_running
($vmid, $nocheck);
4534 $conf = load_config
($vmid);
4535 check_lock
($conf) if !$skiplock;
4536 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4537 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4538 $timeout = $opts->{down
} if $opts->{down
};
4542 $timeout = 60 if !defined($timeout);
4546 if (defined($conf) && $conf->{agent
}) {
4547 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4549 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4552 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4559 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4564 if ($count >= $timeout) {
4566 warn "VM still running - terminating now with SIGTERM\n";
4569 die "VM quit/powerdown failed - got timeout\n";
4572 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4577 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4580 die "VM quit/powerdown failed\n";
4588 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4593 if ($count >= $timeout) {
4594 warn "VM still running - terminating now with SIGKILL\n";
4599 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4604 my ($vmid, $skiplock) = @_;
4606 lock_config
($vmid, sub {
4608 my $conf = load_config
($vmid);
4610 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4612 vm_mon_cmd
($vmid, "stop");
4617 my ($vmid, $skiplock) = @_;
4619 lock_config
($vmid, sub {
4621 my $conf = load_config
($vmid);
4623 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4625 vm_mon_cmd
($vmid, "cont");
4630 my ($vmid, $skiplock, $key) = @_;
4632 lock_config
($vmid, sub {
4634 my $conf = load_config
($vmid);
4636 # there is no qmp command, so we use the human monitor command
4637 vm_human_monitor_command
($vmid, "sendkey $key");
4642 my ($storecfg, $vmid, $skiplock) = @_;
4644 lock_config
($vmid, sub {
4646 my $conf = load_config
($vmid);
4648 check_lock
($conf) if !$skiplock;
4650 if (!check_running
($vmid)) {
4651 destroy_vm
($storecfg, $vmid);
4653 die "VM $vmid is running - destroy failed\n";
4661 my ($filename, $buf) = @_;
4663 my $fh = IO
::File-
>new($filename, "w");
4664 return undef if !$fh;
4666 my $res = print $fh $buf;
4673 sub pci_device_info
{
4678 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4679 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4681 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4682 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4684 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4685 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4687 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4688 return undef if !defined($product) || $product !~ s/^0x//;
4693 product
=> $product,
4699 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4708 my $name = $dev->{name
};
4710 my $fn = "$pcisysfs/devices/$name/reset";
4712 return file_write
($fn, "1");
4715 sub pci_dev_bind_to_stub
{
4718 my $name = $dev->{name
};
4720 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4721 return 1 if -d
$testdir;
4723 my $data = "$dev->{vendor} $dev->{product}";
4724 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4726 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4727 if (!file_write
($fn, $name)) {
4728 return undef if -f
$fn;
4731 $fn = "$pcisysfs/drivers/pci-stub/bind";
4732 if (! -d
$testdir) {
4733 return undef if !file_write
($fn, $name);
4739 sub pci_dev_bind_to_vfio
{
4742 my $name = $dev->{name
};
4744 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4746 if (!-d
$vfio_basedir) {
4747 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4749 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4751 my $testdir = "$vfio_basedir/$name";
4752 return 1 if -d
$testdir;
4754 my $data = "$dev->{vendor} $dev->{product}";
4755 return undef if !file_write
("$vfio_basedir/new_id", $data);
4757 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4758 if (!file_write
($fn, $name)) {
4759 return undef if -f
$fn;
4762 $fn = "$vfio_basedir/bind";
4763 if (! -d
$testdir) {
4764 return undef if !file_write
($fn, $name);
4770 sub pci_dev_group_bind_to_vfio
{
4773 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4775 if (!-d
$vfio_basedir) {
4776 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4778 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4780 # get IOMMU group devices
4781 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4782 my @devs = grep /^0000:/, readdir($D);
4785 foreach my $pciid (@devs) {
4786 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4788 # pci bridges, switches or root ports are not supported
4789 # they have a pci_bus subdirectory so skip them
4790 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4792 my $info = pci_device_info
($1);
4793 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4799 sub print_pci_addr
{
4800 my ($id, $bridges) = @_;
4804 piix3
=> { bus
=> 0, addr
=> 1 },
4805 #addr2 : first videocard
4806 balloon0
=> { bus
=> 0, addr
=> 3 },
4807 watchdog
=> { bus
=> 0, addr
=> 4 },
4808 scsihw0
=> { bus
=> 0, addr
=> 5 },
4809 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4810 scsihw1
=> { bus
=> 0, addr
=> 6 },
4811 ahci0
=> { bus
=> 0, addr
=> 7 },
4812 qga0
=> { bus
=> 0, addr
=> 8 },
4813 spice
=> { bus
=> 0, addr
=> 9 },
4814 virtio0
=> { bus
=> 0, addr
=> 10 },
4815 virtio1
=> { bus
=> 0, addr
=> 11 },
4816 virtio2
=> { bus
=> 0, addr
=> 12 },
4817 virtio3
=> { bus
=> 0, addr
=> 13 },
4818 virtio4
=> { bus
=> 0, addr
=> 14 },
4819 virtio5
=> { bus
=> 0, addr
=> 15 },
4820 hostpci0
=> { bus
=> 0, addr
=> 16 },
4821 hostpci1
=> { bus
=> 0, addr
=> 17 },
4822 net0
=> { bus
=> 0, addr
=> 18 },
4823 net1
=> { bus
=> 0, addr
=> 19 },
4824 net2
=> { bus
=> 0, addr
=> 20 },
4825 net3
=> { bus
=> 0, addr
=> 21 },
4826 net4
=> { bus
=> 0, addr
=> 22 },
4827 net5
=> { bus
=> 0, addr
=> 23 },
4828 vga1
=> { bus
=> 0, addr
=> 24 },
4829 vga2
=> { bus
=> 0, addr
=> 25 },
4830 vga3
=> { bus
=> 0, addr
=> 26 },
4831 hostpci2
=> { bus
=> 0, addr
=> 27 },
4832 hostpci3
=> { bus
=> 0, addr
=> 28 },
4833 #addr29 : usb-host (pve-usb.cfg)
4834 'pci.1' => { bus
=> 0, addr
=> 30 },
4835 'pci.2' => { bus
=> 0, addr
=> 31 },
4836 'net6' => { bus
=> 1, addr
=> 1 },
4837 'net7' => { bus
=> 1, addr
=> 2 },
4838 'net8' => { bus
=> 1, addr
=> 3 },
4839 'net9' => { bus
=> 1, addr
=> 4 },
4840 'net10' => { bus
=> 1, addr
=> 5 },
4841 'net11' => { bus
=> 1, addr
=> 6 },
4842 'net12' => { bus
=> 1, addr
=> 7 },
4843 'net13' => { bus
=> 1, addr
=> 8 },
4844 'net14' => { bus
=> 1, addr
=> 9 },
4845 'net15' => { bus
=> 1, addr
=> 10 },
4846 'net16' => { bus
=> 1, addr
=> 11 },
4847 'net17' => { bus
=> 1, addr
=> 12 },
4848 'net18' => { bus
=> 1, addr
=> 13 },
4849 'net19' => { bus
=> 1, addr
=> 14 },
4850 'net20' => { bus
=> 1, addr
=> 15 },
4851 'net21' => { bus
=> 1, addr
=> 16 },
4852 'net22' => { bus
=> 1, addr
=> 17 },
4853 'net23' => { bus
=> 1, addr
=> 18 },
4854 'net24' => { bus
=> 1, addr
=> 19 },
4855 'net25' => { bus
=> 1, addr
=> 20 },
4856 'net26' => { bus
=> 1, addr
=> 21 },
4857 'net27' => { bus
=> 1, addr
=> 22 },
4858 'net28' => { bus
=> 1, addr
=> 23 },
4859 'net29' => { bus
=> 1, addr
=> 24 },
4860 'net30' => { bus
=> 1, addr
=> 25 },
4861 'net31' => { bus
=> 1, addr
=> 26 },
4862 'virtio6' => { bus
=> 2, addr
=> 1 },
4863 'virtio7' => { bus
=> 2, addr
=> 2 },
4864 'virtio8' => { bus
=> 2, addr
=> 3 },
4865 'virtio9' => { bus
=> 2, addr
=> 4 },
4866 'virtio10' => { bus
=> 2, addr
=> 5 },
4867 'virtio11' => { bus
=> 2, addr
=> 6 },
4868 'virtio12' => { bus
=> 2, addr
=> 7 },
4869 'virtio13' => { bus
=> 2, addr
=> 8 },
4870 'virtio14' => { bus
=> 2, addr
=> 9 },
4871 'virtio15' => { bus
=> 2, addr
=> 10 },
4872 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4873 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4874 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4875 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4876 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4877 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4878 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4879 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4880 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4881 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4882 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4883 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4884 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4885 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4886 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4887 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4888 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4889 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4890 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4891 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4892 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4893 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4894 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4895 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4896 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4897 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4898 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4899 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4900 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4901 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4902 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4906 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4907 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4908 my $bus = $devices->{$id}->{bus
};
4909 $res = ",bus=pci.$bus,addr=$addr";
4910 $bridges->{$bus} = 1 if $bridges;
4916 sub print_pcie_addr
{
4921 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4922 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4923 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4924 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4927 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4928 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4929 my $bus = $devices->{$id}->{bus
};
4930 $res = ",bus=$bus,addr=$addr";
4936 # vzdump restore implementaion
4938 sub tar_archive_read_firstfile
{
4939 my $archive = shift;
4941 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4943 # try to detect archive type first
4944 my $pid = open (TMP
, "tar tf '$archive'|") ||
4945 die "unable to open file '$archive'\n";
4946 my $firstfile = <TMP
>;
4950 die "ERROR: archive contaions no data\n" if !$firstfile;
4956 sub tar_restore_cleanup
{
4957 my ($storecfg, $statfile) = @_;
4959 print STDERR
"starting cleanup\n";
4961 if (my $fd = IO
::File-
>new($statfile, "r")) {
4962 while (defined(my $line = <$fd>)) {
4963 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4966 if ($volid =~ m
|^/|) {
4967 unlink $volid || die 'unlink failed\n';
4969 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4971 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4973 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4975 print STDERR
"unable to parse line in statfile - $line";
4982 sub restore_archive
{
4983 my ($archive, $vmid, $user, $opts) = @_;
4985 my $format = $opts->{format
};
4988 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4989 $format = 'tar' if !$format;
4991 } elsif ($archive =~ m/\.tar$/) {
4992 $format = 'tar' if !$format;
4993 } elsif ($archive =~ m/.tar.lzo$/) {
4994 $format = 'tar' if !$format;
4996 } elsif ($archive =~ m/\.vma$/) {
4997 $format = 'vma' if !$format;
4998 } elsif ($archive =~ m/\.vma\.gz$/) {
4999 $format = 'vma' if !$format;
5001 } elsif ($archive =~ m/\.vma\.lzo$/) {
5002 $format = 'vma' if !$format;
5005 $format = 'vma' if !$format; # default
5008 # try to detect archive format
5009 if ($format eq 'tar') {
5010 return restore_tar_archive
($archive, $vmid, $user, $opts);
5012 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5016 sub restore_update_config_line
{
5017 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5019 return if $line =~ m/^\#qmdump\#/;
5020 return if $line =~ m/^\#vzdump\#/;
5021 return if $line =~ m/^lock:/;
5022 return if $line =~ m/^unused\d+:/;
5023 return if $line =~ m/^parent:/;
5024 return if $line =~ m/^template:/; # restored VM is never a template
5026 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5027 # try to convert old 1.X settings
5028 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5029 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5030 my ($model, $macaddr) = split(/\=/, $devconfig);
5031 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5034 bridge
=> "vmbr$ind",
5035 macaddr
=> $macaddr,
5037 my $netstr = print_net
($net);
5039 print $outfd "net$cookie->{netcount}: $netstr\n";
5040 $cookie->{netcount
}++;
5042 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5043 my ($id, $netstr) = ($1, $2);
5044 my $net = parse_net
($netstr);
5045 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5046 $netstr = print_net
($net);
5047 print $outfd "$id: $netstr\n";
5048 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5051 if ($line =~ m/backup=no/) {
5052 print $outfd "#$line";
5053 } elsif ($virtdev && $map->{$virtdev}) {
5054 my $di = parse_drive
($virtdev, $value);
5055 delete $di->{format
}; # format can change on restore
5056 $di->{file
} = $map->{$virtdev};
5057 $value = print_drive
($vmid, $di);
5058 print $outfd "$virtdev: $value\n";
5068 my ($cfg, $vmid) = @_;
5070 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5072 my $volid_hash = {};
5073 foreach my $storeid (keys %$info) {
5074 foreach my $item (@{$info->{$storeid}}) {
5075 next if !($item->{volid
} && $item->{size
});
5076 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5077 $volid_hash->{$item->{volid
}} = $item;
5084 sub get_used_paths
{
5085 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5089 my $scan_config = sub {
5090 my ($cref, $snapname) = @_;
5092 foreach my $key (keys %$cref) {
5093 my $value = $cref->{$key};
5094 if (valid_drivename
($key)) {
5095 next if $skip_drive && $key eq $skip_drive;
5096 my $drive = parse_drive
($key, $value);
5097 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5098 if ($drive->{file
} =~ m!^/!) {
5099 $used_path->{$drive->{file
}}++; # = 1;
5101 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5103 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5105 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5106 $used_path->{$path}++; # = 1;
5112 &$scan_config($conf);
5116 if ($scan_snapshots) {
5117 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5118 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5125 sub update_disksize
{
5126 my ($vmid, $conf, $volid_hash) = @_;
5132 # Note: it is allowed to define multiple storages with same path (alias), so
5133 # we need to check both 'volid' and real 'path' (two different volid can point
5134 # to the same path).
5139 foreach my $opt (keys %$conf) {
5140 if (valid_drivename
($opt)) {
5141 my $drive = parse_drive
($opt, $conf->{$opt});
5142 my $volid = $drive->{file
};
5145 $used->{$volid} = 1;
5146 if ($volid_hash->{$volid} &&
5147 (my $path = $volid_hash->{$volid}->{path
})) {
5148 $usedpath->{$path} = 1;
5151 next if drive_is_cdrom
($drive);
5152 next if !$volid_hash->{$volid};
5154 $drive->{size
} = $volid_hash->{$volid}->{size
};
5155 my $new = print_drive
($vmid, $drive);
5156 if ($new ne $conf->{$opt}) {
5158 $conf->{$opt} = $new;
5163 # remove 'unusedX' entry if volume is used
5164 foreach my $opt (keys %$conf) {
5165 next if $opt !~ m/^unused\d+$/;
5166 my $volid = $conf->{$opt};
5167 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5168 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5170 delete $conf->{$opt};
5174 foreach my $volid (sort keys %$volid_hash) {
5175 next if $volid =~ m/vm-$vmid-state-/;
5176 next if $used->{$volid};
5177 my $path = $volid_hash->{$volid}->{path
};
5178 next if !$path; # just to be sure
5179 next if $usedpath->{$path};
5181 add_unused_volume
($conf, $volid);
5182 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5189 my ($vmid, $nolock) = @_;
5191 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5193 my $volid_hash = scan_volids
($cfg, $vmid);
5195 my $updatefn = sub {
5198 my $conf = load_config
($vmid);
5203 foreach my $volid (keys %$volid_hash) {
5204 my $info = $volid_hash->{$volid};
5205 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5208 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5210 update_config_nolock
($vmid, $conf, 1) if $changes;
5213 if (defined($vmid)) {
5217 lock_config
($vmid, $updatefn, $vmid);
5220 my $vmlist = config_list
();
5221 foreach my $vmid (keys %$vmlist) {
5225 lock_config
($vmid, $updatefn, $vmid);
5231 sub restore_vma_archive
{
5232 my ($archive, $vmid, $user, $opts, $comp) = @_;
5234 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5235 my $readfrom = $archive;
5240 my $qarchive = PVE
::Tools
::shellquote
($archive);
5241 if ($comp eq 'gzip') {
5242 $uncomp = "zcat $qarchive|";
5243 } elsif ($comp eq 'lzop') {
5244 $uncomp = "lzop -d -c $qarchive|";
5246 die "unknown compression method '$comp'\n";
5251 my $tmpdir = "/var/tmp/vzdumptmp$$";
5254 # disable interrupts (always do cleanups)
5255 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5256 warn "got interrupt - ignored\n";
5259 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5260 POSIX
::mkfifo
($mapfifo, 0600);
5263 my $openfifo = sub {
5264 open($fifofh, '>', $mapfifo) || die $!;
5267 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5274 my $rpcenv = PVE
::RPCEnvironment
::get
();
5276 my $conffile = config_file
($vmid);
5277 my $tmpfn = "$conffile.$$.tmp";
5279 # Note: $oldconf is undef if VM does not exists
5280 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5282 my $print_devmap = sub {
5283 my $virtdev_hash = {};
5285 my $cfgfn = "$tmpdir/qemu-server.conf";
5287 # we can read the config - that is already extracted
5288 my $fh = IO
::File-
>new($cfgfn, "r") ||
5289 "unable to read qemu-server.conf - $!\n";
5291 while (defined(my $line = <$fh>)) {
5292 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5293 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5294 die "archive does not contain data for drive '$virtdev'\n"
5295 if !$devinfo->{$devname};
5296 if (defined($opts->{storage
})) {
5297 $storeid = $opts->{storage
} || 'local';
5298 } elsif (!$storeid) {
5301 $format = 'raw' if !$format;
5302 $devinfo->{$devname}->{devname
} = $devname;
5303 $devinfo->{$devname}->{virtdev
} = $virtdev;
5304 $devinfo->{$devname}->{format
} = $format;
5305 $devinfo->{$devname}->{storeid
} = $storeid;
5307 # check permission on storage
5308 my $pool = $opts->{pool
}; # todo: do we need that?
5309 if ($user ne 'root@pam') {
5310 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5313 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5317 foreach my $devname (keys %$devinfo) {
5318 die "found no device mapping information for device '$devname'\n"
5319 if !$devinfo->{$devname}->{virtdev
};
5322 my $cfg = cfs_read_file
('storage.cfg');
5324 # create empty/temp config
5326 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5327 foreach_drive
($oldconf, sub {
5328 my ($ds, $drive) = @_;
5330 return if drive_is_cdrom
($drive);
5332 my $volid = $drive->{file
};
5334 return if !$volid || $volid =~ m
|^/|;
5336 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5337 return if !$path || !$owner || ($owner != $vmid);
5339 # Note: only delete disk we want to restore
5340 # other volumes will become unused
5341 if ($virtdev_hash->{$ds}) {
5342 PVE
::Storage
::vdisk_free
($cfg, $volid);
5348 foreach my $virtdev (sort keys %$virtdev_hash) {
5349 my $d = $virtdev_hash->{$virtdev};
5350 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5351 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5353 # test if requested format is supported
5354 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5355 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5356 $d->{format
} = $defFormat if !$supported;
5358 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5359 $d->{format
}, undef, $alloc_size);
5360 print STDERR
"new volume ID is '$volid'\n";
5361 $d->{volid
} = $volid;
5362 my $path = PVE
::Storage
::path
($cfg, $volid);
5364 my $write_zeros = 1;
5365 # fixme: what other storages types initialize volumes with zero?
5366 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5367 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5371 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5373 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5374 $map->{$virtdev} = $volid;
5377 $fh->seek(0, 0) || die "seek failed - $!\n";
5379 my $outfd = new IO
::File
($tmpfn, "w") ||
5380 die "unable to write config for VM $vmid\n";
5382 my $cookie = { netcount
=> 0 };
5383 while (defined(my $line = <$fh>)) {
5384 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5393 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5394 die "interrupted by signal\n";
5396 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5398 $oldtimeout = alarm($timeout);
5405 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5406 my ($dev_id, $size, $devname) = ($1, $2, $3);
5407 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5408 } elsif ($line =~ m/^CTIME: /) {
5409 # we correctly received the vma config, so we can disable
5410 # the timeout now for disk allocation (set to 10 minutes, so
5411 # that we always timeout if something goes wrong)
5414 print $fifofh "done\n";
5415 my $tmp = $oldtimeout || 0;
5416 $oldtimeout = undef;
5422 print "restore vma archive: $cmd\n";
5423 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5427 alarm($oldtimeout) if $oldtimeout;
5435 my $cfg = cfs_read_file
('storage.cfg');
5436 foreach my $devname (keys %$devinfo) {
5437 my $volid = $devinfo->{$devname}->{volid
};
5440 if ($volid =~ m
|^/|) {
5441 unlink $volid || die 'unlink failed\n';
5443 PVE
::Storage
::vdisk_free
($cfg, $volid);
5445 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5447 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5454 rename($tmpfn, $conffile) ||
5455 die "unable to commit configuration file '$conffile'\n";
5457 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5459 eval { rescan
($vmid, 1); };
5463 sub restore_tar_archive
{
5464 my ($archive, $vmid, $user, $opts) = @_;
5466 if ($archive ne '-') {
5467 my $firstfile = tar_archive_read_firstfile
($archive);
5468 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5469 if $firstfile ne 'qemu-server.conf';
5472 my $storecfg = cfs_read_file
('storage.cfg');
5474 # destroy existing data - keep empty config
5475 my $vmcfgfn = config_file
($vmid);
5476 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5478 my $tocmd = "/usr/lib/qemu-server/qmextract";
5480 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5481 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5482 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5483 $tocmd .= ' --info' if $opts->{info
};
5485 # tar option "xf" does not autodetect compression when read from STDIN,
5486 # so we pipe to zcat
5487 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5488 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5490 my $tmpdir = "/var/tmp/vzdumptmp$$";
5493 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5494 local $ENV{VZDUMP_VMID
} = $vmid;
5495 local $ENV{VZDUMP_USER
} = $user;
5497 my $conffile = config_file
($vmid);
5498 my $tmpfn = "$conffile.$$.tmp";
5500 # disable interrupts (always do cleanups)
5501 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5502 print STDERR
"got interrupt - ignored\n";
5507 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5508 die "interrupted by signal\n";
5511 if ($archive eq '-') {
5512 print "extracting archive from STDIN\n";
5513 run_command
($cmd, input
=> "<&STDIN");
5515 print "extracting archive '$archive'\n";
5519 return if $opts->{info
};
5523 my $statfile = "$tmpdir/qmrestore.stat";
5524 if (my $fd = IO
::File-
>new($statfile, "r")) {
5525 while (defined (my $line = <$fd>)) {
5526 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5527 $map->{$1} = $2 if $1;
5529 print STDERR
"unable to parse line in statfile - $line\n";
5535 my $confsrc = "$tmpdir/qemu-server.conf";
5537 my $srcfd = new IO
::File
($confsrc, "r") ||
5538 die "unable to open file '$confsrc'\n";
5540 my $outfd = new IO
::File
($tmpfn, "w") ||
5541 die "unable to write config for VM $vmid\n";
5543 my $cookie = { netcount
=> 0 };
5544 while (defined (my $line = <$srcfd>)) {
5545 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5557 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5564 rename $tmpfn, $conffile ||
5565 die "unable to commit configuration file '$conffile'\n";
5567 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5569 eval { rescan
($vmid, 1); };
5574 # Internal snapshots
5576 # NOTE: Snapshot create/delete involves several non-atomic
5577 # action, and can take a long time.
5578 # So we try to avoid locking the file and use 'lock' variable
5579 # inside the config file instead.
5581 my $snapshot_copy_config = sub {
5582 my ($source, $dest) = @_;
5584 foreach my $k (keys %$source) {
5585 next if $k eq 'snapshots';
5586 next if $k eq 'snapstate';
5587 next if $k eq 'snaptime';
5588 next if $k eq 'vmstate';
5589 next if $k eq 'lock';
5590 next if $k eq 'digest';
5591 next if $k eq 'description';
5592 next if $k =~ m/^unused\d+$/;
5594 $dest->{$k} = $source->{$k};
5598 my $snapshot_apply_config = sub {
5599 my ($conf, $snap) = @_;
5601 # copy snapshot list
5603 snapshots
=> $conf->{snapshots
},
5606 # keep description and list of unused disks
5607 foreach my $k (keys %$conf) {
5608 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5609 $newconf->{$k} = $conf->{$k};
5612 &$snapshot_copy_config($snap, $newconf);
5617 sub foreach_writable_storage
{
5618 my ($conf, $func) = @_;
5622 foreach my $ds (keys %$conf) {
5623 next if !valid_drivename
($ds);
5625 my $drive = parse_drive
($ds, $conf->{$ds});
5627 next if drive_is_cdrom
($drive);
5629 my $volid = $drive->{file
};
5631 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5632 $sidhash->{$sid} = $sid if $sid;
5635 foreach my $sid (sort keys %$sidhash) {
5640 my $alloc_vmstate_volid = sub {
5641 my ($storecfg, $vmid, $conf, $snapname) = @_;
5643 # Note: we try to be smart when selecting a $target storage
5647 # search shared storage first
5648 foreach_writable_storage
($conf, sub {
5650 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5651 return if !$scfg->{shared
};
5653 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5657 # now search local storage
5658 foreach_writable_storage
($conf, sub {
5660 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5661 return if $scfg->{shared
};
5663 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5667 $target = 'local' if !$target;
5669 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5670 # we abort live save after $conf->{memory}, so we need at max twice that space
5671 my $size = $conf->{memory
}*2 + $driver_state_size;
5673 my $name = "vm-$vmid-state-$snapname";
5674 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5675 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5676 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5681 my $snapshot_prepare = sub {
5682 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5686 my $updatefn = sub {
5688 my $conf = load_config
($vmid);
5690 die "you can't take a snapshot if it's a template\n"
5691 if is_template
($conf);
5695 $conf->{lock} = 'snapshot';
5697 die "snapshot name '$snapname' already used\n"
5698 if defined($conf->{snapshots
}->{$snapname});
5700 my $storecfg = PVE
::Storage
::config
();
5701 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5703 $snap = $conf->{snapshots
}->{$snapname} = {};
5705 if ($save_vmstate && check_running
($vmid)) {
5706 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5709 &$snapshot_copy_config($conf, $snap);
5711 $snap->{snapstate
} = "prepare";
5712 $snap->{snaptime
} = time();
5713 $snap->{description
} = $comment if $comment;
5715 # always overwrite machine if we save vmstate. This makes sure we
5716 # can restore it later using correct machine type
5717 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5719 update_config_nolock
($vmid, $conf, 1);
5722 lock_config
($vmid, $updatefn);
5727 my $snapshot_commit = sub {
5728 my ($vmid, $snapname) = @_;
5730 my $updatefn = sub {
5732 my $conf = load_config
($vmid);
5734 die "missing snapshot lock\n"
5735 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5737 my $has_machine_config = defined($conf->{machine
});
5739 my $snap = $conf->{snapshots
}->{$snapname};
5741 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5743 die "wrong snapshot state\n"
5744 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5746 delete $snap->{snapstate
};
5747 delete $conf->{lock};
5749 my $newconf = &$snapshot_apply_config($conf, $snap);
5751 delete $newconf->{machine
} if !$has_machine_config;
5753 $newconf->{parent
} = $snapname;
5755 update_config_nolock
($vmid, $newconf, 1);
5758 lock_config
($vmid, $updatefn);
5761 sub snapshot_rollback
{
5762 my ($vmid, $snapname) = @_;
5766 my $storecfg = PVE
::Storage
::config
();
5768 my $conf = load_config
($vmid);
5770 my $get_snapshot_config = sub {
5772 die "you can't rollback if vm is a template\n" if is_template
($conf);
5774 my $res = $conf->{snapshots
}->{$snapname};
5776 die "snapshot '$snapname' does not exist\n" if !defined($res);
5781 my $snap = &$get_snapshot_config();
5783 foreach_drive
($snap, sub {
5784 my ($ds, $drive) = @_;
5786 return if drive_is_cdrom
($drive);
5788 my $volid = $drive->{file
};
5790 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5793 my $updatefn = sub {
5795 $conf = load_config
($vmid);
5797 $snap = &$get_snapshot_config();
5799 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5800 if $snap->{snapstate
};
5804 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5807 die "unable to rollback vm $vmid: vm is running\n"
5808 if check_running
($vmid);
5811 $conf->{lock} = 'rollback';
5813 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5814 delete $conf->{lock};
5820 my $has_machine_config = defined($conf->{machine
});
5822 # copy snapshot config to current config
5823 $conf = &$snapshot_apply_config($conf, $snap);
5824 $conf->{parent
} = $snapname;
5826 # Note: old code did not store 'machine', so we try to be smart
5827 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5828 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5829 # we remove the 'machine' configuration if not explicitly specified
5830 # in the original config.
5831 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5834 update_config_nolock
($vmid, $conf, 1);
5836 if (!$prepare && $snap->{vmstate
}) {
5837 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5838 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5842 lock_config
($vmid, $updatefn);
5844 foreach_drive
($snap, sub {
5845 my ($ds, $drive) = @_;
5847 return if drive_is_cdrom
($drive);
5849 my $volid = $drive->{file
};
5850 my $device = "drive-$ds";
5852 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5856 lock_config
($vmid, $updatefn);
5859 my $savevm_wait = sub {
5863 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5864 if (!$stat->{status
}) {
5865 die "savevm not active\n";
5866 } elsif ($stat->{status
} eq 'active') {
5869 } elsif ($stat->{status
} eq 'completed') {
5872 die "query-savevm returned status '$stat->{status}'\n";
5877 sub do_snapshots_with_qemu
{
5878 my ($storecfg, $volid) = @_;
5880 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5882 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5886 if ($volid =~ m/\.(qcow2|qed)$/){
5893 sub snapshot_create
{
5894 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5896 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5898 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5900 my $config = load_config
($vmid);
5902 my $running = check_running
($vmid);
5904 my $freezefs = $running && $config->{agent
};
5905 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5910 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5911 warn "guest-fsfreeze-freeze problems - $@" if $@;
5915 # create internal snapshots of all drives
5917 my $storecfg = PVE
::Storage
::config
();
5920 if ($snap->{vmstate
}) {
5921 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5922 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5923 &$savevm_wait($vmid);
5925 vm_mon_cmd
($vmid, "savevm-start");
5929 foreach_drive
($snap, sub {
5930 my ($ds, $drive) = @_;
5932 return if drive_is_cdrom
($drive);
5934 my $volid = $drive->{file
};
5935 my $device = "drive-$ds";
5937 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5938 $drivehash->{$ds} = 1;
5944 eval { vm_mon_cmd
($vmid, "savevm-end") };
5948 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5949 warn "guest-fsfreeze-thaw problems - $@" if $@;
5952 # savevm-end is async, we need to wait
5954 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5955 if (!$stat->{bytes
}) {
5958 print "savevm not yet finished\n";
5966 warn "snapshot create failed: starting cleanup\n";
5967 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5972 &$snapshot_commit($vmid, $snapname);
5975 # Note: $drivehash is only set when called from snapshot_create.
5976 sub snapshot_delete
{
5977 my ($vmid, $snapname, $force, $drivehash) = @_;
5984 my $unlink_parent = sub {
5985 my ($confref, $new_parent) = @_;
5987 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5989 $confref->{parent
} = $new_parent;
5991 delete $confref->{parent
};
5996 my $updatefn = sub {
5997 my ($remove_drive) = @_;
5999 my $conf = load_config
($vmid);
6003 die "you can't delete a snapshot if vm is a template\n"
6004 if is_template
($conf);
6007 $snap = $conf->{snapshots
}->{$snapname};
6009 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6011 # remove parent refs
6013 &$unlink_parent($conf, $snap->{parent
});
6014 foreach my $sn (keys %{$conf->{snapshots
}}) {
6015 next if $sn eq $snapname;
6016 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6020 if ($remove_drive) {
6021 if ($remove_drive eq 'vmstate') {
6022 delete $snap->{$remove_drive};
6024 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6025 my $volid = $drive->{file
};
6026 delete $snap->{$remove_drive};
6027 add_unused_volume
($conf, $volid);
6032 $snap->{snapstate
} = 'delete';
6034 delete $conf->{snapshots
}->{$snapname};
6035 delete $conf->{lock} if $drivehash;
6036 foreach my $volid (@$unused) {
6037 add_unused_volume
($conf, $volid);
6041 update_config_nolock
($vmid, $conf, 1);
6044 lock_config
($vmid, $updatefn);
6046 # now remove vmstate file
6048 my $storecfg = PVE
::Storage
::config
();
6050 if ($snap->{vmstate
}) {
6051 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6053 die $err if !$force;
6056 # save changes (remove vmstate from snapshot)
6057 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6060 # now remove all internal snapshots
6061 foreach_drive
($snap, sub {
6062 my ($ds, $drive) = @_;
6064 return if drive_is_cdrom
($drive);
6066 my $volid = $drive->{file
};
6067 my $device = "drive-$ds";
6069 if (!$drivehash || $drivehash->{$ds}) {
6070 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6072 die $err if !$force;
6077 # save changes (remove drive fron snapshot)
6078 lock_config
($vmid, $updatefn, $ds) if !$force;
6079 push @$unused, $volid;
6082 # now cleanup config
6084 lock_config
($vmid, $updatefn);
6088 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6091 foreach_drive
($conf, sub {
6092 my ($ds, $drive) = @_;
6094 return if drive_is_cdrom
($drive);
6095 my $volid = $drive->{file
};
6096 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6099 return $err ?
0 : 1;
6102 sub template_create
{
6103 my ($vmid, $conf, $disk) = @_;
6105 my $storecfg = PVE
::Storage
::config
();
6107 foreach_drive
($conf, sub {
6108 my ($ds, $drive) = @_;
6110 return if drive_is_cdrom
($drive);
6111 return if $disk && $ds ne $disk;
6113 my $volid = $drive->{file
};
6114 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6116 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6117 $drive->{file
} = $voliddst;
6118 $conf->{$ds} = print_drive
($vmid, $drive);
6119 update_config_nolock
($vmid, $conf, 1);
6126 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6129 sub qemu_img_convert
{
6130 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6132 my $storecfg = PVE
::Storage
::config
();
6133 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6134 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6136 if ($src_storeid && $dst_storeid) {
6137 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6138 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6140 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6141 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6143 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6144 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6147 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6148 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6149 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6153 if($line =~ m/\((\S+)\/100\
%\)/){
6155 my $transferred = int($size * $percent / 100);
6156 my $remaining = $size - $transferred;
6158 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6163 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6165 die "copy failed: $err" if $err;
6169 sub qemu_img_format
{
6170 my ($scfg, $volname) = @_;
6172 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6179 sub qemu_drive_mirror
{
6180 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6182 my $storecfg = PVE
::Storage
::config
();
6183 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6185 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6187 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6189 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6191 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6192 $opts->{format
} = $format if $format;
6194 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6197 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6199 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6200 my $stat = @$stats[0];
6201 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6202 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6204 my $busy = $stat->{busy
};
6205 my $ready = $stat->{ready
};
6207 if (my $total = $stat->{len
}) {
6208 my $transferred = $stat->{offset
} || 0;
6209 my $remaining = $total - $transferred;
6210 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6212 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6216 if ($stat->{ready
} eq 'true') {
6218 last if $vmiddst != $vmid;
6220 # try to switch the disk if source and destination are on the same guest
6221 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6223 die $@ if $@ !~ m/cannot be completed/;
6232 my $cancel_job = sub {
6233 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6235 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6236 my $stat = @$stats[0];
6243 eval { &$cancel_job(); };
6244 die "mirroring error: $err";
6247 if ($vmiddst != $vmid) {
6248 # if we clone a disk for a new target vm, we don't switch the disk
6249 &$cancel_job(); # so we call block-job-cancel
6254 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6255 $newvmid, $storage, $format, $full, $newvollist) = @_;
6260 print "create linked clone of drive $drivename ($drive->{file})\n";
6261 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6262 push @$newvollist, $newvolid;
6264 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6265 $storeid = $storage if $storage;
6267 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6269 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6270 $format = qemu_img_format
($scfg, $volname);
6273 # test if requested format is supported - else use default
6274 my $supported = grep { $_ eq $format } @$validFormats;
6275 $format = $defFormat if !$supported;
6277 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6279 print "create full clone of drive $drivename ($drive->{file})\n";
6280 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6281 push @$newvollist, $newvolid;
6283 if (!$running || $snapname) {
6284 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6286 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6290 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6293 $disk->{format
} = undef;
6294 $disk->{file
} = $newvolid;
6295 $disk->{size
} = $size;
6300 # this only works if VM is running
6301 sub get_current_qemu_machine
{
6304 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6305 my $res = vm_qmp_command
($vmid, $cmd);
6307 my ($current, $default);
6308 foreach my $e (@$res) {
6309 $default = $e->{name
} if $e->{'is-default'};
6310 $current = $e->{name
} if $e->{'is-current'};
6313 # fallback to the default machine if current is not supported by qemu
6314 return $current || $default || 'pc';
6317 sub qemu_machine_feature_enabled
{
6318 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6323 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6325 $current_major = $3;
6326 $current_minor = $4;
6328 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6330 $current_major = $1;
6331 $current_minor = $2;
6334 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6343 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6344 my (undef, $id, $function) = @_;
6345 my $res = { id
=> $id, function
=> $function};
6346 push @{$devices->{$id}}, $res;
6352 sub vm_iothreads_list
{
6355 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6358 foreach my $iothread (@$res) {
6359 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6366 my ($conf, $drive) = @_;
6370 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6372 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6378 my $controller = int($drive->{index} / $maxdev);
6379 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6381 return ($maxdev, $controller, $controller_prefix);