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+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
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]",
390 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
395 # what about other qemu settings ?
397 #machine => 'string',
410 ##soundhw => 'string',
412 while (my ($k, $v) = each %$confdesc) {
413 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
416 my $MAX_IDE_DISKS = 4;
417 my $MAX_SCSI_DISKS = 14;
418 my $MAX_VIRTIO_DISKS = 16;
419 my $MAX_SATA_DISKS = 6;
420 my $MAX_USB_DEVICES = 5;
422 my $MAX_UNUSED_DISKS = 8;
423 my $MAX_HOSTPCI_DEVICES = 4;
424 my $MAX_SERIAL_PORTS = 4;
425 my $MAX_PARALLEL_PORTS = 3;
427 my $MAX_MEM = 4194304;
428 my $STATICMEM = 1024;
432 type
=> 'string', format
=> 'pve-qm-numanode',
433 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
434 description
=> "numa topology",
436 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
438 for (my $i = 0; $i < $MAX_NUMA; $i++) {
439 $confdesc->{"numa$i"} = $numadesc;
442 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
443 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
444 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
445 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
449 type
=> 'string', format
=> 'pve-qm-net',
450 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
451 description
=> <<EODESCR,
452 Specify network devices.
454 MODEL is one of: $nic_model_list_txt
456 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
457 automatically generated if not specified.
459 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
461 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'.
463 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
469 The DHCP server assign addresses to the guest starting from 10.0.2.15.
473 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
475 for (my $i = 0; $i < $MAX_NETS; $i++) {
476 $confdesc->{"net$i"} = $netdesc;
483 type
=> 'string', format
=> 'pve-qm-drive',
484 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] [,serial=serial][,model=model]',
485 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
487 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
491 type
=> 'string', format
=> 'pve-qm-drive',
492 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>] [,serial=serial]',
493 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
499 type
=> 'string', format
=> 'pve-qm-drive',
500 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] [,serial=serial]',
501 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
503 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
507 type
=> 'string', format
=> 'pve-qm-drive',
508 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] [,serial=serial]',
509 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
511 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
515 type
=> 'string', format
=> 'pve-qm-usb-device',
516 typetext
=> 'host=HOSTUSBDEVICE|spice',
517 description
=> <<EODESCR,
518 Configure an USB device (n is 0 to 4). This can be used to
519 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
521 'bus-port(.port)*' (decimal numbers) or
522 'vendor_id:product_id' (hexadeciaml numbers)
524 You can use the 'lsusb -t' command to list existing usb devices.
526 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
528 The value 'spice' can be used to add a usb redirection devices for spice.
532 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
536 type
=> 'string', format
=> 'pve-qm-hostpci',
537 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
538 description
=> <<EODESCR,
539 Map host pci devices. HOSTPCIDEVICE syntax is:
541 'bus:dev.func' (hexadecimal numbers)
543 You can us the 'lspci' command to list existing pci devices.
545 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
547 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
549 Experimental: user reported problems with this option.
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
557 pattern
=> '(/dev/.+|socket)',
558 description
=> <<EODESCR,
559 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).
561 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
563 Experimental: user reported problems with this option.
570 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
571 description
=> <<EODESCR,
572 Map host parallel devices (n is 0 to 2).
574 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
576 Experimental: user reported problems with this option.
580 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
581 $confdesc->{"parallel$i"} = $paralleldesc;
584 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
585 $confdesc->{"serial$i"} = $serialdesc;
588 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
589 $confdesc->{"hostpci$i"} = $hostpcidesc;
592 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
593 $drivename_hash->{"ide$i"} = 1;
594 $confdesc->{"ide$i"} = $idedesc;
597 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
598 $drivename_hash->{"sata$i"} = 1;
599 $confdesc->{"sata$i"} = $satadesc;
602 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
603 $drivename_hash->{"scsi$i"} = 1;
604 $confdesc->{"scsi$i"} = $scsidesc ;
607 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
608 $drivename_hash->{"virtio$i"} = 1;
609 $confdesc->{"virtio$i"} = $virtiodesc;
612 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
613 $confdesc->{"usb$i"} = $usbdesc;
618 type
=> 'string', format
=> 'pve-volume-id',
619 description
=> "Reference to unused volumes.",
622 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
623 $confdesc->{"unused$i"} = $unuseddesc;
626 my $kvm_api_version = 0;
630 return $kvm_api_version if $kvm_api_version;
632 my $fh = IO
::File-
>new("</dev/kvm") ||
635 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
636 $kvm_api_version = $v;
641 return $kvm_api_version;
644 my $kvm_user_version;
646 sub kvm_user_version
{
648 return $kvm_user_version if $kvm_user_version;
650 $kvm_user_version = 'unknown';
652 my $tmp = `kvm -help 2>/dev/null`;
654 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
655 $kvm_user_version = $2;
658 return $kvm_user_version;
662 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
665 # order is important - used to autoselect boot disk
666 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
667 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
668 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
669 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
672 sub valid_drivename
{
675 return defined($drivename_hash->{$dev});
680 return defined($confdesc->{$key});
684 return $nic_model_list;
687 sub os_list_description
{
692 w2k
=> 'Windows 2000',
693 w2k3
=>, 'Windows 2003',
694 w2k8
=> 'Windows 2008',
695 wvista
=> 'Windows Vista',
697 win8
=> 'Windows 8/2012',
707 return $cdrom_path if $cdrom_path;
709 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
710 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
711 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
715 my ($storecfg, $vmid, $cdrom) = @_;
717 if ($cdrom eq 'cdrom') {
718 return get_cdrom_path
();
719 } elsif ($cdrom eq 'none') {
721 } elsif ($cdrom =~ m
|^/|) {
724 return PVE
::Storage
::path
($storecfg, $cdrom);
728 # try to convert old style file names to volume IDs
729 sub filename_to_volume_id
{
730 my ($vmid, $file, $media) = @_;
732 if (!($file eq 'none' || $file eq 'cdrom' ||
733 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
735 return undef if $file =~ m
|/|;
737 if ($media && $media eq 'cdrom') {
738 $file = "local:iso/$file";
740 $file = "local:$vmid/$file";
747 sub verify_media_type
{
748 my ($opt, $vtype, $media) = @_;
753 if ($media eq 'disk') {
755 } elsif ($media eq 'cdrom') {
758 die "internal error";
761 return if ($vtype eq $etype);
763 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
766 sub cleanup_drive_path
{
767 my ($opt, $storecfg, $drive) = @_;
769 # try to convert filesystem paths to volume IDs
771 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
772 ($drive->{file
} !~ m
|^/dev/.+|) &&
773 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
774 ($drive->{file
} !~ m/^\d+$/)) {
775 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
776 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
777 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
778 verify_media_type
($opt, $vtype, $drive->{media
});
779 $drive->{file
} = $volid;
782 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
785 sub create_conf_nolock
{
786 my ($vmid, $settings) = @_;
788 my $filename = config_file
($vmid);
790 die "configuration file '$filename' already exists\n" if -f
$filename;
792 my $defaults = load_defaults
();
794 $settings->{name
} = "vm$vmid" if !$settings->{name
};
795 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
798 foreach my $opt (keys %$settings) {
799 next if !$confdesc->{$opt};
801 my $value = $settings->{$opt};
804 $data .= "$opt: $value\n";
807 PVE
::Tools
::file_set_contents
($filename, $data);
810 sub parse_hotplug_features
{
815 return $res if $data eq '0';
817 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
819 foreach my $feature (PVE
::Tools
::split_list
($data)) {
820 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
823 warn "ignoring unknown hotplug feature '$feature'\n";
829 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
830 sub pve_verify_hotplug_features
{
831 my ($value, $noerr) = @_;
833 return $value if parse_hotplug_features
($value);
835 return undef if $noerr;
837 die "unable to parse hotplug option\n";
840 my $parse_size = sub {
843 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
844 my ($size, $unit) = ($1, $3);
847 $size = $size * 1024;
848 } elsif ($unit eq 'M') {
849 $size = $size * 1024 * 1024;
850 } elsif ($unit eq 'G') {
851 $size = $size * 1024 * 1024 * 1024;
857 my $format_size = sub {
862 my $kb = int($size/1024);
863 return $size if $kb*1024 != $size;
865 my $mb = int($kb/1024);
866 return "${kb}K" if $mb*1024 != $kb;
868 my $gb = int($mb/1024);
869 return "${mb}M" if $gb*1024 != $mb;
874 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
875 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
876 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
877 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
878 # [,serial=serial][,model=model]
881 my ($key, $data) = @_;
885 # $key may be undefined - used to verify JSON parameters
886 if (!defined($key)) {
887 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
889 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
890 $res->{interface
} = $1;
896 foreach my $p (split (/,/, $data)) {
897 next if $p =~ m/^\s*$/;
899 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|serial|model)=(.+)$/) {
900 my ($k, $v) = ($1, $2);
902 $k = 'file' if $k eq 'volume';
904 return undef if defined $res->{$k};
906 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
907 return undef if !$v || $v !~ m/^\d+/;
909 $v = sprintf("%.3f", $v / (1024*1024));
913 if (!$res->{file
} && $p !~ m/=/) {
921 return undef if !$res->{file
};
923 return undef if $res->{cache
} &&
924 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
925 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
926 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
927 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
928 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
929 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
930 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
931 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
932 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
933 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
934 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
935 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
936 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
937 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
938 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
940 return undef if $res->{mbps_rd
} && $res->{mbps
};
941 return undef if $res->{mbps_wr
} && $res->{mbps
};
943 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
944 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
945 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
946 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
947 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{iops_rd
} && $res->{iops
};
951 return undef if $res->{iops_wr
} && $res->{iops
};
954 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
955 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
956 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
957 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
958 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
959 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
962 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
965 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
966 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
967 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
968 return undef if $res->{interface
} eq 'virtio';
971 # rerror does not work with scsi drives
972 if ($res->{rerror
}) {
973 return undef if $res->{interface
} eq 'scsi';
979 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
982 my ($vmid, $drive) = @_;
985 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
986 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
989 if ($drive->{size
}) {
990 $opts .= ",size=" . &$format_size($drive->{size
});
993 if (my $model = $drive->{model
}) {
994 $opts .= ",model=$model";
997 return "$drive->{file}$opts";
1001 my($fh, $noerr) = @_;
1004 my $SG_GET_VERSION_NUM = 0x2282;
1006 my $versionbuf = "\x00" x
8;
1007 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1009 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1012 my $version = unpack("I", $versionbuf);
1013 if ($version < 30000) {
1014 die "scsi generic interface too old\n" if !$noerr;
1018 my $buf = "\x00" x
36;
1019 my $sensebuf = "\x00" x
8;
1020 my $cmd = pack("C x3 C x1", 0x12, 36);
1022 # see /usr/include/scsi/sg.h
1023 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";
1025 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1026 length($sensebuf), 0, length($buf), $buf,
1027 $cmd, $sensebuf, 6000);
1029 $ret = ioctl($fh, $SG_IO, $packet);
1031 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1035 my @res = unpack($sg_io_hdr_t, $packet);
1036 if ($res[17] || $res[18]) {
1037 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1042 (my $byte0, my $byte1, $res->{vendor
},
1043 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1045 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1046 $res->{type
} = $byte0 & 31;
1054 my $fh = IO
::File-
>new("+<$path") || return undef;
1055 my $res = scsi_inquiry
($fh, 1);
1061 sub machine_type_is_q35
{
1064 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1067 sub print_tabletdevice_full
{
1070 my $q35 = machine_type_is_q35
($conf);
1072 # we use uhci for old VMs because tablet driver was buggy in older qemu
1073 my $usbbus = $q35 ?
"ehci" : "uhci";
1075 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1078 sub print_drivedevice_full
{
1079 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1084 if ($drive->{interface
} eq 'virtio') {
1085 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1086 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1087 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1088 } elsif ($drive->{interface
} eq 'scsi') {
1090 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1091 my $unit = $drive->{index} % $maxdev;
1092 my $devicetype = 'hd';
1094 if (drive_is_cdrom
($drive)) {
1097 if ($drive->{file
} =~ m
|^/|) {
1098 $path = $drive->{file
};
1100 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1103 if($path =~ m/^iscsi\:\/\
//){
1104 $devicetype = 'generic';
1106 if (my $info = path_is_scsi
($path)) {
1107 if ($info->{type
} == 0) {
1108 $devicetype = 'block';
1109 } elsif ($info->{type
} == 1) { # tape
1110 $devicetype = 'generic';
1116 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1117 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 $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}";
1122 } elsif ($drive->{interface
} eq 'ide'){
1124 my $controller = int($drive->{index} / $maxdev);
1125 my $unit = $drive->{index} % $maxdev;
1126 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1128 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1129 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1130 $device .= ",model=$model";
1132 } elsif ($drive->{interface
} eq 'sata'){
1133 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1134 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1135 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1136 } elsif ($drive->{interface
} eq 'usb') {
1138 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1140 die "unsupported interface type";
1143 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1148 sub get_initiator_name
{
1151 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1152 while (defined(my $line = <$fh>)) {
1153 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1162 sub print_drive_full
{
1163 my ($storecfg, $vmid, $drive) = @_;
1166 my $volid = $drive->{file
};
1169 if (drive_is_cdrom
($drive)) {
1170 $path = get_iso_path
($storecfg, $vmid, $volid);
1172 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1174 $path = PVE
::Storage
::path
($storecfg, $volid);
1175 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1176 $format = qemu_img_format
($scfg, $volname);
1183 foreach my $o (@qemu_drive_options) {
1184 next if $o eq 'bootindex';
1185 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1188 $opts .= ",format=$format" if $format && !$drive->{format
};
1190 foreach my $o (qw(bps bps_rd bps_wr)) {
1191 my $v = $drive->{"m$o"};
1192 $opts .= ",$o=" . int($v*1024*1024) if $v;
1195 my $cache_direct = 0;
1197 if (my $cache = $drive->{cache
}) {
1198 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1199 } elsif (!drive_is_cdrom
($drive)) {
1200 $opts .= ",cache=none";
1204 # aio native works only with O_DIRECT
1205 if (!$drive->{aio
}) {
1207 $opts .= ",aio=native";
1209 $opts .= ",aio=threads";
1213 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1214 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1216 my $pathinfo = $path ?
"file=$path," : '';
1218 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1221 sub print_netdevice_full
{
1222 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1224 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1226 my $device = $net->{model
};
1227 if ($net->{model
} eq 'virtio') {
1228 $device = 'virtio-net-pci';
1231 my $pciaddr = print_pci_addr
("$netid", $bridges);
1232 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1233 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1234 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1235 my $vectors = $net->{queues
} * 2 + 2;
1236 $tmpstr .= ",vectors=$vectors,mq=on";
1238 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1240 if ($use_old_bios_files) {
1242 if ($device eq 'virtio-net-pci') {
1243 $romfile = 'pxe-virtio.rom';
1244 } elsif ($device eq 'e1000') {
1245 $romfile = 'pxe-e1000.rom';
1246 } elsif ($device eq 'ne2k') {
1247 $romfile = 'pxe-ne2k_pci.rom';
1248 } elsif ($device eq 'pcnet') {
1249 $romfile = 'pxe-pcnet.rom';
1250 } elsif ($device eq 'rtl8139') {
1251 $romfile = 'pxe-rtl8139.rom';
1253 $tmpstr .= ",romfile=$romfile" if $romfile;
1259 sub print_netdev_full
{
1260 my ($vmid, $conf, $net, $netid) = @_;
1263 if ($netid =~ m/^net(\d+)$/) {
1267 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1269 my $ifname = "tap${vmid}i$i";
1271 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1272 die "interface name '$ifname' is too long (max 15 character)\n"
1273 if length($ifname) >= 16;
1275 my $vhostparam = '';
1276 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1278 my $vmname = $conf->{name
} || "vm$vmid";
1282 if ($net->{bridge
}) {
1283 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1285 $netdev = "type=user,id=$netid,hostname=$vmname";
1288 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1293 sub drive_is_cdrom
{
1296 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1305 foreach my $kvp (split(/,/, $data)) {
1307 if ($kvp =~ m/^memory=(\S+)$/) {
1308 $res->{memory
} = $1;
1309 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1310 $res->{policy
} = $1;
1311 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1312 $res->{cpus
}->{start
} = $1;
1313 $res->{cpus
}->{end
} = $3;
1314 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1315 $res->{hostnodes
}->{start
} = $1;
1316 $res->{hostnodes
}->{end
} = $3;
1328 return undef if !$value;
1331 my @list = split(/,/, $value);
1335 foreach my $kv (@list) {
1337 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1340 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1343 my $pcidevices = lspci
($2);
1344 $res->{pciid
} = $pcidevices->{$2};
1346 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1347 $res->{rombar
} = $1;
1348 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1349 $res->{'x-vga'} = $1;
1350 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1351 $res->{pcie
} = 1 if $1 == 1;
1353 warn "unknown hostpci setting '$kv'\n";
1357 return undef if !$found;
1362 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1368 foreach my $kvp (split(/,/, $data)) {
1370 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) {
1372 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1373 $res->{model
} = $model;
1374 $res->{macaddr
} = $mac;
1375 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1376 $res->{bridge
} = $1;
1377 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1378 $res->{queues
} = $1;
1379 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1381 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1383 } elsif ($kvp =~ m/^firewall=([01])$/) {
1384 $res->{firewall
} = $1;
1385 } elsif ($kvp =~ m/^link_down=([01])$/) {
1386 $res->{link_down
} = $1;
1393 return undef if !$res->{model
};
1401 my $res = "$net->{model}";
1402 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1403 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1404 $res .= ",rate=$net->{rate}" if $net->{rate
};
1405 $res .= ",tag=$net->{tag}" if $net->{tag
};
1406 $res .= ",firewall=1" if $net->{firewall
};
1407 $res .= ",link_down=1" if $net->{link_down
};
1408 $res .= ",queues=$net->{queues}" if $net->{queues
};
1413 sub add_random_macs
{
1414 my ($settings) = @_;
1416 foreach my $opt (keys %$settings) {
1417 next if $opt !~ m/^net(\d+)$/;
1418 my $net = parse_net
($settings->{$opt});
1420 $settings->{$opt} = print_net
($net);
1424 sub add_unused_volume
{
1425 my ($config, $volid) = @_;
1428 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1429 my $test = "unused$ind";
1430 if (my $vid = $config->{$test}) {
1431 return if $vid eq $volid; # do not add duplicates
1437 die "To many unused volume - please delete them first.\n" if !$key;
1439 $config->{$key} = $volid;
1444 sub vm_is_volid_owner
{
1445 my ($storecfg, $vmid, $volid) = @_;
1447 if ($volid !~ m
|^/|) {
1449 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1450 if ($owner && ($owner == $vmid)) {
1458 sub split_flagged_list
{
1459 my $text = shift || '';
1460 $text =~ s/[,;]/ /g;
1462 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1465 sub join_flagged_list
{
1466 my ($how, $lst) = @_;
1467 join $how, map { $lst->{$_} . $_ } keys %$lst;
1470 sub vmconfig_delete_pending_option
{
1471 my ($conf, $key, $force) = @_;
1473 delete $conf->{pending
}->{$key};
1474 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1475 $pending_delete_hash->{$key} = $force ?
'!' : '';
1476 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1479 sub vmconfig_undelete_pending_option
{
1480 my ($conf, $key) = @_;
1482 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1483 delete $pending_delete_hash->{$key};
1485 if (%$pending_delete_hash) {
1486 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1488 delete $conf->{pending
}->{delete};
1492 sub vmconfig_register_unused_drive
{
1493 my ($storecfg, $vmid, $conf, $drive) = @_;
1495 if (!drive_is_cdrom
($drive)) {
1496 my $volid = $drive->{file
};
1497 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1498 add_unused_volume
($conf, $volid, $vmid);
1503 sub vmconfig_cleanup_pending
{
1506 # remove pending changes when nothing changed
1508 foreach my $opt (keys %{$conf->{pending
}}) {
1509 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1511 delete $conf->{pending
}->{$opt};
1515 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1516 my $pending_delete_hash = {};
1517 while (my ($opt, $force) = each %$current_delete_hash) {
1518 if (defined($conf->{$opt})) {
1519 $pending_delete_hash->{$opt} = $force;
1525 if (%$pending_delete_hash) {
1526 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1528 delete $conf->{pending
}->{delete};
1534 my $valid_smbios1_options = {
1535 manufacturer
=> '\S+',
1539 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1544 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1550 foreach my $kvp (split(/,/, $data)) {
1551 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1552 my ($k, $v) = split(/=/, $kvp);
1553 return undef if !defined($k) || !defined($v);
1554 return undef if !$valid_smbios1_options->{$k};
1555 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1566 foreach my $k (keys %$smbios1) {
1567 next if !defined($smbios1->{$k});
1568 next if !$valid_smbios1_options->{$k};
1569 $data .= ',' if $data;
1570 $data .= "$k=$smbios1->{$k}";
1575 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1576 sub verify_smbios1
{
1577 my ($value, $noerr) = @_;
1579 return $value if parse_smbios1
($value);
1581 return undef if $noerr;
1583 die "unable to parse smbios (type 1) options\n";
1586 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1587 sub verify_bootdisk
{
1588 my ($value, $noerr) = @_;
1590 return $value if valid_drivename
($value);
1592 return undef if $noerr;
1594 die "invalid boot disk '$value'\n";
1597 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1599 my ($value, $noerr) = @_;
1601 return $value if parse_numa
($value);
1603 return undef if $noerr;
1605 die "unable to parse numa options\n";
1608 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1610 my ($value, $noerr) = @_;
1612 return $value if parse_net
($value);
1614 return undef if $noerr;
1616 die "unable to parse network options\n";
1619 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1621 my ($value, $noerr) = @_;
1623 return $value if parse_drive
(undef, $value);
1625 return undef if $noerr;
1627 die "unable to parse drive options\n";
1630 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1631 sub verify_hostpci
{
1632 my ($value, $noerr) = @_;
1634 return $value if parse_hostpci
($value);
1636 return undef if $noerr;
1638 die "unable to parse pci id\n";
1641 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1642 sub verify_watchdog
{
1643 my ($value, $noerr) = @_;
1645 return $value if parse_watchdog
($value);
1647 return undef if $noerr;
1649 die "unable to parse watchdog options\n";
1652 sub parse_watchdog
{
1655 return undef if !$value;
1659 foreach my $p (split(/,/, $value)) {
1660 next if $p =~ m/^\s*$/;
1662 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1664 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1665 $res->{action
} = $2;
1674 sub parse_usb_device
{
1677 return undef if !$value;
1679 my @dl = split(/,/, $value);
1683 foreach my $v (@dl) {
1684 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1686 $res->{vendorid
} = $2;
1687 $res->{productid
} = $4;
1688 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1690 $res->{hostbus
} = $1;
1691 $res->{hostport
} = $2;
1692 } elsif ($v =~ m/^spice$/) {
1699 return undef if !$found;
1704 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1705 sub verify_usb_device
{
1706 my ($value, $noerr) = @_;
1708 return $value if parse_usb_device
($value);
1710 return undef if $noerr;
1712 die "unable to parse usb device\n";
1715 # add JSON properties for create and set function
1716 sub json_config_properties
{
1719 foreach my $opt (keys %$confdesc) {
1720 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1721 $prop->{$opt} = $confdesc->{$opt};
1728 my ($key, $value) = @_;
1730 die "unknown setting '$key'\n" if !$confdesc->{$key};
1732 my $type = $confdesc->{$key}->{type
};
1734 if (!defined($value)) {
1735 die "got undefined value\n";
1738 if ($value =~ m/[\n\r]/) {
1739 die "property contains a line feed\n";
1742 if ($type eq 'boolean') {
1743 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1744 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1745 die "type check ('boolean') failed - got '$value'\n";
1746 } elsif ($type eq 'integer') {
1747 return int($1) if $value =~ m/^(\d+)$/;
1748 die "type check ('integer') failed - got '$value'\n";
1749 } elsif ($type eq 'number') {
1750 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1751 die "type check ('number') failed - got '$value'\n";
1752 } elsif ($type eq 'string') {
1753 if (my $fmt = $confdesc->{$key}->{format
}) {
1754 if ($fmt eq 'pve-qm-drive') {
1755 # special case - we need to pass $key to parse_drive()
1756 my $drive = parse_drive
($key, $value);
1757 return $value if $drive;
1758 die "unable to parse drive options\n";
1760 PVE
::JSONSchema
::check_format
($fmt, $value);
1763 $value =~ s/^\"(.*)\"$/$1/;
1766 die "internal error"
1770 sub lock_config_full
{
1771 my ($vmid, $timeout, $code, @param) = @_;
1773 my $filename = config_file_lock
($vmid);
1775 my $res = lock_file
($filename, $timeout, $code, @param);
1782 sub lock_config_mode
{
1783 my ($vmid, $timeout, $shared, $code, @param) = @_;
1785 my $filename = config_file_lock
($vmid);
1787 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1795 my ($vmid, $code, @param) = @_;
1797 return lock_config_full
($vmid, 10, $code, @param);
1800 sub cfs_config_path
{
1801 my ($vmid, $node) = @_;
1803 $node = $nodename if !$node;
1804 return "nodes/$node/qemu-server/$vmid.conf";
1807 sub check_iommu_support
{
1808 #fixme : need to check IOMMU support
1809 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1817 my ($vmid, $node) = @_;
1819 my $cfspath = cfs_config_path
($vmid, $node);
1820 return "/etc/pve/$cfspath";
1823 sub config_file_lock
{
1826 return "$lock_dir/lock-$vmid.conf";
1832 my $conf = config_file
($vmid);
1833 utime undef, undef, $conf;
1837 my ($storecfg, $vmid, $keep_empty_config) = @_;
1839 my $conffile = config_file
($vmid);
1841 my $conf = load_config
($vmid);
1845 # only remove disks owned by this VM
1846 foreach_drive
($conf, sub {
1847 my ($ds, $drive) = @_;
1849 return if drive_is_cdrom
($drive);
1851 my $volid = $drive->{file
};
1853 return if !$volid || $volid =~ m
|^/|;
1855 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1856 return if !$path || !$owner || ($owner != $vmid);
1858 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1861 if ($keep_empty_config) {
1862 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1867 # also remove unused disk
1869 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1872 PVE
::Storage
::foreach_volid
($dl, sub {
1873 my ($volid, $sid, $volname, $d) = @_;
1874 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1884 my ($vmid, $node) = @_;
1886 my $cfspath = cfs_config_path
($vmid, $node);
1888 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1890 die "no such VM ('$vmid')\n" if !defined($conf);
1895 sub parse_vm_config
{
1896 my ($filename, $raw) = @_;
1898 return undef if !defined($raw);
1901 digest
=> Digest
::SHA
::sha1_hex
($raw),
1906 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1907 || die "got strange filename '$filename'";
1915 my @lines = split(/\n/, $raw);
1916 foreach my $line (@lines) {
1917 next if $line =~ m/^\s*$/;
1919 if ($line =~ m/^\[PENDING\]\s*$/i) {
1920 $section = 'pending';
1921 if (defined($descr)) {
1923 $conf->{description
} = $descr;
1926 $conf = $res->{$section} = {};
1929 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1931 if (defined($descr)) {
1933 $conf->{description
} = $descr;
1936 $conf = $res->{snapshots
}->{$section} = {};
1940 if ($line =~ m/^\#(.*)\s*$/) {
1941 $descr = '' if !defined($descr);
1942 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1946 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1947 $descr = '' if !defined($descr);
1948 $descr .= PVE
::Tools
::decode_text
($2);
1949 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1950 $conf->{snapstate
} = $1;
1951 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1954 $conf->{$key} = $value;
1955 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1957 if ($section eq 'pending') {
1958 $conf->{delete} = $value; # we parse this later
1960 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1962 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1965 eval { $value = check_type
($key, $value); };
1967 warn "vm $vmid - unable to parse value of '$key' - $@";
1969 my $fmt = $confdesc->{$key}->{format
};
1970 if ($fmt && $fmt eq 'pve-qm-drive') {
1971 my $v = parse_drive
($key, $value);
1972 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1973 $v->{file
} = $volid;
1974 $value = print_drive
($vmid, $v);
1976 warn "vm $vmid - unable to parse value of '$key'\n";
1981 if ($key eq 'cdrom') {
1982 $conf->{ide2
} = $value;
1984 $conf->{$key} = $value;
1990 if (defined($descr)) {
1992 $conf->{description
} = $descr;
1994 delete $res->{snapstate
}; # just to be sure
1999 sub write_vm_config
{
2000 my ($filename, $conf) = @_;
2002 delete $conf->{snapstate
}; # just to be sure
2004 if ($conf->{cdrom
}) {
2005 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2006 $conf->{ide2
} = $conf->{cdrom
};
2007 delete $conf->{cdrom
};
2010 # we do not use 'smp' any longer
2011 if ($conf->{sockets
}) {
2012 delete $conf->{smp
};
2013 } elsif ($conf->{smp
}) {
2014 $conf->{sockets
} = $conf->{smp
};
2015 delete $conf->{cores
};
2016 delete $conf->{smp
};
2019 my $used_volids = {};
2021 my $cleanup_config = sub {
2022 my ($cref, $pending, $snapname) = @_;
2024 foreach my $key (keys %$cref) {
2025 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2026 $key eq 'snapstate' || $key eq 'pending';
2027 my $value = $cref->{$key};
2028 if ($key eq 'delete') {
2029 die "propertry 'delete' is only allowed in [PENDING]\n"
2031 # fixme: check syntax?
2034 eval { $value = check_type
($key, $value); };
2035 die "unable to parse value of '$key' - $@" if $@;
2037 $cref->{$key} = $value;
2039 if (!$snapname && valid_drivename
($key)) {
2040 my $drive = parse_drive
($key, $value);
2041 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2046 &$cleanup_config($conf);
2048 &$cleanup_config($conf->{pending
}, 1);
2050 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2051 die "internal error" if $snapname eq 'pending';
2052 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2055 # remove 'unusedX' settings if we re-add a volume
2056 foreach my $key (keys %$conf) {
2057 my $value = $conf->{$key};
2058 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2059 delete $conf->{$key};
2063 my $generate_raw_config = sub {
2064 my ($conf, $pending) = @_;
2068 # add description as comment to top of file
2069 if (defined(my $descr = $conf->{description
})) {
2071 foreach my $cl (split(/\n/, $descr)) {
2072 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2075 $raw .= "#\n" if $pending;
2079 foreach my $key (sort keys %$conf) {
2080 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2081 $raw .= "$key: $conf->{$key}\n";
2086 my $raw = &$generate_raw_config($conf);
2088 if (scalar(keys %{$conf->{pending
}})){
2089 $raw .= "\n[PENDING]\n";
2090 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2093 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2094 $raw .= "\n[$snapname]\n";
2095 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2101 sub update_config_nolock
{
2102 my ($vmid, $conf, $skiplock) = @_;
2104 check_lock
($conf) if !$skiplock;
2106 my $cfspath = cfs_config_path
($vmid);
2108 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2112 my ($vmid, $conf, $skiplock) = @_;
2114 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2121 # we use static defaults from our JSON schema configuration
2122 foreach my $key (keys %$confdesc) {
2123 if (defined(my $default = $confdesc->{$key}->{default})) {
2124 $res->{$key} = $default;
2128 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2129 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2135 my $vmlist = PVE
::Cluster
::get_vmlist
();
2137 return $res if !$vmlist || !$vmlist->{ids
};
2138 my $ids = $vmlist->{ids
};
2140 foreach my $vmid (keys %$ids) {
2141 my $d = $ids->{$vmid};
2142 next if !$d->{node
} || $d->{node
} ne $nodename;
2143 next if !$d->{type
} || $d->{type
} ne 'qemu';
2144 $res->{$vmid}->{exists} = 1;
2149 # test if VM uses local resources (to prevent migration)
2150 sub check_local_resources
{
2151 my ($conf, $noerr) = @_;
2155 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2156 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2158 foreach my $k (keys %$conf) {
2159 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2160 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2163 die "VM uses local resources\n" if $loc_res && !$noerr;
2168 # check if used storages are available on all nodes (use by migrate)
2169 sub check_storage_availability
{
2170 my ($storecfg, $conf, $node) = @_;
2172 foreach_drive
($conf, sub {
2173 my ($ds, $drive) = @_;
2175 my $volid = $drive->{file
};
2178 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2181 # check if storage is available on both nodes
2182 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2183 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2187 # list nodes where all VM images are available (used by has_feature API)
2189 my ($conf, $storecfg) = @_;
2191 my $nodelist = PVE
::Cluster
::get_nodelist
();
2192 my $nodehash = { map { $_ => 1 } @$nodelist };
2193 my $nodename = PVE
::INotify
::nodename
();
2195 foreach_drive
($conf, sub {
2196 my ($ds, $drive) = @_;
2198 my $volid = $drive->{file
};
2201 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2203 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2204 if ($scfg->{disable
}) {
2206 } elsif (my $avail = $scfg->{nodes
}) {
2207 foreach my $node (keys %$nodehash) {
2208 delete $nodehash->{$node} if !$avail->{$node};
2210 } elsif (!$scfg->{shared
}) {
2211 foreach my $node (keys %$nodehash) {
2212 delete $nodehash->{$node} if $node ne $nodename
2224 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2228 my ($pidfile, $pid) = @_;
2230 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2234 return undef if !$line;
2235 my @param = split(/\0/, $line);
2237 my $cmd = $param[0];
2238 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2240 for (my $i = 0; $i < scalar (@param); $i++) {
2243 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2244 my $p = $param[$i+1];
2245 return 1 if $p && ($p eq $pidfile);
2254 my ($vmid, $nocheck, $node) = @_;
2256 my $filename = config_file
($vmid, $node);
2258 die "unable to find configuration file for VM $vmid - no such machine\n"
2259 if !$nocheck && ! -f
$filename;
2261 my $pidfile = pidfile_name
($vmid);
2263 if (my $fd = IO
::File-
>new("<$pidfile")) {
2268 my $mtime = $st->mtime;
2269 if ($mtime > time()) {
2270 warn "file '$filename' modified in future\n";
2273 if ($line =~ m/^(\d+)$/) {
2275 if (check_cmdline
($pidfile, $pid)) {
2276 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2288 my $vzlist = config_list
();
2290 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2292 while (defined(my $de = $fd->read)) {
2293 next if $de !~ m/^(\d+)\.pid$/;
2295 next if !defined($vzlist->{$vmid});
2296 if (my $pid = check_running
($vmid)) {
2297 $vzlist->{$vmid}->{pid
} = $pid;
2305 my ($storecfg, $conf) = @_;
2307 my $bootdisk = $conf->{bootdisk
};
2308 return undef if !$bootdisk;
2309 return undef if !valid_drivename
($bootdisk);
2311 return undef if !$conf->{$bootdisk};
2313 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2314 return undef if !defined($drive);
2316 return undef if drive_is_cdrom
($drive);
2318 my $volid = $drive->{file
};
2319 return undef if !$volid;
2321 return $drive->{size
};
2324 my $last_proc_pid_stat;
2326 # get VM status information
2327 # This must be fast and should not block ($full == false)
2328 # We only query KVM using QMP if $full == true (this can be slow)
2330 my ($opt_vmid, $full) = @_;
2334 my $storecfg = PVE
::Storage
::config
();
2336 my $list = vzlist
();
2337 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2339 my $cpucount = $cpuinfo->{cpus
} || 1;
2341 foreach my $vmid (keys %$list) {
2342 next if $opt_vmid && ($vmid ne $opt_vmid);
2344 my $cfspath = cfs_config_path
($vmid);
2345 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2348 $d->{pid
} = $list->{$vmid}->{pid
};
2350 # fixme: better status?
2351 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2353 my $size = disksize
($storecfg, $conf);
2354 if (defined($size)) {
2355 $d->{disk
} = 0; # no info available
2356 $d->{maxdisk
} = $size;
2362 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2363 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2364 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2366 $d->{name
} = $conf->{name
} || "VM $vmid";
2367 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2369 if ($conf->{balloon
}) {
2370 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2371 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2382 $d->{diskwrite
} = 0;
2384 $d->{template
} = is_template
($conf);
2389 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2390 foreach my $dev (keys %$netdev) {
2391 next if $dev !~ m/^tap([1-9]\d*)i/;
2393 my $d = $res->{$vmid};
2396 $d->{netout
} += $netdev->{$dev}->{receive
};
2397 $d->{netin
} += $netdev->{$dev}->{transmit
};
2400 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2401 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2406 my $ctime = gettimeofday
;
2408 foreach my $vmid (keys %$list) {
2410 my $d = $res->{$vmid};
2411 my $pid = $d->{pid
};
2414 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2415 next if !$pstat; # not running
2417 my $used = $pstat->{utime} + $pstat->{stime
};
2419 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2421 if ($pstat->{vsize
}) {
2422 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2425 my $old = $last_proc_pid_stat->{$pid};
2427 $last_proc_pid_stat->{$pid} = {
2435 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2437 if ($dtime > 1000) {
2438 my $dutime = $used - $old->{used
};
2440 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2441 $last_proc_pid_stat->{$pid} = {
2447 $d->{cpu
} = $old->{cpu
};
2451 return $res if !$full;
2453 my $qmpclient = PVE
::QMPClient-
>new();
2455 my $ballooncb = sub {
2456 my ($vmid, $resp) = @_;
2458 my $info = $resp->{'return'};
2459 return if !$info->{max_mem
};
2461 my $d = $res->{$vmid};
2463 # use memory assigned to VM
2464 $d->{maxmem
} = $info->{max_mem
};
2465 $d->{balloon
} = $info->{actual
};
2467 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2468 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2469 $d->{freemem
} = $info->{free_mem
};
2472 $d->{ballooninfo
} = $info;
2475 my $blockstatscb = sub {
2476 my ($vmid, $resp) = @_;
2477 my $data = $resp->{'return'} || [];
2478 my $totalrdbytes = 0;
2479 my $totalwrbytes = 0;
2481 for my $blockstat (@$data) {
2482 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2483 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2485 $blockstat->{device
} =~ s/drive-//;
2486 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2488 $res->{$vmid}->{diskread
} = $totalrdbytes;
2489 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2492 my $statuscb = sub {
2493 my ($vmid, $resp) = @_;
2495 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2496 # this fails if ballon driver is not loaded, so this must be
2497 # the last commnand (following command are aborted if this fails).
2498 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2500 my $status = 'unknown';
2501 if (!defined($status = $resp->{'return'}->{status
})) {
2502 warn "unable to get VM status\n";
2506 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2509 foreach my $vmid (keys %$list) {
2510 next if $opt_vmid && ($vmid ne $opt_vmid);
2511 next if !$res->{$vmid}->{pid
}; # not running
2512 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2515 $qmpclient->queue_execute(undef, 1);
2517 foreach my $vmid (keys %$list) {
2518 next if $opt_vmid && ($vmid ne $opt_vmid);
2519 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2526 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2529 my $current_size = 1024;
2530 my $dimm_size = 512;
2531 return if $current_size == $memory;
2533 for (my $j = 0; $j < 8; $j++) {
2534 for (my $i = 0; $i < 32; $i++) {
2535 my $name = "dimm${dimm_id}";
2537 my $numanode = $i % $sockets;
2538 $current_size += $dimm_size;
2539 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2540 return $current_size if $current_size >= $memory;
2546 sub foreach_reverse_dimm
{
2547 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2550 my $current_size = 4177920;
2551 my $dimm_size = 65536;
2552 return if $current_size == $memory;
2554 for (my $j = 0; $j < 8; $j++) {
2555 for (my $i = 0; $i < 32; $i++) {
2556 my $name = "dimm${dimm_id}";
2558 my $numanode = $i % $sockets;
2559 $current_size -= $dimm_size;
2560 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2561 return $current_size if $current_size <= $memory;
2568 my ($conf, $func) = @_;
2570 foreach my $ds (keys %$conf) {
2571 next if !valid_drivename
($ds);
2573 my $drive = parse_drive
($ds, $conf->{$ds});
2576 &$func($ds, $drive);
2581 my ($conf, $func) = @_;
2585 my $test_volid = sub {
2586 my ($volid, $is_cdrom) = @_;
2590 $volhash->{$volid} = $is_cdrom || 0;
2593 foreach_drive
($conf, sub {
2594 my ($ds, $drive) = @_;
2595 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2598 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2599 my $snap = $conf->{snapshots
}->{$snapname};
2600 &$test_volid($snap->{vmstate
}, 0);
2601 foreach_drive
($snap, sub {
2602 my ($ds, $drive) = @_;
2603 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2607 foreach my $volid (keys %$volhash) {
2608 &$func($volid, $volhash->{$volid});
2612 sub vga_conf_has_spice
{
2615 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2620 sub config_to_command
{
2621 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2624 my $globalFlags = [];
2625 my $machineFlags = [];
2631 my $kvmver = kvm_user_version
();
2632 my $vernum = 0; # unknown
2633 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2634 $vernum = $1*1000000+$2*1000;
2635 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2636 $vernum = $1*1000000+$2*1000+$3;
2639 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2641 my $have_ovz = -f
'/proc/vz/vestat';
2643 my $q35 = machine_type_is_q35
($conf);
2644 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2645 my $machine_type = $forcemachine || $conf->{machine
};
2647 my $cpuunits = defined($conf->{cpuunits
}) ?
2648 $conf->{cpuunits
} : $defaults->{cpuunits
};
2650 push @$cmd, '/usr/bin/systemd-run';
2651 push @$cmd, '--scope';
2652 push @$cmd, '--slice', "qemu";
2653 push @$cmd, '--unit', $vmid;
2654 push @$cmd, '-p', "CPUShares=$cpuunits";
2655 if ($conf->{cpulimit
}) {
2656 my $cpulimit = int($conf->{cpulimit
} * 100);
2657 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2661 my $use_old_bios_files = undef;
2663 if ($machine_type && $machine_type =~ m/^(\S+)\.pxe$/){
2665 $use_old_bios_files = 1;
2667 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
2668 # load new efi bios files on migration. So this hack is required to allow
2669 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
2670 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
2671 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
2674 push @$cmd, '/usr/bin/kvm';
2676 push @$cmd, '-id', $vmid;
2680 my $qmpsocket = qmp_socket
($vmid);
2681 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2682 push @$cmd, '-mon', "chardev=qmp,mode=control";
2684 my $socket = vnc_socket
($vmid);
2685 push @$cmd, '-vnc', "unix:$socket,x509,password";
2687 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2689 push @$cmd, '-daemonize';
2691 if ($conf->{smbios1
}) {
2692 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2696 # the q35 chipset support native usb2, so we enable usb controller
2697 # by default for this machine type
2698 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2700 $pciaddr = print_pci_addr
("piix3", $bridges);
2701 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2704 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2705 next if !$conf->{"usb$i"};
2708 # include usb device config
2709 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2712 my $vga = $conf->{vga
};
2714 my $qxlnum = vga_conf_has_spice
($vga);
2715 $vga = 'qxl' if $qxlnum;
2718 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2719 $conf->{ostype
} eq 'win7' ||
2720 $conf->{ostype
} eq 'w2k8')) {
2727 # enable absolute mouse coordinates (needed by vnc)
2729 if (defined($conf->{tablet
})) {
2730 $tablet = $conf->{tablet
};
2732 $tablet = $defaults->{tablet
};
2733 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2734 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2737 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2740 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2741 my $d = parse_hostpci
($conf->{"hostpci$i"});
2744 my $pcie = $d->{pcie
};
2746 die "q35 machine model is not enabled" if !$q35;
2747 $pciaddr = print_pcie_addr
("hostpci$i");
2749 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2752 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2753 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2754 if ($xvga && $xvga ne '') {
2755 push @$cpuFlags, 'kvm=off';
2758 my $pcidevices = $d->{pciid
};
2759 my $multifunction = 1 if @$pcidevices > 1;
2762 foreach my $pcidevice (@$pcidevices) {
2764 my $id = "hostpci$i";
2765 $id .= ".$j" if $multifunction;
2766 my $addr = $pciaddr;
2767 $addr .= ".$j" if $multifunction;
2768 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2771 $devicestr .= "$rombar$xvga";
2772 $devicestr .= ",multifunction=on" if $multifunction;
2775 push @$devices, '-device', $devicestr;
2781 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2782 my $d = parse_usb_device
($conf->{"usb$i"});
2784 if ($d->{vendorid
} && $d->{productid
}) {
2785 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2786 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2787 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2788 } elsif ($d->{spice
}) {
2789 # usb redir support for spice
2790 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2791 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2796 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2797 if (my $path = $conf->{"serial$i"}) {
2798 if ($path eq 'socket') {
2799 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2800 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2801 push @$devices, '-device', "isa-serial,chardev=serial$i";
2803 die "no such serial device\n" if ! -c
$path;
2804 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2805 push @$devices, '-device', "isa-serial,chardev=serial$i";
2811 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2812 if (my $path = $conf->{"parallel$i"}) {
2813 die "no such parallel device\n" if ! -c
$path;
2814 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2815 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2816 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2820 my $vmname = $conf->{name
} || "vm$vmid";
2822 push @$cmd, '-name', $vmname;
2825 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2826 $sockets = $conf->{sockets
} if $conf->{sockets
};
2828 my $cores = $conf->{cores
} || 1;
2830 my $maxcpus = $sockets * $cores;
2832 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2834 my $allowed_vcpus = $cpuinfo->{cpus
};
2836 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2837 if ($allowed_vcpus < $maxcpus);
2839 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2841 push @$cmd, '-nodefaults';
2843 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2845 my $bootindex_hash = {};
2847 foreach my $o (split(//, $bootorder)) {
2848 $bootindex_hash->{$o} = $i*100;
2852 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2854 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2856 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2858 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2861 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2863 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2864 my $useLocaltime = $conf->{localtime};
2866 if (my $ost = $conf->{ostype
}) {
2867 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2869 if ($ost =~ m/^w/) { # windows
2870 $useLocaltime = 1 if !defined($conf->{localtime});
2872 # use time drift fix when acpi is enabled
2873 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2874 $tdf = 1 if !defined($conf->{tdf
});
2878 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2880 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2881 push @$cmd, '-no-hpet';
2882 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2883 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2884 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2885 push @$cpuFlags , 'hv_time' if !$nokvm;
2888 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2892 if ($ost eq 'win7' || $ost eq 'win8') {
2893 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2897 push @$rtcFlags, 'driftfix=slew' if $tdf;
2900 push @$machineFlags, 'accel=tcg';
2902 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2905 if ($machine_type) {
2906 push @$machineFlags, "type=${machine_type}";
2909 if ($conf->{startdate
}) {
2910 push @$rtcFlags, "base=$conf->{startdate}";
2911 } elsif ($useLocaltime) {
2912 push @$rtcFlags, 'base=localtime';
2915 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2916 $cpu = $conf->{cpu
} if $conf->{cpu
};
2918 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2920 push @$cpuFlags , '-x2apic'
2921 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2923 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2925 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2927 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2929 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2930 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2931 push @$cpuFlags , '-kvm_steal_time' if !$nokvm;
2934 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2936 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2938 push @$cmd, '-cpu', $cpu;
2940 my $memory = $conf->{memory
} || $defaults->{memory
};
2941 my $static_memory = 0;
2942 my $dimm_memory = 0;
2944 if ($hotplug_features->{memory
}) {
2945 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2946 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2947 $static_memory = $STATICMEM;
2948 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2949 $dimm_memory = $memory - $static_memory;
2950 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2954 $static_memory = $memory;
2955 push @$cmd, '-m', $static_memory;
2958 if ($conf->{numa
}) {
2960 my $numa_totalmemory = undef;
2961 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2962 next if !$conf->{"numa$i"};
2963 my $numa = parse_numa
($conf->{"numa$i"});
2966 die "missing numa node$i memory value\n" if !$numa->{memory
};
2967 my $numa_memory = $numa->{memory
};
2968 $numa_totalmemory += $numa_memory;
2969 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2972 my $cpus_start = $numa->{cpus
}->{start
};
2973 die "missing numa node$i cpus\n" if !defined($cpus_start);
2974 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2975 my $cpus = $cpus_start;
2976 if (defined($cpus_end)) {
2977 $cpus .= "-$cpus_end";
2978 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2982 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2983 if (defined($hostnodes_start)) {
2984 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2985 my $hostnodes = $hostnodes_start;
2986 if (defined($hostnodes_end)) {
2987 $hostnodes .= "-$hostnodes_end";
2988 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2991 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2992 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2993 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2997 my $policy = $numa->{policy
};
2998 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2999 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3002 push @$cmd, '-object', $numa_object;
3003 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3006 die "total memory for NUMA nodes must be equal to vm static memory\n"
3007 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3009 #if no custom tology, we split memory and cores across numa nodes
3010 if(!$numa_totalmemory) {
3012 my $numa_memory = ($static_memory / $sockets) . "M";
3014 for (my $i = 0; $i < $sockets; $i++) {
3016 my $cpustart = ($cores * $i);
3017 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3018 my $cpus = $cpustart;
3019 $cpus .= "-$cpuend" if $cpuend;
3021 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3022 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3027 if ($hotplug_features->{memory
}) {
3028 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3029 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3030 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3031 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3033 #if dimm_memory is not aligned to dimm map
3034 if($current_size > $memory) {
3035 $conf->{memory
} = $current_size;
3036 update_config_nolock
($vmid, $conf, 1);
3041 push @$cmd, '-S' if $conf->{freeze
};
3043 # set keyboard layout
3044 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3045 push @$cmd, '-k', $kb if $kb;
3048 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3049 #push @$cmd, '-soundhw', 'es1370';
3050 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3052 if($conf->{agent
}) {
3053 my $qgasocket = qmp_socket
($vmid, 1);
3054 my $pciaddr = print_pci_addr
("qga0", $bridges);
3055 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3056 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3057 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3064 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3065 for(my $i = 1; $i < $qxlnum; $i++){
3066 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3067 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3070 # assume other OS works like Linux
3071 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3072 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3076 my $pciaddr = print_pci_addr
("spice", $bridges);
3078 my $nodename = PVE
::INotify
::nodename
();
3079 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3080 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3082 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3084 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3085 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3086 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3089 # enable balloon by default, unless explicitly disabled
3090 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3091 $pciaddr = print_pci_addr
("balloon0", $bridges);
3092 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3095 if ($conf->{watchdog
}) {
3096 my $wdopts = parse_watchdog
($conf->{watchdog
});
3097 $pciaddr = print_pci_addr
("watchdog", $bridges);
3098 my $watchdog = $wdopts->{model
} || 'i6300esb';
3099 push @$devices, '-device', "$watchdog$pciaddr";
3100 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3104 my $scsicontroller = {};
3105 my $ahcicontroller = {};
3106 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3108 # Add iscsi initiator name if available
3109 if (my $initiator = get_initiator_name
()) {
3110 push @$devices, '-iscsi', "initiator-name=$initiator";
3113 foreach_drive
($conf, sub {
3114 my ($ds, $drive) = @_;
3116 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3117 push @$vollist, $drive->{file
};
3120 $use_virtio = 1 if $ds =~ m/^virtio/;
3122 if (drive_is_cdrom
($drive)) {
3123 if ($bootindex_hash->{d
}) {
3124 $drive->{bootindex
} = $bootindex_hash->{d
};
3125 $bootindex_hash->{d
} += 1;
3128 if ($bootindex_hash->{c
}) {
3129 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3130 $bootindex_hash->{c
} += 1;
3134 if($drive->{interface
} eq 'virtio'){
3135 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3138 if ($drive->{interface
} eq 'scsi') {
3140 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3142 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3143 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3146 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3147 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3148 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3152 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3153 $queues = ",num_queues=$drive->{queues}";
3156 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3157 $scsicontroller->{$controller}=1;
3160 if ($drive->{interface
} eq 'sata') {
3161 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3162 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3163 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3164 $ahcicontroller->{$controller}=1;
3167 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3168 push @$devices, '-drive',$drive_cmd;
3169 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3172 for (my $i = 0; $i < $MAX_NETS; $i++) {
3173 next if !$conf->{"net$i"};
3174 my $d = parse_net
($conf->{"net$i"});
3177 $use_virtio = 1 if $d->{model
} eq 'virtio';
3179 if ($bootindex_hash->{n
}) {
3180 $d->{bootindex
} = $bootindex_hash->{n
};
3181 $bootindex_hash->{n
} += 1;
3184 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3185 push @$devices, '-netdev', $netdevfull;
3187 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3188 push @$devices, '-device', $netdevicefull;
3193 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3198 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3200 while (my ($k, $v) = each %$bridges) {
3201 $pciaddr = print_pci_addr
("pci.$k");
3202 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3207 if ($conf->{args
}) {
3208 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3212 push @$cmd, @$devices;
3213 push @$cmd, '-rtc', join(',', @$rtcFlags)
3214 if scalar(@$rtcFlags);
3215 push @$cmd, '-machine', join(',', @$machineFlags)
3216 if scalar(@$machineFlags);
3217 push @$cmd, '-global', join(',', @$globalFlags)
3218 if scalar(@$globalFlags);
3220 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3225 return "${var_run_tmpdir}/$vmid.vnc";
3231 my $res = vm_mon_cmd
($vmid, 'query-spice');
3233 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3237 my ($vmid, $qga) = @_;
3238 my $sockettype = $qga ?
'qga' : 'qmp';
3239 return "${var_run_tmpdir}/$vmid.$sockettype";
3244 return "${var_run_tmpdir}/$vmid.pid";
3247 sub vm_devices_list
{
3250 my $res = vm_mon_cmd
($vmid, 'query-pci');
3252 foreach my $pcibus (@$res) {
3253 foreach my $device (@{$pcibus->{devices
}}) {
3254 next if !$device->{'qdev_id'};
3255 if ($device->{'pci_bridge'}) {
3256 $devices->{$device->{'qdev_id'}} = 1;
3257 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3258 next if !$bridge_device->{'qdev_id'};
3259 $devices->{$bridge_device->{'qdev_id'}} = 1;
3260 $devices->{$device->{'qdev_id'}}++;
3263 $devices->{$device->{'qdev_id'}} = 1;
3268 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3269 foreach my $block (@$resblock) {
3270 if($block->{device
} =~ m/^drive-(\S+)/){
3275 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3276 foreach my $mice (@$resmice) {
3277 if ($mice->{name
} eq 'QEMU HID Tablet') {
3278 $devices->{tablet
} = 1;
3287 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3289 my $q35 = machine_type_is_q35
($conf);
3291 my $devices_list = vm_devices_list
($vmid);
3292 return 1 if defined($devices_list->{$deviceid});
3294 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3296 if ($deviceid eq 'tablet') {
3298 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3300 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3302 qemu_iothread_add
($vmid, $deviceid, $device);
3304 qemu_driveadd
($storecfg, $vmid, $device);
3305 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3307 qemu_deviceadd
($vmid, $devicefull);
3308 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3310 eval { qemu_drivedel
($vmid, $deviceid); };
3315 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3318 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3319 my $pciaddr = print_pci_addr
($deviceid);
3320 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3322 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3324 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3325 qemu_iothread_add
($vmid, $deviceid, $device);
3326 $devicefull .= ",iothread=iothread-$deviceid";
3329 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3330 $devicefull .= ",num_queues=$device->{queues}";
3333 qemu_deviceadd
($vmid, $devicefull);
3334 qemu_deviceaddverify
($vmid, $deviceid);
3336 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3338 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3339 qemu_driveadd
($storecfg, $vmid, $device);
3341 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3342 eval { qemu_deviceadd
($vmid, $devicefull); };
3344 eval { qemu_drivedel
($vmid, $deviceid); };
3349 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3351 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3352 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3353 qemu_deviceadd
($vmid, $netdevicefull);
3354 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3356 eval { qemu_netdevdel
($vmid, $deviceid); };
3361 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3364 my $pciaddr = print_pci_addr
($deviceid);
3365 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3367 qemu_deviceadd
($vmid, $devicefull);
3368 qemu_deviceaddverify
($vmid, $deviceid);
3371 die "can't hotplug device '$deviceid'\n";
3377 # fixme: this should raise exceptions on error!
3378 sub vm_deviceunplug
{
3379 my ($vmid, $conf, $deviceid) = @_;
3381 my $devices_list = vm_devices_list
($vmid);
3382 return 1 if !defined($devices_list->{$deviceid});
3384 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3386 if ($deviceid eq 'tablet') {
3388 qemu_devicedel
($vmid, $deviceid);
3390 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3392 qemu_devicedel
($vmid, $deviceid);
3393 qemu_devicedelverify
($vmid, $deviceid);
3394 qemu_drivedel
($vmid, $deviceid);
3395 qemu_iothread_del
($conf, $vmid, $deviceid);
3397 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3399 qemu_devicedel
($vmid, $deviceid);
3400 qemu_devicedelverify
($vmid, $deviceid);
3401 qemu_iothread_del
($conf, $vmid, $deviceid);
3403 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3405 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3406 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3407 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3409 qemu_devicedel
($vmid, $deviceid);
3410 qemu_drivedel
($vmid, $deviceid);
3411 qemu_deletescsihw
($conf, $vmid, $deviceid);
3413 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3415 qemu_devicedel
($vmid, $deviceid);
3416 qemu_devicedelverify
($vmid, $deviceid);
3417 qemu_netdevdel
($vmid, $deviceid);
3420 die "can't unplug device '$deviceid'\n";
3426 sub qemu_deviceadd
{
3427 my ($vmid, $devicefull) = @_;
3429 $devicefull = "driver=".$devicefull;
3430 my %options = split(/[=,]/, $devicefull);
3432 vm_mon_cmd
($vmid, "device_add" , %options);
3435 sub qemu_devicedel
{
3436 my ($vmid, $deviceid) = @_;
3438 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3441 sub qemu_iothread_add
{
3442 my($vmid, $deviceid, $device) = @_;
3444 if ($device->{iothread
}) {
3445 my $iothreads = vm_iothreads_list
($vmid);
3446 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3450 sub qemu_iothread_del
{
3451 my($conf, $vmid, $deviceid) = @_;
3453 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3454 if ($device->{iothread
}) {
3455 my $iothreads = vm_iothreads_list
($vmid);
3456 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3460 sub qemu_objectadd
{
3461 my($vmid, $objectid, $qomtype) = @_;
3463 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3468 sub qemu_objectdel
{
3469 my($vmid, $objectid) = @_;
3471 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3477 my ($storecfg, $vmid, $device) = @_;
3479 my $drive = print_drive_full
($storecfg, $vmid, $device);
3480 $drive =~ s/\\/\\\\/g;
3481 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3483 # If the command succeeds qemu prints: "OK
"
3484 return 1 if $ret =~ m/OK/s;
3486 die "adding drive failed
: $ret\n";
3490 my($vmid, $deviceid) = @_;
3492 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3495 return 1 if $ret eq "";
3497 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3498 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3500 die "deleting drive
$deviceid failed
: $ret\n";
3503 sub qemu_deviceaddverify {
3504 my ($vmid, $deviceid) = @_;
3506 for (my $i = 0; $i <= 5; $i++) {
3507 my $devices_list = vm_devices_list($vmid);
3508 return 1 if defined($devices_list->{$deviceid});
3512 die "error on hotplug device
'$deviceid'\n";
3516 sub qemu_devicedelverify {
3517 my ($vmid, $deviceid) = @_;
3519 # need to verify that the device is correctly removed as device_del
3520 # is async and empty return is not reliable
3522 for (my $i = 0; $i <= 5; $i++) {
3523 my $devices_list = vm_devices_list($vmid);
3524 return 1 if !defined($devices_list->{$deviceid});
3528 die "error on hot-unplugging device
'$deviceid'\n";
3531 sub qemu_findorcreatescsihw {
3532 my ($storecfg, $conf, $vmid, $device) = @_;
3534 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3536 my $scsihwid="$controller_prefix$controller";
3537 my $devices_list = vm_devices_list($vmid);
3539 if(!defined($devices_list->{$scsihwid})) {
3540 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3546 sub qemu_deletescsihw {
3547 my ($conf, $vmid, $opt) = @_;
3549 my $device = parse_drive($opt, $conf->{$opt});
3551 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3552 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3556 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3558 my $devices_list = vm_devices_list($vmid);
3559 foreach my $opt (keys %{$devices_list}) {
3560 if (PVE::QemuServer::valid_drivename($opt)) {
3561 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3562 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3568 my $scsihwid="scsihw
$controller";
3570 vm_deviceunplug($vmid, $conf, $scsihwid);
3575 sub qemu_add_pci_bridge {
3576 my ($storecfg, $conf, $vmid, $device) = @_;
3582 print_pci_addr($device, $bridges);
3584 while (my ($k, $v) = each %$bridges) {
3587 return 1 if !defined($bridgeid) || $bridgeid < 1;
3589 my $bridge = "pci
.$bridgeid";
3590 my $devices_list = vm_devices_list($vmid);
3592 if (!defined($devices_list->{$bridge})) {
3593 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3599 sub qemu_set_link_status {
3600 my ($vmid, $device, $up) = @_;
3602 vm_mon_cmd($vmid, "set_link
", name => $device,
3603 up => $up ? JSON::true : JSON::false);
3606 sub qemu_netdevadd {
3607 my ($vmid, $conf, $device, $deviceid) = @_;
3609 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3610 my %options = split(/[=,]/, $netdev);
3612 vm_mon_cmd($vmid, "netdev_add
", %options);
3616 sub qemu_netdevdel {
3617 my ($vmid, $deviceid) = @_;
3619 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3622 sub qemu_cpu_hotplug {
3623 my ($vmid, $conf, $vcpus) = @_;
3626 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3627 $sockets = $conf->{sockets} if $conf->{sockets};
3628 my $cores = $conf->{cores} || 1;
3629 my $maxcpus = $sockets * $cores;
3631 $vcpus = $maxcpus if !$vcpus;
3633 die "you can
't add more vcpus than maxcpus\n"
3634 if $vcpus > $maxcpus;
3636 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3637 die "online cpu unplug is not yet possible\n"
3638 if $vcpus < $currentvcpus;
3640 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3641 die "vcpus in running vm is different than configuration\n"
3642 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3644 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3645 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3649 sub qemu_memory_hotplug {
3650 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3652 return $value if !check_running($vmid);
3654 my $memory = $conf->{memory} || $defaults->{memory};
3655 $value = $defaults->{memory} if !$value;
3656 return $value if $value == $memory;
3658 my $static_memory = $STATICMEM;
3659 my $dimm_memory = $memory - $static_memory;
3661 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3662 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3666 $sockets = $conf->{sockets} if $conf->{sockets};
3668 if($value > $memory) {
3670 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3671 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3673 return if $current_size <= $conf->{memory};
3675 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3677 eval { qemu_objectdel($vmid, "mem-
$name"); };
3681 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3683 eval { qemu_objectdel($vmid, "mem-
$name"); };
3686 #update conf after each succesful module hotplug
3687 $conf->{memory} = $current_size;
3688 update_config_nolock($vmid, $conf, 1);
3693 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3694 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3696 return if $current_size >= $conf->{memory};
3697 print "try to unplug memory dimm
$name\n";
3701 eval { qemu_devicedel($vmid, $name) };
3703 my $dimm_list = qemu_dimm_list($vmid);
3704 last if !$dimm_list->{$name};
3705 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3709 #update conf after each succesful module unplug
3710 $conf->{memory} = $current_size;
3712 eval { qemu_objectdel($vmid, "mem-
$name"); };
3713 update_config_nolock($vmid, $conf, 1);
3718 sub qemu_dimm_list {
3721 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3724 foreach my $dimm (@$dimmarray) {
3726 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3727 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3728 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3729 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3730 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3735 sub qemu_block_set_io_throttle {
3736 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3738 return if !check_running($vmid) ;
3740 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));
3744 # old code, only used to shutdown old VM after update
3746 my ($fh, $timeout) = @_;
3748 my $sel = new IO::Select;
3755 while (scalar (@ready = $sel->can_read($timeout))) {
3757 if ($count = $fh->sysread($buf, 8192)) {
3758 if ($buf =~ /^(.*)\(qemu\) $/s) {
3765 if (!defined($count)) {
3772 die "monitor
read timeout
\n" if !scalar(@ready);
3777 # old code, only used to shutdown old VM after update
3778 sub vm_monitor_command {
3779 my ($vmid, $cmdstr, $nocheck) = @_;
3784 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3786 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3788 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3789 die "unable to
connect to VM
$vmid socket - $!\n";
3793 # hack: migrate sometime blocks the monitor (when migrate_downtime
3795 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3796 $timeout = 60*60; # 1 hour
3800 my $data = __read_avail($sock, $timeout);
3802 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3803 die "got unexpected qemu monitor banner
\n";
3806 my $sel = new IO::Select;
3809 if (!scalar(my @ready = $sel->can_write($timeout))) {
3810 die "monitor
write error
- timeout
";
3813 my $fullcmd = "$cmdstr\r";
3815 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3818 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3819 die "monitor
write error
- $!";
3822 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3826 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3827 $timeout = 60*60; # 1 hour
3828 } elsif ($cmdstr =~ m/^(eject|change)/) {
3829 $timeout = 60; # note: cdrom mount command is slow
3831 if ($res = __read_avail($sock, $timeout)) {
3833 my @lines = split("\r?
\n", $res);
3835 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3837 $res = join("\n", @lines);
3845 syslog("err
", "VM
$vmid monitor command failed
- $err");
3852 sub qemu_block_resize {
3853 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3855 my $running = check_running($vmid);
3857 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3859 return if !$running;
3861 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3865 sub qemu_volume_snapshot {
3866 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3868 my $running = check_running($vmid);
3870 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3871 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3873 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3877 sub qemu_volume_snapshot_delete {
3878 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3880 my $running = check_running($vmid);
3882 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3884 return if !$running;
3886 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3889 sub set_migration_caps {
3895 "auto-converge
" => 1,
3897 "x-rdma-pin-all
" => 0,
3902 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3904 for my $supported_capability (@$supported_capabilities) {
3906 capability => $supported_capability->{capability},
3907 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3911 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3914 my $fast_plug_option = {
3923 # hotplug changes in [PENDING]
3924 # $selection hash can be used to only apply specified options, for
3925 # example: { cores => 1 } (only apply changed 'cores')
3926 # $errors ref is used to return error messages
3927 sub vmconfig_hotplug_pending {
3928 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3930 my $defaults = load_defaults();
3932 # commit values which do not have any impact on running VM first
3933 # Note: those option cannot raise errors, we we do not care about
3934 # $selection and always apply them.
3936 my $add_error = sub {
3937 my ($opt, $msg) = @_;
3938 $errors->{$opt} = "hotplug problem
- $msg";
3942 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3943 if ($fast_plug_option->{$opt}) {
3944 $conf->{$opt} = $conf->{pending}->{$opt};
3945 delete $conf->{pending}->{$opt};
3951 update_config_nolock($vmid, $conf, 1);
3952 $conf = load_config($vmid); # update/reload
3955 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3957 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3958 while (my ($opt, $force) = each %$pending_delete_hash) {
3959 next if $selection && !$selection->{$opt};
3961 if ($opt eq 'hotplug') {
3962 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3963 } elsif ($opt eq 'tablet') {
3964 die "skip
\n" if !$hotplug_features->{usb};
3965 if ($defaults->{tablet}) {
3966 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3968 vm_deviceunplug($vmid, $conf, $opt);
3970 } elsif ($opt eq 'vcpus') {
3971 die "skip
\n" if !$hotplug_features->{cpu};
3972 qemu_cpu_hotplug($vmid, $conf, undef);
3973 } elsif ($opt eq 'balloon') {
3974 # enable balloon device is not hotpluggable
3975 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3976 } elsif ($fast_plug_option->{$opt}) {
3978 } elsif ($opt =~ m/^net(\d+)$/) {
3979 die "skip
\n" if !$hotplug_features->{network};
3980 vm_deviceunplug($vmid, $conf, $opt);
3981 } elsif (valid_drivename($opt)) {
3982 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3983 vm_deviceunplug($vmid, $conf, $opt);
3984 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3985 } elsif ($opt =~ m/^memory$/) {
3986 die "skip
\n" if !$hotplug_features->{memory};
3987 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3988 } elsif ($opt eq 'cpuunits') {
3989 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3990 } elsif ($opt eq 'cpulimit') {
3991 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3997 &$add_error($opt, $err) if $err ne "skip
\n";
3999 # save new config if hotplug was successful
4000 delete $conf->{$opt};
4001 vmconfig_undelete_pending_option($conf, $opt);
4002 update_config_nolock($vmid, $conf, 1);
4003 $conf = load_config($vmid); # update/reload
4007 foreach my $opt (keys %{$conf->{pending}}) {
4008 next if $selection && !$selection->{$opt};
4009 my $value = $conf->{pending}->{$opt};
4011 if ($opt eq 'hotplug') {
4012 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4013 } elsif ($opt eq 'tablet') {
4014 die "skip
\n" if !$hotplug_features->{usb};
4016 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4017 } elsif ($value == 0) {
4018 vm_deviceunplug($vmid, $conf, $opt);
4020 } elsif ($opt eq 'vcpus') {
4021 die "skip
\n" if !$hotplug_features->{cpu};
4022 qemu_cpu_hotplug($vmid, $conf, $value);
4023 } elsif ($opt eq 'balloon') {
4024 # enable/disable balloning device is not hotpluggable
4025 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4026 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4027 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4029 # allow manual ballooning if shares is set to zero
4030 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4031 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4032 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4034 } elsif ($opt =~ m/^net(\d+)$/) {
4035 # some changes can be done without hotplug
4036 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4037 $vmid, $opt, $value);
4038 } elsif (valid_drivename($opt)) {
4039 # some changes can be done without hotplug
4040 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4041 $vmid, $opt, $value, 1);
4042 } elsif ($opt =~ m/^memory$/) { #dimms
4043 die "skip
\n" if !$hotplug_features->{memory};
4044 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4045 } elsif ($opt eq 'cpuunits') {
4046 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4047 } elsif ($opt eq 'cpulimit') {
4048 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4049 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4051 die "skip
\n"; # skip non-hot-pluggable options
4055 &$add_error($opt, $err) if $err ne "skip
\n";
4057 # save new config if hotplug was successful
4058 $conf->{$opt} = $value;
4059 delete $conf->{pending}->{$opt};
4060 update_config_nolock($vmid, $conf, 1);
4061 $conf = load_config($vmid); # update/reload
4066 sub try_deallocate_drive {
4067 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4069 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4070 my $volid = $drive->{file};
4071 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4072 my $sid = PVE::Storage::parse_volume_id($volid);
4073 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4075 # check if the disk is really unused
4076 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4077 my $path = PVE::Storage::path($storecfg, $volid);
4078 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4079 if $used_paths->{$path};
4080 PVE::Storage::vdisk_free($storecfg, $volid);
4083 # If vm is not owner of this disk remove from config
4091 sub vmconfig_delete_or_detach_drive {
4092 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4094 my $drive = parse_drive($opt, $conf->{$opt});
4096 my $rpcenv = PVE::RPCEnvironment::get();
4097 my $authuser = $rpcenv->get_user();
4100 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4101 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4103 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4107 sub vmconfig_apply_pending {
4108 my ($vmid, $conf, $storecfg) = @_;
4112 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4113 while (my ($opt, $force) = each %$pending_delete_hash) {
4114 die "internal error
" if $opt =~ m/^unused/;
4115 $conf = load_config($vmid); # update/reload
4116 if (!defined($conf->{$opt})) {
4117 vmconfig_undelete_pending_option($conf, $opt);
4118 update_config_nolock($vmid, $conf, 1);
4119 } elsif (valid_drivename($opt)) {
4120 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4121 vmconfig_undelete_pending_option($conf, $opt);
4122 delete $conf->{$opt};
4123 update_config_nolock($vmid, $conf, 1);
4125 vmconfig_undelete_pending_option($conf, $opt);
4126 delete $conf->{$opt};
4127 update_config_nolock($vmid, $conf, 1);
4131 $conf = load_config($vmid); # update/reload
4133 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4134 $conf = load_config($vmid); # update/reload
4136 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4137 # skip if nothing changed
4138 } elsif (valid_drivename($opt)) {
4139 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4140 if defined($conf->{$opt});
4141 $conf->{$opt} = $conf->{pending}->{$opt};
4143 $conf->{$opt} = $conf->{pending}->{$opt};
4146 delete $conf->{pending}->{$opt};
4147 update_config_nolock($vmid, $conf, 1);
4151 my $safe_num_ne = sub {
4154 return 0 if !defined($a) && !defined($b);
4155 return 1 if !defined($a);
4156 return 1 if !defined($b);
4161 my $safe_string_ne = sub {
4164 return 0 if !defined($a) && !defined($b);
4165 return 1 if !defined($a);
4166 return 1 if !defined($b);
4171 sub vmconfig_update_net {
4172 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4174 my $newnet = parse_net($value);
4176 if ($conf->{$opt}) {
4177 my $oldnet = parse_net($conf->{$opt});
4179 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4180 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4181 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4182 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4184 # for non online change, we try to hot-unplug
4185 die "skip
\n" if !$hotplug;
4186 vm_deviceunplug($vmid, $conf, $opt);
4189 die "internal error
" if $opt !~ m/net(\d+)/;
4190 my $iface = "tap
${vmid
}i
$1";
4192 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4193 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4196 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4197 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4198 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4199 PVE::Network::tap_unplug($iface);
4200 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4203 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4204 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4212 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4218 sub vmconfig_update_disk {
4219 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4221 # fixme: do we need force?
4223 my $drive = parse_drive($opt, $value);
4225 if ($conf->{$opt}) {
4227 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4229 my $media = $drive->{media} || 'disk';
4230 my $oldmedia = $old_drive->{media} || 'disk';
4231 die "unable to change media type
\n" if $media ne $oldmedia;
4233 if (!drive_is_cdrom($old_drive)) {
4235 if ($drive->{file} ne $old_drive->{file}) {
4237 die "skip
\n" if !$hotplug;
4239 # unplug and register as unused
4240 vm_deviceunplug($vmid, $conf, $opt);
4241 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4244 # update existing disk
4246 # skip non hotpluggable value
4247 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4248 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4249 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4250 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4255 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4256 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4257 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4258 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4259 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4260 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4261 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4262 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4263 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4264 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4265 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4266 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4268 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4269 ($drive->{mbps} || 0)*1024*1024,
4270 ($drive->{mbps_rd} || 0)*1024*1024,
4271 ($drive->{mbps_wr} || 0)*1024*1024,
4272 $drive->{iops} || 0,
4273 $drive->{iops_rd} || 0,
4274 $drive->{iops_wr} || 0,
4275 ($drive->{mbps_max} || 0)*1024*1024,
4276 ($drive->{mbps_rd_max} || 0)*1024*1024,
4277 ($drive->{mbps_wr_max} || 0)*1024*1024,
4278 $drive->{iops_max} || 0,
4279 $drive->{iops_rd_max} || 0,
4280 $drive->{iops_wr_max} || 0);
4289 if ($drive->{file} eq 'none') {
4290 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4292 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4293 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4294 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4302 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4304 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4308 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4309 $forcemachine, $spice_ticket) = @_;
4311 lock_config($vmid, sub {
4312 my $conf = load_config($vmid, $migratedfrom);
4314 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4316 check_lock($conf) if !$skiplock;
4318 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4320 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4321 vmconfig_apply_pending($vmid, $conf, $storecfg);
4322 $conf = load_config($vmid); # update/reload
4325 my $defaults = load_defaults();
4327 # set environment variable useful inside network script
4328 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4330 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4332 my $migrate_port = 0;
4335 if ($statefile eq 'tcp') {
4336 my $localip = "localhost
";
4337 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4338 my $nodename = PVE::INotify::nodename();
4339 if ($datacenterconf->{migration_unsecure}) {
4340 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4341 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4343 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4344 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4345 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4346 push @$cmd, '-incoming', $migrate_uri;
4349 push @$cmd, '-loadstate', $statefile;
4356 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4357 my $d = parse_hostpci($conf->{"hostpci
$i"});
4359 my $pcidevices = $d->{pciid};
4360 foreach my $pcidevice (@$pcidevices) {
4361 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4363 my $info = pci_device_info("0000:$pciid");
4364 die "IOMMU
not present
\n" if !check_iommu_support();
4365 die "no pci device info
for device
'$pciid'\n" if !$info;
4366 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4367 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4371 PVE::Storage::activate_volumes($storecfg, $vollist);
4373 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4376 die "start failed
: $err" if $err;
4378 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4380 if ($statefile && $statefile ne 'tcp') {
4381 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4385 if ($migratedfrom) {
4388 set_migration_caps($vmid);
4393 print "spice listens on port
$spice_port\n";
4394 if ($spice_ticket) {
4395 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4396 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4402 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4403 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4404 if $conf->{balloon};
4407 foreach my $opt (keys %$conf) {
4408 next if $opt !~ m/^net\d+$/;
4409 my $nicconf = parse_net($conf->{$opt});
4410 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4414 vm_mon_cmd_nocheck($vmid, 'qom-set',
4415 path => "machine
/peripheral/balloon0
",
4416 property => "guest-stats-polling-interval
",
4417 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4423 my ($vmid, $execute, %params) = @_;
4425 my $cmd = { execute => $execute, arguments => \%params };
4426 vm_qmp_command($vmid, $cmd);
4429 sub vm_mon_cmd_nocheck {
4430 my ($vmid, $execute, %params) = @_;
4432 my $cmd = { execute => $execute, arguments => \%params };
4433 vm_qmp_command($vmid, $cmd, 1);
4436 sub vm_qmp_command {
4437 my ($vmid, $cmd, $nocheck) = @_;
4442 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4443 $timeout = $cmd->{arguments}->{timeout};
4444 delete $cmd->{arguments}->{timeout};
4448 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4449 my $sname = qmp_socket($vmid);
4450 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4451 my $qmpclient = PVE::QMPClient->new();
4453 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4454 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4455 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4456 if scalar(%{$cmd->{arguments}});
4457 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4459 die "unable to open monitor socket\n";
4463 syslog("err", "VM $vmid qmp command failed - $err");
4470 sub vm_human_monitor_command {
4471 my ($vmid, $cmdline) = @_;
4476 execute => 'human-monitor-command
',
4477 arguments => { 'command-line
' => $cmdline},
4480 return vm_qmp_command($vmid, $cmd);
4483 sub vm_commandline {
4484 my ($storecfg, $vmid) = @_;
4486 my $conf = load_config($vmid);
4488 my $defaults = load_defaults();
4490 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4492 return join(' ', @$cmd);
4496 my ($vmid, $skiplock) = @_;
4498 lock_config($vmid, sub {
4500 my $conf = load_config($vmid);
4502 check_lock($conf) if !$skiplock;
4504 vm_mon_cmd($vmid, "system_reset");
4508 sub get_vm_volumes {
4512 foreach_volid($conf, sub {
4513 my ($volid, $is_cdrom) = @_;
4515 return if $volid =~ m|^/|;
4517 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4520 push @$vollist, $volid;
4526 sub vm_stop_cleanup {
4527 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4532 my $vollist = get_vm_volumes($conf);
4533 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4536 foreach my $ext (qw(mon qmp pid vnc qga)) {
4537 unlink "/var/run/qemu-server/${vmid}.$ext";
4540 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4542 warn $@ if $@; # avoid errors - just warn
4545 # Note: use $nockeck to skip tests if VM configuration file exists.
4546 # We need that when migration VMs to other nodes (files already moved)
4547 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4549 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4551 $force = 1 if !defined($force) && !$shutdown;
4554 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4555 kill 15, $pid if $pid;
4556 my $conf = load_config
($vmid, $migratedfrom);
4557 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4561 lock_config
($vmid, sub {
4563 my $pid = check_running
($vmid, $nocheck);
4568 $conf = load_config
($vmid);
4569 check_lock
($conf) if !$skiplock;
4570 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4571 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4572 $timeout = $opts->{down
} if $opts->{down
};
4576 $timeout = 60 if !defined($timeout);
4580 if (defined($conf) && $conf->{agent
}) {
4581 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4583 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4586 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4593 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4598 if ($count >= $timeout) {
4600 warn "VM still running - terminating now with SIGTERM\n";
4603 die "VM quit/powerdown failed - got timeout\n";
4606 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4611 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4614 die "VM quit/powerdown failed\n";
4622 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4627 if ($count >= $timeout) {
4628 warn "VM still running - terminating now with SIGKILL\n";
4633 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4638 my ($vmid, $skiplock) = @_;
4640 lock_config
($vmid, sub {
4642 my $conf = load_config
($vmid);
4644 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4646 vm_mon_cmd
($vmid, "stop");
4651 my ($vmid, $skiplock, $nocheck) = @_;
4653 lock_config
($vmid, sub {
4657 my $conf = load_config
($vmid);
4659 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4661 vm_mon_cmd
($vmid, "cont");
4664 vm_mon_cmd_nocheck
($vmid, "cont");
4670 my ($vmid, $skiplock, $key) = @_;
4672 lock_config
($vmid, sub {
4674 my $conf = load_config
($vmid);
4676 # there is no qmp command, so we use the human monitor command
4677 vm_human_monitor_command
($vmid, "sendkey $key");
4682 my ($storecfg, $vmid, $skiplock) = @_;
4684 lock_config
($vmid, sub {
4686 my $conf = load_config
($vmid);
4688 check_lock
($conf) if !$skiplock;
4690 if (!check_running
($vmid)) {
4691 destroy_vm
($storecfg, $vmid);
4693 die "VM $vmid is running - destroy failed\n";
4701 my ($filename, $buf) = @_;
4703 my $fh = IO
::File-
>new($filename, "w");
4704 return undef if !$fh;
4706 my $res = print $fh $buf;
4713 sub pci_device_info
{
4718 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4719 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4721 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4722 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4724 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4725 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4727 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4728 return undef if !defined($product) || $product !~ s/^0x//;
4733 product
=> $product,
4739 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4748 my $name = $dev->{name
};
4750 my $fn = "$pcisysfs/devices/$name/reset";
4752 return file_write
($fn, "1");
4755 sub pci_dev_bind_to_vfio
{
4758 my $name = $dev->{name
};
4760 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4762 if (!-d
$vfio_basedir) {
4763 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4765 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4767 my $testdir = "$vfio_basedir/$name";
4768 return 1 if -d
$testdir;
4770 my $data = "$dev->{vendor} $dev->{product}";
4771 return undef if !file_write
("$vfio_basedir/new_id", $data);
4773 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4774 if (!file_write
($fn, $name)) {
4775 return undef if -f
$fn;
4778 $fn = "$vfio_basedir/bind";
4779 if (! -d
$testdir) {
4780 return undef if !file_write
($fn, $name);
4786 sub pci_dev_group_bind_to_vfio
{
4789 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4791 if (!-d
$vfio_basedir) {
4792 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4794 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4796 # get IOMMU group devices
4797 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4798 my @devs = grep /^0000:/, readdir($D);
4801 foreach my $pciid (@devs) {
4802 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4804 # pci bridges, switches or root ports are not supported
4805 # they have a pci_bus subdirectory so skip them
4806 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4808 my $info = pci_device_info
($1);
4809 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4815 sub print_pci_addr
{
4816 my ($id, $bridges) = @_;
4820 piix3
=> { bus
=> 0, addr
=> 1 },
4821 #addr2 : first videocard
4822 balloon0
=> { bus
=> 0, addr
=> 3 },
4823 watchdog
=> { bus
=> 0, addr
=> 4 },
4824 scsihw0
=> { bus
=> 0, addr
=> 5 },
4825 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4826 scsihw1
=> { bus
=> 0, addr
=> 6 },
4827 ahci0
=> { bus
=> 0, addr
=> 7 },
4828 qga0
=> { bus
=> 0, addr
=> 8 },
4829 spice
=> { bus
=> 0, addr
=> 9 },
4830 virtio0
=> { bus
=> 0, addr
=> 10 },
4831 virtio1
=> { bus
=> 0, addr
=> 11 },
4832 virtio2
=> { bus
=> 0, addr
=> 12 },
4833 virtio3
=> { bus
=> 0, addr
=> 13 },
4834 virtio4
=> { bus
=> 0, addr
=> 14 },
4835 virtio5
=> { bus
=> 0, addr
=> 15 },
4836 hostpci0
=> { bus
=> 0, addr
=> 16 },
4837 hostpci1
=> { bus
=> 0, addr
=> 17 },
4838 net0
=> { bus
=> 0, addr
=> 18 },
4839 net1
=> { bus
=> 0, addr
=> 19 },
4840 net2
=> { bus
=> 0, addr
=> 20 },
4841 net3
=> { bus
=> 0, addr
=> 21 },
4842 net4
=> { bus
=> 0, addr
=> 22 },
4843 net5
=> { bus
=> 0, addr
=> 23 },
4844 vga1
=> { bus
=> 0, addr
=> 24 },
4845 vga2
=> { bus
=> 0, addr
=> 25 },
4846 vga3
=> { bus
=> 0, addr
=> 26 },
4847 hostpci2
=> { bus
=> 0, addr
=> 27 },
4848 hostpci3
=> { bus
=> 0, addr
=> 28 },
4849 #addr29 : usb-host (pve-usb.cfg)
4850 'pci.1' => { bus
=> 0, addr
=> 30 },
4851 'pci.2' => { bus
=> 0, addr
=> 31 },
4852 'net6' => { bus
=> 1, addr
=> 1 },
4853 'net7' => { bus
=> 1, addr
=> 2 },
4854 'net8' => { bus
=> 1, addr
=> 3 },
4855 'net9' => { bus
=> 1, addr
=> 4 },
4856 'net10' => { bus
=> 1, addr
=> 5 },
4857 'net11' => { bus
=> 1, addr
=> 6 },
4858 'net12' => { bus
=> 1, addr
=> 7 },
4859 'net13' => { bus
=> 1, addr
=> 8 },
4860 'net14' => { bus
=> 1, addr
=> 9 },
4861 'net15' => { bus
=> 1, addr
=> 10 },
4862 'net16' => { bus
=> 1, addr
=> 11 },
4863 'net17' => { bus
=> 1, addr
=> 12 },
4864 'net18' => { bus
=> 1, addr
=> 13 },
4865 'net19' => { bus
=> 1, addr
=> 14 },
4866 'net20' => { bus
=> 1, addr
=> 15 },
4867 'net21' => { bus
=> 1, addr
=> 16 },
4868 'net22' => { bus
=> 1, addr
=> 17 },
4869 'net23' => { bus
=> 1, addr
=> 18 },
4870 'net24' => { bus
=> 1, addr
=> 19 },
4871 'net25' => { bus
=> 1, addr
=> 20 },
4872 'net26' => { bus
=> 1, addr
=> 21 },
4873 'net27' => { bus
=> 1, addr
=> 22 },
4874 'net28' => { bus
=> 1, addr
=> 23 },
4875 'net29' => { bus
=> 1, addr
=> 24 },
4876 'net30' => { bus
=> 1, addr
=> 25 },
4877 'net31' => { bus
=> 1, addr
=> 26 },
4878 'virtio6' => { bus
=> 2, addr
=> 1 },
4879 'virtio7' => { bus
=> 2, addr
=> 2 },
4880 'virtio8' => { bus
=> 2, addr
=> 3 },
4881 'virtio9' => { bus
=> 2, addr
=> 4 },
4882 'virtio10' => { bus
=> 2, addr
=> 5 },
4883 'virtio11' => { bus
=> 2, addr
=> 6 },
4884 'virtio12' => { bus
=> 2, addr
=> 7 },
4885 'virtio13' => { bus
=> 2, addr
=> 8 },
4886 'virtio14' => { bus
=> 2, addr
=> 9 },
4887 'virtio15' => { bus
=> 2, addr
=> 10 },
4888 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4889 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4890 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4891 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4892 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4893 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4894 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4895 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4896 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4897 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4898 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4899 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4900 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4901 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4902 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4903 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4904 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4905 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4906 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4907 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4908 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4909 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4910 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4911 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4912 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4913 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4914 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4915 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4916 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4917 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4918 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4922 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4923 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4924 my $bus = $devices->{$id}->{bus
};
4925 $res = ",bus=pci.$bus,addr=$addr";
4926 $bridges->{$bus} = 1 if $bridges;
4932 sub print_pcie_addr
{
4937 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4938 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4939 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4940 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4943 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4944 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4945 my $bus = $devices->{$id}->{bus
};
4946 $res = ",bus=$bus,addr=$addr";
4952 # vzdump restore implementaion
4954 sub tar_archive_read_firstfile
{
4955 my $archive = shift;
4957 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4959 # try to detect archive type first
4960 my $pid = open (TMP
, "tar tf '$archive'|") ||
4961 die "unable to open file '$archive'\n";
4962 my $firstfile = <TMP
>;
4966 die "ERROR: archive contaions no data\n" if !$firstfile;
4972 sub tar_restore_cleanup
{
4973 my ($storecfg, $statfile) = @_;
4975 print STDERR
"starting cleanup\n";
4977 if (my $fd = IO
::File-
>new($statfile, "r")) {
4978 while (defined(my $line = <$fd>)) {
4979 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4982 if ($volid =~ m
|^/|) {
4983 unlink $volid || die 'unlink failed\n';
4985 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4987 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4989 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4991 print STDERR
"unable to parse line in statfile - $line";
4998 sub restore_archive
{
4999 my ($archive, $vmid, $user, $opts) = @_;
5001 my $format = $opts->{format
};
5004 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5005 $format = 'tar' if !$format;
5007 } elsif ($archive =~ m/\.tar$/) {
5008 $format = 'tar' if !$format;
5009 } elsif ($archive =~ m/.tar.lzo$/) {
5010 $format = 'tar' if !$format;
5012 } elsif ($archive =~ m/\.vma$/) {
5013 $format = 'vma' if !$format;
5014 } elsif ($archive =~ m/\.vma\.gz$/) {
5015 $format = 'vma' if !$format;
5017 } elsif ($archive =~ m/\.vma\.lzo$/) {
5018 $format = 'vma' if !$format;
5021 $format = 'vma' if !$format; # default
5024 # try to detect archive format
5025 if ($format eq 'tar') {
5026 return restore_tar_archive
($archive, $vmid, $user, $opts);
5028 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5032 sub restore_update_config_line
{
5033 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5035 return if $line =~ m/^\#qmdump\#/;
5036 return if $line =~ m/^\#vzdump\#/;
5037 return if $line =~ m/^lock:/;
5038 return if $line =~ m/^unused\d+:/;
5039 return if $line =~ m/^parent:/;
5040 return if $line =~ m/^template:/; # restored VM is never a template
5042 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5043 # try to convert old 1.X settings
5044 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5045 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5046 my ($model, $macaddr) = split(/\=/, $devconfig);
5047 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5050 bridge
=> "vmbr$ind",
5051 macaddr
=> $macaddr,
5053 my $netstr = print_net
($net);
5055 print $outfd "net$cookie->{netcount}: $netstr\n";
5056 $cookie->{netcount
}++;
5058 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5059 my ($id, $netstr) = ($1, $2);
5060 my $net = parse_net
($netstr);
5061 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5062 $netstr = print_net
($net);
5063 print $outfd "$id: $netstr\n";
5064 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5067 if ($line =~ m/backup=no/) {
5068 print $outfd "#$line";
5069 } elsif ($virtdev && $map->{$virtdev}) {
5070 my $di = parse_drive
($virtdev, $value);
5071 delete $di->{format
}; # format can change on restore
5072 $di->{file
} = $map->{$virtdev};
5073 $value = print_drive
($vmid, $di);
5074 print $outfd "$virtdev: $value\n";
5084 my ($cfg, $vmid) = @_;
5086 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5088 my $volid_hash = {};
5089 foreach my $storeid (keys %$info) {
5090 foreach my $item (@{$info->{$storeid}}) {
5091 next if !($item->{volid
} && $item->{size
});
5092 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5093 $volid_hash->{$item->{volid
}} = $item;
5100 sub get_used_paths
{
5101 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5105 my $scan_config = sub {
5106 my ($cref, $snapname) = @_;
5108 foreach my $key (keys %$cref) {
5109 my $value = $cref->{$key};
5110 if (valid_drivename
($key)) {
5111 next if $skip_drive && $key eq $skip_drive;
5112 my $drive = parse_drive
($key, $value);
5113 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5114 if ($drive->{file
} =~ m!^/!) {
5115 $used_path->{$drive->{file
}}++; # = 1;
5117 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5119 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5121 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5122 $used_path->{$path}++; # = 1;
5128 &$scan_config($conf);
5132 if ($scan_snapshots) {
5133 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5134 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5141 sub update_disksize
{
5142 my ($vmid, $conf, $volid_hash) = @_;
5148 # Note: it is allowed to define multiple storages with same path (alias), so
5149 # we need to check both 'volid' and real 'path' (two different volid can point
5150 # to the same path).
5155 foreach my $opt (keys %$conf) {
5156 if (valid_drivename
($opt)) {
5157 my $drive = parse_drive
($opt, $conf->{$opt});
5158 my $volid = $drive->{file
};
5161 $used->{$volid} = 1;
5162 if ($volid_hash->{$volid} &&
5163 (my $path = $volid_hash->{$volid}->{path
})) {
5164 $usedpath->{$path} = 1;
5167 next if drive_is_cdrom
($drive);
5168 next if !$volid_hash->{$volid};
5170 $drive->{size
} = $volid_hash->{$volid}->{size
};
5171 my $new = print_drive
($vmid, $drive);
5172 if ($new ne $conf->{$opt}) {
5174 $conf->{$opt} = $new;
5179 # remove 'unusedX' entry if volume is used
5180 foreach my $opt (keys %$conf) {
5181 next if $opt !~ m/^unused\d+$/;
5182 my $volid = $conf->{$opt};
5183 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5184 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5186 delete $conf->{$opt};
5190 foreach my $volid (sort keys %$volid_hash) {
5191 next if $volid =~ m/vm-$vmid-state-/;
5192 next if $used->{$volid};
5193 my $path = $volid_hash->{$volid}->{path
};
5194 next if !$path; # just to be sure
5195 next if $usedpath->{$path};
5197 add_unused_volume
($conf, $volid);
5198 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5205 my ($vmid, $nolock) = @_;
5207 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5209 my $volid_hash = scan_volids
($cfg, $vmid);
5211 my $updatefn = sub {
5214 my $conf = load_config
($vmid);
5219 foreach my $volid (keys %$volid_hash) {
5220 my $info = $volid_hash->{$volid};
5221 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5224 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5226 update_config_nolock
($vmid, $conf, 1) if $changes;
5229 if (defined($vmid)) {
5233 lock_config
($vmid, $updatefn, $vmid);
5236 my $vmlist = config_list
();
5237 foreach my $vmid (keys %$vmlist) {
5241 lock_config
($vmid, $updatefn, $vmid);
5247 sub restore_vma_archive
{
5248 my ($archive, $vmid, $user, $opts, $comp) = @_;
5250 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5251 my $readfrom = $archive;
5256 my $qarchive = PVE
::Tools
::shellquote
($archive);
5257 if ($comp eq 'gzip') {
5258 $uncomp = "zcat $qarchive|";
5259 } elsif ($comp eq 'lzop') {
5260 $uncomp = "lzop -d -c $qarchive|";
5262 die "unknown compression method '$comp'\n";
5267 my $tmpdir = "/var/tmp/vzdumptmp$$";
5270 # disable interrupts (always do cleanups)
5271 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5272 warn "got interrupt - ignored\n";
5275 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5276 POSIX
::mkfifo
($mapfifo, 0600);
5279 my $openfifo = sub {
5280 open($fifofh, '>', $mapfifo) || die $!;
5283 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5290 my $rpcenv = PVE
::RPCEnvironment
::get
();
5292 my $conffile = config_file
($vmid);
5293 my $tmpfn = "$conffile.$$.tmp";
5295 # Note: $oldconf is undef if VM does not exists
5296 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5298 my $print_devmap = sub {
5299 my $virtdev_hash = {};
5301 my $cfgfn = "$tmpdir/qemu-server.conf";
5303 # we can read the config - that is already extracted
5304 my $fh = IO
::File-
>new($cfgfn, "r") ||
5305 "unable to read qemu-server.conf - $!\n";
5307 while (defined(my $line = <$fh>)) {
5308 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5309 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5310 die "archive does not contain data for drive '$virtdev'\n"
5311 if !$devinfo->{$devname};
5312 if (defined($opts->{storage
})) {
5313 $storeid = $opts->{storage
} || 'local';
5314 } elsif (!$storeid) {
5317 $format = 'raw' if !$format;
5318 $devinfo->{$devname}->{devname
} = $devname;
5319 $devinfo->{$devname}->{virtdev
} = $virtdev;
5320 $devinfo->{$devname}->{format
} = $format;
5321 $devinfo->{$devname}->{storeid
} = $storeid;
5323 # check permission on storage
5324 my $pool = $opts->{pool
}; # todo: do we need that?
5325 if ($user ne 'root@pam') {
5326 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5329 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5333 foreach my $devname (keys %$devinfo) {
5334 die "found no device mapping information for device '$devname'\n"
5335 if !$devinfo->{$devname}->{virtdev
};
5338 my $cfg = cfs_read_file
('storage.cfg');
5340 # create empty/temp config
5342 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5343 foreach_drive
($oldconf, sub {
5344 my ($ds, $drive) = @_;
5346 return if drive_is_cdrom
($drive);
5348 my $volid = $drive->{file
};
5350 return if !$volid || $volid =~ m
|^/|;
5352 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5353 return if !$path || !$owner || ($owner != $vmid);
5355 # Note: only delete disk we want to restore
5356 # other volumes will become unused
5357 if ($virtdev_hash->{$ds}) {
5358 PVE
::Storage
::vdisk_free
($cfg, $volid);
5364 foreach my $virtdev (sort keys %$virtdev_hash) {
5365 my $d = $virtdev_hash->{$virtdev};
5366 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5367 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5369 # test if requested format is supported
5370 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5371 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5372 $d->{format
} = $defFormat if !$supported;
5374 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5375 $d->{format
}, undef, $alloc_size);
5376 print STDERR
"new volume ID is '$volid'\n";
5377 $d->{volid
} = $volid;
5378 my $path = PVE
::Storage
::path
($cfg, $volid);
5380 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5382 my $write_zeros = 1;
5383 # fixme: what other storages types initialize volumes with zero?
5384 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5385 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5389 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5391 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5392 $map->{$virtdev} = $volid;
5395 $fh->seek(0, 0) || die "seek failed - $!\n";
5397 my $outfd = new IO
::File
($tmpfn, "w") ||
5398 die "unable to write config for VM $vmid\n";
5400 my $cookie = { netcount
=> 0 };
5401 while (defined(my $line = <$fh>)) {
5402 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5411 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5412 die "interrupted by signal\n";
5414 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5416 $oldtimeout = alarm($timeout);
5423 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5424 my ($dev_id, $size, $devname) = ($1, $2, $3);
5425 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5426 } elsif ($line =~ m/^CTIME: /) {
5427 # we correctly received the vma config, so we can disable
5428 # the timeout now for disk allocation (set to 10 minutes, so
5429 # that we always timeout if something goes wrong)
5432 print $fifofh "done\n";
5433 my $tmp = $oldtimeout || 0;
5434 $oldtimeout = undef;
5440 print "restore vma archive: $cmd\n";
5441 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5445 alarm($oldtimeout) if $oldtimeout;
5448 foreach my $devname (keys %$devinfo) {
5449 my $volid = $devinfo->{$devname}->{volid
};
5450 push @$vollist, $volid if $volid;
5453 my $cfg = cfs_read_file
('storage.cfg');
5454 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5462 foreach my $devname (keys %$devinfo) {
5463 my $volid = $devinfo->{$devname}->{volid
};
5466 if ($volid =~ m
|^/|) {
5467 unlink $volid || die 'unlink failed\n';
5469 PVE
::Storage
::vdisk_free
($cfg, $volid);
5471 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5473 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5480 rename($tmpfn, $conffile) ||
5481 die "unable to commit configuration file '$conffile'\n";
5483 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5485 eval { rescan
($vmid, 1); };
5489 sub restore_tar_archive
{
5490 my ($archive, $vmid, $user, $opts) = @_;
5492 if ($archive ne '-') {
5493 my $firstfile = tar_archive_read_firstfile
($archive);
5494 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5495 if $firstfile ne 'qemu-server.conf';
5498 my $storecfg = cfs_read_file
('storage.cfg');
5500 # destroy existing data - keep empty config
5501 my $vmcfgfn = config_file
($vmid);
5502 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5504 my $tocmd = "/usr/lib/qemu-server/qmextract";
5506 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5507 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5508 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5509 $tocmd .= ' --info' if $opts->{info
};
5511 # tar option "xf" does not autodetect compression when read from STDIN,
5512 # so we pipe to zcat
5513 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5514 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5516 my $tmpdir = "/var/tmp/vzdumptmp$$";
5519 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5520 local $ENV{VZDUMP_VMID
} = $vmid;
5521 local $ENV{VZDUMP_USER
} = $user;
5523 my $conffile = config_file
($vmid);
5524 my $tmpfn = "$conffile.$$.tmp";
5526 # disable interrupts (always do cleanups)
5527 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5528 print STDERR
"got interrupt - ignored\n";
5533 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5534 die "interrupted by signal\n";
5537 if ($archive eq '-') {
5538 print "extracting archive from STDIN\n";
5539 run_command
($cmd, input
=> "<&STDIN");
5541 print "extracting archive '$archive'\n";
5545 return if $opts->{info
};
5549 my $statfile = "$tmpdir/qmrestore.stat";
5550 if (my $fd = IO
::File-
>new($statfile, "r")) {
5551 while (defined (my $line = <$fd>)) {
5552 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5553 $map->{$1} = $2 if $1;
5555 print STDERR
"unable to parse line in statfile - $line\n";
5561 my $confsrc = "$tmpdir/qemu-server.conf";
5563 my $srcfd = new IO
::File
($confsrc, "r") ||
5564 die "unable to open file '$confsrc'\n";
5566 my $outfd = new IO
::File
($tmpfn, "w") ||
5567 die "unable to write config for VM $vmid\n";
5569 my $cookie = { netcount
=> 0 };
5570 while (defined (my $line = <$srcfd>)) {
5571 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5583 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5590 rename $tmpfn, $conffile ||
5591 die "unable to commit configuration file '$conffile'\n";
5593 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5595 eval { rescan
($vmid, 1); };
5600 # Internal snapshots
5602 # NOTE: Snapshot create/delete involves several non-atomic
5603 # action, and can take a long time.
5604 # So we try to avoid locking the file and use 'lock' variable
5605 # inside the config file instead.
5607 my $snapshot_copy_config = sub {
5608 my ($source, $dest) = @_;
5610 foreach my $k (keys %$source) {
5611 next if $k eq 'snapshots';
5612 next if $k eq 'snapstate';
5613 next if $k eq 'snaptime';
5614 next if $k eq 'vmstate';
5615 next if $k eq 'lock';
5616 next if $k eq 'digest';
5617 next if $k eq 'description';
5618 next if $k =~ m/^unused\d+$/;
5620 $dest->{$k} = $source->{$k};
5624 my $snapshot_apply_config = sub {
5625 my ($conf, $snap) = @_;
5627 # copy snapshot list
5629 snapshots
=> $conf->{snapshots
},
5632 # keep description and list of unused disks
5633 foreach my $k (keys %$conf) {
5634 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5635 $newconf->{$k} = $conf->{$k};
5638 &$snapshot_copy_config($snap, $newconf);
5643 sub foreach_writable_storage
{
5644 my ($conf, $func) = @_;
5648 foreach my $ds (keys %$conf) {
5649 next if !valid_drivename
($ds);
5651 my $drive = parse_drive
($ds, $conf->{$ds});
5653 next if drive_is_cdrom
($drive);
5655 my $volid = $drive->{file
};
5657 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5658 $sidhash->{$sid} = $sid if $sid;
5661 foreach my $sid (sort keys %$sidhash) {
5666 my $alloc_vmstate_volid = sub {
5667 my ($storecfg, $vmid, $conf, $snapname) = @_;
5669 # Note: we try to be smart when selecting a $target storage
5673 # search shared storage first
5674 foreach_writable_storage
($conf, sub {
5676 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5677 return if !$scfg->{shared
};
5679 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5683 # now search local storage
5684 foreach_writable_storage
($conf, sub {
5686 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5687 return if $scfg->{shared
};
5689 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5693 $target = 'local' if !$target;
5695 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5696 # we abort live save after $conf->{memory}, so we need at max twice that space
5697 my $size = $conf->{memory
}*2 + $driver_state_size;
5699 my $name = "vm-$vmid-state-$snapname";
5700 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5701 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5702 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5707 my $snapshot_prepare = sub {
5708 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5712 my $updatefn = sub {
5714 my $conf = load_config
($vmid);
5716 die "you can't take a snapshot if it's a template\n"
5717 if is_template
($conf);
5721 $conf->{lock} = 'snapshot';
5723 die "snapshot name '$snapname' already used\n"
5724 if defined($conf->{snapshots
}->{$snapname});
5726 my $storecfg = PVE
::Storage
::config
();
5727 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5729 $snap = $conf->{snapshots
}->{$snapname} = {};
5731 if ($save_vmstate && check_running
($vmid)) {
5732 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5735 &$snapshot_copy_config($conf, $snap);
5737 $snap->{snapstate
} = "prepare";
5738 $snap->{snaptime
} = time();
5739 $snap->{description
} = $comment if $comment;
5741 # always overwrite machine if we save vmstate. This makes sure we
5742 # can restore it later using correct machine type
5743 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5745 update_config_nolock
($vmid, $conf, 1);
5748 lock_config
($vmid, $updatefn);
5753 my $snapshot_commit = sub {
5754 my ($vmid, $snapname) = @_;
5756 my $updatefn = sub {
5758 my $conf = load_config
($vmid);
5760 die "missing snapshot lock\n"
5761 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5763 my $has_machine_config = defined($conf->{machine
});
5765 my $snap = $conf->{snapshots
}->{$snapname};
5767 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5769 die "wrong snapshot state\n"
5770 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5772 delete $snap->{snapstate
};
5773 delete $conf->{lock};
5775 my $newconf = &$snapshot_apply_config($conf, $snap);
5777 delete $newconf->{machine
} if !$has_machine_config;
5779 $newconf->{parent
} = $snapname;
5781 update_config_nolock
($vmid, $newconf, 1);
5784 lock_config
($vmid, $updatefn);
5787 sub snapshot_rollback
{
5788 my ($vmid, $snapname) = @_;
5792 my $storecfg = PVE
::Storage
::config
();
5794 my $conf = load_config
($vmid);
5796 my $get_snapshot_config = sub {
5798 die "you can't rollback if vm is a template\n" if is_template
($conf);
5800 my $res = $conf->{snapshots
}->{$snapname};
5802 die "snapshot '$snapname' does not exist\n" if !defined($res);
5807 my $snap = &$get_snapshot_config();
5809 foreach_drive
($snap, sub {
5810 my ($ds, $drive) = @_;
5812 return if drive_is_cdrom
($drive);
5814 my $volid = $drive->{file
};
5816 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5819 my $updatefn = sub {
5821 $conf = load_config
($vmid);
5823 $snap = &$get_snapshot_config();
5825 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5826 if $snap->{snapstate
};
5830 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5833 die "unable to rollback vm $vmid: vm is running\n"
5834 if check_running
($vmid);
5837 $conf->{lock} = 'rollback';
5839 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5840 delete $conf->{lock};
5846 my $has_machine_config = defined($conf->{machine
});
5848 # copy snapshot config to current config
5849 $conf = &$snapshot_apply_config($conf, $snap);
5850 $conf->{parent
} = $snapname;
5852 # Note: old code did not store 'machine', so we try to be smart
5853 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5854 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5855 # we remove the 'machine' configuration if not explicitly specified
5856 # in the original config.
5857 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5860 update_config_nolock
($vmid, $conf, 1);
5862 if (!$prepare && $snap->{vmstate
}) {
5863 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5864 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5868 lock_config
($vmid, $updatefn);
5870 foreach_drive
($snap, sub {
5871 my ($ds, $drive) = @_;
5873 return if drive_is_cdrom
($drive);
5875 my $volid = $drive->{file
};
5876 my $device = "drive-$ds";
5878 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5882 lock_config
($vmid, $updatefn);
5885 my $savevm_wait = sub {
5889 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5890 if (!$stat->{status
}) {
5891 die "savevm not active\n";
5892 } elsif ($stat->{status
} eq 'active') {
5895 } elsif ($stat->{status
} eq 'completed') {
5898 die "query-savevm returned status '$stat->{status}'\n";
5903 sub do_snapshots_with_qemu
{
5904 my ($storecfg, $volid) = @_;
5906 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5908 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5909 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5913 if ($volid =~ m/\.(qcow2|qed)$/){
5920 sub snapshot_create
{
5921 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5923 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5925 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5927 my $config = load_config
($vmid);
5929 my $running = check_running
($vmid);
5931 my $freezefs = $running && $config->{agent
};
5932 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5937 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5938 warn "guest-fsfreeze-freeze problems - $@" if $@;
5942 # create internal snapshots of all drives
5944 my $storecfg = PVE
::Storage
::config
();
5947 if ($snap->{vmstate
}) {
5948 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5949 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5950 &$savevm_wait($vmid);
5952 vm_mon_cmd
($vmid, "savevm-start");
5956 foreach_drive
($snap, sub {
5957 my ($ds, $drive) = @_;
5959 return if drive_is_cdrom
($drive);
5961 my $volid = $drive->{file
};
5962 my $device = "drive-$ds";
5964 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5965 $drivehash->{$ds} = 1;
5971 eval { vm_mon_cmd
($vmid, "savevm-end") };
5975 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5976 warn "guest-fsfreeze-thaw problems - $@" if $@;
5979 # savevm-end is async, we need to wait
5981 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5982 if (!$stat->{bytes
}) {
5985 print "savevm not yet finished\n";
5993 warn "snapshot create failed: starting cleanup\n";
5994 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5999 &$snapshot_commit($vmid, $snapname);
6002 # Note: $drivehash is only set when called from snapshot_create.
6003 sub snapshot_delete
{
6004 my ($vmid, $snapname, $force, $drivehash) = @_;
6011 my $unlink_parent = sub {
6012 my ($confref, $new_parent) = @_;
6014 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6016 $confref->{parent
} = $new_parent;
6018 delete $confref->{parent
};
6023 my $updatefn = sub {
6024 my ($remove_drive) = @_;
6026 my $conf = load_config
($vmid);
6030 die "you can't delete a snapshot if vm is a template\n"
6031 if is_template
($conf);
6034 $snap = $conf->{snapshots
}->{$snapname};
6036 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6038 # remove parent refs
6040 &$unlink_parent($conf, $snap->{parent
});
6041 foreach my $sn (keys %{$conf->{snapshots
}}) {
6042 next if $sn eq $snapname;
6043 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6047 if ($remove_drive) {
6048 if ($remove_drive eq 'vmstate') {
6049 delete $snap->{$remove_drive};
6051 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6052 my $volid = $drive->{file
};
6053 delete $snap->{$remove_drive};
6054 add_unused_volume
($conf, $volid);
6059 $snap->{snapstate
} = 'delete';
6061 delete $conf->{snapshots
}->{$snapname};
6062 delete $conf->{lock} if $drivehash;
6063 foreach my $volid (@$unused) {
6064 add_unused_volume
($conf, $volid);
6068 update_config_nolock
($vmid, $conf, 1);
6071 lock_config
($vmid, $updatefn);
6073 # now remove vmstate file
6075 my $storecfg = PVE
::Storage
::config
();
6077 if ($snap->{vmstate
}) {
6078 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6080 die $err if !$force;
6083 # save changes (remove vmstate from snapshot)
6084 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6087 # now remove all internal snapshots
6088 foreach_drive
($snap, sub {
6089 my ($ds, $drive) = @_;
6091 return if drive_is_cdrom
($drive);
6093 my $volid = $drive->{file
};
6094 my $device = "drive-$ds";
6096 if (!$drivehash || $drivehash->{$ds}) {
6097 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6099 die $err if !$force;
6104 # save changes (remove drive fron snapshot)
6105 lock_config
($vmid, $updatefn, $ds) if !$force;
6106 push @$unused, $volid;
6109 # now cleanup config
6111 lock_config
($vmid, $updatefn);
6115 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6118 foreach_drive
($conf, sub {
6119 my ($ds, $drive) = @_;
6121 return if drive_is_cdrom
($drive);
6122 my $volid = $drive->{file
};
6123 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6126 return $err ?
0 : 1;
6129 sub template_create
{
6130 my ($vmid, $conf, $disk) = @_;
6132 my $storecfg = PVE
::Storage
::config
();
6134 foreach_drive
($conf, sub {
6135 my ($ds, $drive) = @_;
6137 return if drive_is_cdrom
($drive);
6138 return if $disk && $ds ne $disk;
6140 my $volid = $drive->{file
};
6141 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6143 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6144 $drive->{file
} = $voliddst;
6145 $conf->{$ds} = print_drive
($vmid, $drive);
6146 update_config_nolock
($vmid, $conf, 1);
6153 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6156 sub qemu_img_convert
{
6157 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6159 my $storecfg = PVE
::Storage
::config
();
6160 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6161 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6163 if ($src_storeid && $dst_storeid) {
6164 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6165 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6167 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6168 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6170 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6171 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6174 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6175 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6176 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6180 if($line =~ m/\((\S+)\/100\
%\)/){
6182 my $transferred = int($size * $percent / 100);
6183 my $remaining = $size - $transferred;
6185 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6190 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6192 die "copy failed: $err" if $err;
6196 sub qemu_img_format
{
6197 my ($scfg, $volname) = @_;
6199 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6206 sub qemu_drive_mirror
{
6207 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6209 my $storecfg = PVE
::Storage
::config
();
6210 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6212 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6214 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6216 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6218 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6219 $opts->{format
} = $format if $format;
6221 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6224 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6226 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6227 my $stat = @$stats[0];
6228 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6229 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6231 my $busy = $stat->{busy
};
6232 my $ready = $stat->{ready
};
6234 if (my $total = $stat->{len
}) {
6235 my $transferred = $stat->{offset
} || 0;
6236 my $remaining = $total - $transferred;
6237 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6239 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6243 if ($stat->{ready
} eq 'true') {
6245 last if $vmiddst != $vmid;
6247 # try to switch the disk if source and destination are on the same guest
6248 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6250 die $@ if $@ !~ m/cannot be completed/;
6259 my $cancel_job = sub {
6260 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6262 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6263 my $stat = @$stats[0];
6270 eval { &$cancel_job(); };
6271 die "mirroring error: $err";
6274 if ($vmiddst != $vmid) {
6275 # if we clone a disk for a new target vm, we don't switch the disk
6276 &$cancel_job(); # so we call block-job-cancel
6281 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6282 $newvmid, $storage, $format, $full, $newvollist) = @_;
6287 print "create linked clone of drive $drivename ($drive->{file})\n";
6288 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6289 push @$newvollist, $newvolid;
6291 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6292 $storeid = $storage if $storage;
6294 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6296 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6297 $format = qemu_img_format
($scfg, $volname);
6300 # test if requested format is supported - else use default
6301 my $supported = grep { $_ eq $format } @$validFormats;
6302 $format = $defFormat if !$supported;
6304 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6306 print "create full clone of drive $drivename ($drive->{file})\n";
6307 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6308 push @$newvollist, $newvolid;
6310 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6312 if (!$running || $snapname) {
6313 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6315 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6319 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6322 $disk->{format
} = undef;
6323 $disk->{file
} = $newvolid;
6324 $disk->{size
} = $size;
6329 # this only works if VM is running
6330 sub get_current_qemu_machine
{
6333 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6334 my $res = vm_qmp_command
($vmid, $cmd);
6336 my ($current, $default);
6337 foreach my $e (@$res) {
6338 $default = $e->{name
} if $e->{'is-default'};
6339 $current = $e->{name
} if $e->{'is-current'};
6342 # fallback to the default machine if current is not supported by qemu
6343 return $current || $default || 'pc';
6346 sub qemu_machine_feature_enabled
{
6347 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6352 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6354 $current_major = $3;
6355 $current_minor = $4;
6357 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6359 $current_major = $1;
6360 $current_minor = $2;
6363 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6372 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6373 my (undef, $id, $function) = @_;
6374 my $res = { id
=> $id, function
=> $function};
6375 push @{$devices->{$id}}, $res;
6381 sub vm_iothreads_list
{
6384 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6387 foreach my $iothread (@$res) {
6388 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6395 my ($conf, $drive) = @_;
6399 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6401 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6407 my $controller = int($drive->{index} / $maxdev);
6408 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6410 return ($maxdev, $controller, $controller_prefix);
6413 # bash completion helper
6415 sub complete_backup_archives
{
6416 my ($cmdname, $pname, $cvalue) = @_;
6418 my $cfg = PVE
::Storage
::config
();
6422 if ($cvalue =~ m/^([^:]+):/) {
6426 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6429 foreach my $id (keys %$data) {
6430 foreach my $item (@{$data->{$id}}) {
6431 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6432 push @$res, $item->{volid
} if defined($item->{volid
});
6439 my $complete_vmid_full = sub {
6442 my $idlist = vmstatus
();
6446 foreach my $id (keys %$idlist) {
6447 my $d = $idlist->{$id};
6448 if (defined($running)) {
6449 next if $d->{template
};
6450 next if $running && $d->{status
} ne 'running';
6451 next if !$running && $d->{status
} eq 'running';
6460 return &$complete_vmid_full();
6463 sub complete_vmid_stopped
{
6464 return &$complete_vmid_full(0);
6467 sub complete_vmid_running
{
6468 return &$complete_vmid_full(1);
6471 sub complete_storage
{
6473 my $cfg = PVE
::Storage
::config
();
6474 my $ids = $cfg->{ids
};
6477 foreach my $sid (keys %$ids) {
6478 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);