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
};
2646 my $use_old_bios_files = undef;
2647 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2649 my $cpuunits = defined($conf->{cpuunits
}) ?
2650 $conf->{cpuunits
} : $defaults->{cpuunits
};
2652 push @$cmd, '/usr/bin/systemd-run';
2653 push @$cmd, '--scope';
2654 push @$cmd, '--slice', "qemu";
2655 push @$cmd, '--unit', $vmid;
2656 push @$cmd, '-p', "CPUShares=$cpuunits";
2657 if ($conf->{cpulimit
}) {
2658 my $cpulimit = int($conf->{cpulimit
} * 100);
2659 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2662 push @$cmd, '/usr/bin/kvm';
2664 push @$cmd, '-id', $vmid;
2668 my $qmpsocket = qmp_socket
($vmid);
2669 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2670 push @$cmd, '-mon', "chardev=qmp,mode=control";
2672 my $socket = vnc_socket
($vmid);
2673 push @$cmd, '-vnc', "unix:$socket,x509,password";
2675 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2677 push @$cmd, '-daemonize';
2679 if ($conf->{smbios1
}) {
2680 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2684 # the q35 chipset support native usb2, so we enable usb controller
2685 # by default for this machine type
2686 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2688 $pciaddr = print_pci_addr
("piix3", $bridges);
2689 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2692 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2693 next if !$conf->{"usb$i"};
2696 # include usb device config
2697 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2700 my $vga = $conf->{vga
};
2702 my $qxlnum = vga_conf_has_spice
($vga);
2703 $vga = 'qxl' if $qxlnum;
2706 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2707 $conf->{ostype
} eq 'win7' ||
2708 $conf->{ostype
} eq 'w2k8')) {
2715 # enable absolute mouse coordinates (needed by vnc)
2717 if (defined($conf->{tablet
})) {
2718 $tablet = $conf->{tablet
};
2720 $tablet = $defaults->{tablet
};
2721 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2722 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2725 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2728 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2729 my $d = parse_hostpci
($conf->{"hostpci$i"});
2732 my $pcie = $d->{pcie
};
2734 die "q35 machine model is not enabled" if !$q35;
2735 $pciaddr = print_pcie_addr
("hostpci$i");
2737 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2740 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2741 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2742 if ($xvga && $xvga ne '') {
2743 push @$cpuFlags, 'kvm=off';
2746 my $pcidevices = $d->{pciid
};
2747 my $multifunction = 1 if @$pcidevices > 1;
2750 foreach my $pcidevice (@$pcidevices) {
2752 my $id = "hostpci$i";
2753 $id .= ".$j" if $multifunction;
2754 my $addr = $pciaddr;
2755 $addr .= ".$j" if $multifunction;
2756 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2759 $devicestr .= "$rombar$xvga";
2760 $devicestr .= ",multifunction=on" if $multifunction;
2763 push @$devices, '-device', $devicestr;
2769 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2770 my $d = parse_usb_device
($conf->{"usb$i"});
2772 if ($d->{vendorid
} && $d->{productid
}) {
2773 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2774 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2775 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2776 } elsif ($d->{spice
}) {
2777 # usb redir support for spice
2778 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2779 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2784 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2785 if (my $path = $conf->{"serial$i"}) {
2786 if ($path eq 'socket') {
2787 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2788 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2789 push @$devices, '-device', "isa-serial,chardev=serial$i";
2791 die "no such serial device\n" if ! -c
$path;
2792 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2793 push @$devices, '-device', "isa-serial,chardev=serial$i";
2799 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2800 if (my $path = $conf->{"parallel$i"}) {
2801 die "no such parallel device\n" if ! -c
$path;
2802 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2803 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2804 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2808 my $vmname = $conf->{name
} || "vm$vmid";
2810 push @$cmd, '-name', $vmname;
2813 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2814 $sockets = $conf->{sockets
} if $conf->{sockets
};
2816 my $cores = $conf->{cores
} || 1;
2818 my $maxcpus = $sockets * $cores;
2820 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2822 my $allowed_vcpus = $cpuinfo->{cpus
};
2824 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2825 if ($allowed_vcpus < $maxcpus);
2827 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2829 push @$cmd, '-nodefaults';
2831 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2833 my $bootindex_hash = {};
2835 foreach my $o (split(//, $bootorder)) {
2836 $bootindex_hash->{$o} = $i*100;
2840 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2842 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2844 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2846 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2849 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2851 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2852 my $useLocaltime = $conf->{localtime};
2854 if (my $ost = $conf->{ostype
}) {
2855 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2857 if ($ost =~ m/^w/) { # windows
2858 $useLocaltime = 1 if !defined($conf->{localtime});
2860 # use time drift fix when acpi is enabled
2861 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2862 $tdf = 1 if !defined($conf->{tdf
});
2866 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2868 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2869 push @$cmd, '-no-hpet';
2870 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2871 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2872 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2873 push @$cpuFlags , 'hv_time' if !$nokvm;
2876 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2880 if ($ost eq 'win7' || $ost eq 'win8') {
2881 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2885 push @$rtcFlags, 'driftfix=slew' if $tdf;
2888 push @$machineFlags, 'accel=tcg';
2890 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2893 if ($machine_type) {
2894 push @$machineFlags, "type=${machine_type}";
2897 if ($conf->{startdate
}) {
2898 push @$rtcFlags, "base=$conf->{startdate}";
2899 } elsif ($useLocaltime) {
2900 push @$rtcFlags, 'base=localtime';
2903 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2904 $cpu = $conf->{cpu
} if $conf->{cpu
};
2906 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2908 push @$cpuFlags , '-x2apic'
2909 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2911 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2913 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2915 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2917 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2918 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2919 push @$cpuFlags , '-kvm_steal_time' if !$nokvm;
2922 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2924 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2926 push @$cmd, '-cpu', $cpu;
2928 my $memory = $conf->{memory
} || $defaults->{memory
};
2929 my $static_memory = 0;
2930 my $dimm_memory = 0;
2932 if ($hotplug_features->{memory
}) {
2933 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2934 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2935 $static_memory = $STATICMEM;
2936 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2937 $dimm_memory = $memory - $static_memory;
2938 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2942 $static_memory = $memory;
2943 push @$cmd, '-m', $static_memory;
2946 if ($conf->{numa
}) {
2948 my $numa_totalmemory = undef;
2949 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2950 next if !$conf->{"numa$i"};
2951 my $numa = parse_numa
($conf->{"numa$i"});
2954 die "missing numa node$i memory value\n" if !$numa->{memory
};
2955 my $numa_memory = $numa->{memory
};
2956 $numa_totalmemory += $numa_memory;
2957 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2960 my $cpus_start = $numa->{cpus
}->{start
};
2961 die "missing numa node$i cpus\n" if !defined($cpus_start);
2962 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2963 my $cpus = $cpus_start;
2964 if (defined($cpus_end)) {
2965 $cpus .= "-$cpus_end";
2966 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2970 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2971 if (defined($hostnodes_start)) {
2972 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2973 my $hostnodes = $hostnodes_start;
2974 if (defined($hostnodes_end)) {
2975 $hostnodes .= "-$hostnodes_end";
2976 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2979 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2980 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2981 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2985 my $policy = $numa->{policy
};
2986 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2987 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2990 push @$cmd, '-object', $numa_object;
2991 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2994 die "total memory for NUMA nodes must be equal to vm static memory\n"
2995 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2997 #if no custom tology, we split memory and cores across numa nodes
2998 if(!$numa_totalmemory) {
3000 my $numa_memory = ($static_memory / $sockets) . "M";
3002 for (my $i = 0; $i < $sockets; $i++) {
3004 my $cpustart = ($cores * $i);
3005 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3006 my $cpus = $cpustart;
3007 $cpus .= "-$cpuend" if $cpuend;
3009 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3010 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3015 if ($hotplug_features->{memory
}) {
3016 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3017 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3018 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3019 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3021 #if dimm_memory is not aligned to dimm map
3022 if($current_size > $memory) {
3023 $conf->{memory
} = $current_size;
3024 update_config_nolock
($vmid, $conf, 1);
3029 push @$cmd, '-S' if $conf->{freeze
};
3031 # set keyboard layout
3032 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3033 push @$cmd, '-k', $kb if $kb;
3036 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3037 #push @$cmd, '-soundhw', 'es1370';
3038 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3040 if($conf->{agent
}) {
3041 my $qgasocket = qmp_socket
($vmid, 1);
3042 my $pciaddr = print_pci_addr
("qga0", $bridges);
3043 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3044 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3045 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3052 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3053 for(my $i = 1; $i < $qxlnum; $i++){
3054 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3055 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3058 # assume other OS works like Linux
3059 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3060 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3064 my $pciaddr = print_pci_addr
("spice", $bridges);
3066 my $nodename = PVE
::INotify
::nodename
();
3067 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3068 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3070 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3072 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3073 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3074 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3077 # enable balloon by default, unless explicitly disabled
3078 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3079 $pciaddr = print_pci_addr
("balloon0", $bridges);
3080 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3083 if ($conf->{watchdog
}) {
3084 my $wdopts = parse_watchdog
($conf->{watchdog
});
3085 $pciaddr = print_pci_addr
("watchdog", $bridges);
3086 my $watchdog = $wdopts->{model
} || 'i6300esb';
3087 push @$devices, '-device', "$watchdog$pciaddr";
3088 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3092 my $scsicontroller = {};
3093 my $ahcicontroller = {};
3094 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3096 # Add iscsi initiator name if available
3097 if (my $initiator = get_initiator_name
()) {
3098 push @$devices, '-iscsi', "initiator-name=$initiator";
3101 foreach_drive
($conf, sub {
3102 my ($ds, $drive) = @_;
3104 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3105 push @$vollist, $drive->{file
};
3108 $use_virtio = 1 if $ds =~ m/^virtio/;
3110 if (drive_is_cdrom
($drive)) {
3111 if ($bootindex_hash->{d
}) {
3112 $drive->{bootindex
} = $bootindex_hash->{d
};
3113 $bootindex_hash->{d
} += 1;
3116 if ($bootindex_hash->{c
}) {
3117 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3118 $bootindex_hash->{c
} += 1;
3122 if($drive->{interface
} eq 'virtio'){
3123 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3126 if ($drive->{interface
} eq 'scsi') {
3128 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3130 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3131 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3134 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3135 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3136 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3140 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3141 $queues = ",num_queues=$drive->{queues}";
3144 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3145 $scsicontroller->{$controller}=1;
3148 if ($drive->{interface
} eq 'sata') {
3149 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3150 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3151 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3152 $ahcicontroller->{$controller}=1;
3155 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3156 push @$devices, '-drive',$drive_cmd;
3157 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3160 for (my $i = 0; $i < $MAX_NETS; $i++) {
3161 next if !$conf->{"net$i"};
3162 my $d = parse_net
($conf->{"net$i"});
3165 $use_virtio = 1 if $d->{model
} eq 'virtio';
3167 if ($bootindex_hash->{n
}) {
3168 $d->{bootindex
} = $bootindex_hash->{n
};
3169 $bootindex_hash->{n
} += 1;
3172 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3173 push @$devices, '-netdev', $netdevfull;
3175 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3176 push @$devices, '-device', $netdevicefull;
3181 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3186 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3188 while (my ($k, $v) = each %$bridges) {
3189 $pciaddr = print_pci_addr
("pci.$k");
3190 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3195 if ($conf->{args
}) {
3196 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3200 push @$cmd, @$devices;
3201 push @$cmd, '-rtc', join(',', @$rtcFlags)
3202 if scalar(@$rtcFlags);
3203 push @$cmd, '-machine', join(',', @$machineFlags)
3204 if scalar(@$machineFlags);
3205 push @$cmd, '-global', join(',', @$globalFlags)
3206 if scalar(@$globalFlags);
3208 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3213 return "${var_run_tmpdir}/$vmid.vnc";
3219 my $res = vm_mon_cmd
($vmid, 'query-spice');
3221 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3225 my ($vmid, $qga) = @_;
3226 my $sockettype = $qga ?
'qga' : 'qmp';
3227 return "${var_run_tmpdir}/$vmid.$sockettype";
3232 return "${var_run_tmpdir}/$vmid.pid";
3235 sub vm_devices_list
{
3238 my $res = vm_mon_cmd
($vmid, 'query-pci');
3240 foreach my $pcibus (@$res) {
3241 foreach my $device (@{$pcibus->{devices
}}) {
3242 next if !$device->{'qdev_id'};
3243 if ($device->{'pci_bridge'}) {
3244 $devices->{$device->{'qdev_id'}} = 1;
3245 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3246 next if !$bridge_device->{'qdev_id'};
3247 $devices->{$bridge_device->{'qdev_id'}} = 1;
3248 $devices->{$device->{'qdev_id'}}++;
3251 $devices->{$device->{'qdev_id'}} = 1;
3256 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3257 foreach my $block (@$resblock) {
3258 if($block->{device
} =~ m/^drive-(\S+)/){
3263 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3264 foreach my $mice (@$resmice) {
3265 if ($mice->{name
} eq 'QEMU HID Tablet') {
3266 $devices->{tablet
} = 1;
3275 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3277 my $q35 = machine_type_is_q35
($conf);
3279 my $devices_list = vm_devices_list
($vmid);
3280 return 1 if defined($devices_list->{$deviceid});
3282 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3284 if ($deviceid eq 'tablet') {
3286 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3288 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3290 qemu_iothread_add
($vmid, $deviceid, $device);
3292 qemu_driveadd
($storecfg, $vmid, $device);
3293 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3295 qemu_deviceadd
($vmid, $devicefull);
3296 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3298 eval { qemu_drivedel
($vmid, $deviceid); };
3303 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3306 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3307 my $pciaddr = print_pci_addr
($deviceid);
3308 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3310 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3312 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3313 qemu_iothread_add
($vmid, $deviceid, $device);
3314 $devicefull .= ",iothread=iothread-$deviceid";
3317 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3318 $devicefull .= ",num_queues=$device->{queues}";
3321 qemu_deviceadd
($vmid, $devicefull);
3322 qemu_deviceaddverify
($vmid, $deviceid);
3324 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3326 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3327 qemu_driveadd
($storecfg, $vmid, $device);
3329 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3330 eval { qemu_deviceadd
($vmid, $devicefull); };
3332 eval { qemu_drivedel
($vmid, $deviceid); };
3337 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3339 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3340 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3341 qemu_deviceadd
($vmid, $netdevicefull);
3342 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3344 eval { qemu_netdevdel
($vmid, $deviceid); };
3349 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3352 my $pciaddr = print_pci_addr
($deviceid);
3353 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3355 qemu_deviceadd
($vmid, $devicefull);
3356 qemu_deviceaddverify
($vmid, $deviceid);
3359 die "can't hotplug device '$deviceid'\n";
3365 # fixme: this should raise exceptions on error!
3366 sub vm_deviceunplug
{
3367 my ($vmid, $conf, $deviceid) = @_;
3369 my $devices_list = vm_devices_list
($vmid);
3370 return 1 if !defined($devices_list->{$deviceid});
3372 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3374 if ($deviceid eq 'tablet') {
3376 qemu_devicedel
($vmid, $deviceid);
3378 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3380 qemu_devicedel
($vmid, $deviceid);
3381 qemu_devicedelverify
($vmid, $deviceid);
3382 qemu_drivedel
($vmid, $deviceid);
3383 qemu_iothread_del
($conf, $vmid, $deviceid);
3385 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3387 qemu_devicedel
($vmid, $deviceid);
3388 qemu_devicedelverify
($vmid, $deviceid);
3389 qemu_iothread_del
($conf, $vmid, $deviceid);
3391 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3393 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3394 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3395 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3397 qemu_devicedel
($vmid, $deviceid);
3398 qemu_drivedel
($vmid, $deviceid);
3399 qemu_deletescsihw
($conf, $vmid, $deviceid);
3401 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3403 qemu_devicedel
($vmid, $deviceid);
3404 qemu_devicedelverify
($vmid, $deviceid);
3405 qemu_netdevdel
($vmid, $deviceid);
3408 die "can't unplug device '$deviceid'\n";
3414 sub qemu_deviceadd
{
3415 my ($vmid, $devicefull) = @_;
3417 $devicefull = "driver=".$devicefull;
3418 my %options = split(/[=,]/, $devicefull);
3420 vm_mon_cmd
($vmid, "device_add" , %options);
3423 sub qemu_devicedel
{
3424 my ($vmid, $deviceid) = @_;
3426 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3429 sub qemu_iothread_add
{
3430 my($vmid, $deviceid, $device) = @_;
3432 if ($device->{iothread
}) {
3433 my $iothreads = vm_iothreads_list
($vmid);
3434 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3438 sub qemu_iothread_del
{
3439 my($conf, $vmid, $deviceid) = @_;
3441 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3442 if ($device->{iothread
}) {
3443 my $iothreads = vm_iothreads_list
($vmid);
3444 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3448 sub qemu_objectadd
{
3449 my($vmid, $objectid, $qomtype) = @_;
3451 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3456 sub qemu_objectdel
{
3457 my($vmid, $objectid) = @_;
3459 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3465 my ($storecfg, $vmid, $device) = @_;
3467 my $drive = print_drive_full
($storecfg, $vmid, $device);
3468 $drive =~ s/\\/\\\\/g;
3469 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3471 # If the command succeeds qemu prints: "OK
"
3472 return 1 if $ret =~ m/OK/s;
3474 die "adding drive failed
: $ret\n";
3478 my($vmid, $deviceid) = @_;
3480 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3483 return 1 if $ret eq "";
3485 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3486 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3488 die "deleting drive
$deviceid failed
: $ret\n";
3491 sub qemu_deviceaddverify {
3492 my ($vmid, $deviceid) = @_;
3494 for (my $i = 0; $i <= 5; $i++) {
3495 my $devices_list = vm_devices_list($vmid);
3496 return 1 if defined($devices_list->{$deviceid});
3500 die "error on hotplug device
'$deviceid'\n";
3504 sub qemu_devicedelverify {
3505 my ($vmid, $deviceid) = @_;
3507 # need to verify that the device is correctly removed as device_del
3508 # is async and empty return is not reliable
3510 for (my $i = 0; $i <= 5; $i++) {
3511 my $devices_list = vm_devices_list($vmid);
3512 return 1 if !defined($devices_list->{$deviceid});
3516 die "error on hot-unplugging device
'$deviceid'\n";
3519 sub qemu_findorcreatescsihw {
3520 my ($storecfg, $conf, $vmid, $device) = @_;
3522 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3524 my $scsihwid="$controller_prefix$controller";
3525 my $devices_list = vm_devices_list($vmid);
3527 if(!defined($devices_list->{$scsihwid})) {
3528 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3534 sub qemu_deletescsihw {
3535 my ($conf, $vmid, $opt) = @_;
3537 my $device = parse_drive($opt, $conf->{$opt});
3539 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3540 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3544 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3546 my $devices_list = vm_devices_list($vmid);
3547 foreach my $opt (keys %{$devices_list}) {
3548 if (PVE::QemuServer::valid_drivename($opt)) {
3549 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3550 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3556 my $scsihwid="scsihw
$controller";
3558 vm_deviceunplug($vmid, $conf, $scsihwid);
3563 sub qemu_add_pci_bridge {
3564 my ($storecfg, $conf, $vmid, $device) = @_;
3570 print_pci_addr($device, $bridges);
3572 while (my ($k, $v) = each %$bridges) {
3575 return 1 if !defined($bridgeid) || $bridgeid < 1;
3577 my $bridge = "pci
.$bridgeid";
3578 my $devices_list = vm_devices_list($vmid);
3580 if (!defined($devices_list->{$bridge})) {
3581 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3587 sub qemu_set_link_status {
3588 my ($vmid, $device, $up) = @_;
3590 vm_mon_cmd($vmid, "set_link
", name => $device,
3591 up => $up ? JSON::true : JSON::false);
3594 sub qemu_netdevadd {
3595 my ($vmid, $conf, $device, $deviceid) = @_;
3597 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3598 my %options = split(/[=,]/, $netdev);
3600 vm_mon_cmd($vmid, "netdev_add
", %options);
3604 sub qemu_netdevdel {
3605 my ($vmid, $deviceid) = @_;
3607 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3610 sub qemu_cpu_hotplug {
3611 my ($vmid, $conf, $vcpus) = @_;
3614 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3615 $sockets = $conf->{sockets} if $conf->{sockets};
3616 my $cores = $conf->{cores} || 1;
3617 my $maxcpus = $sockets * $cores;
3619 $vcpus = $maxcpus if !$vcpus;
3621 die "you can
't add more vcpus than maxcpus\n"
3622 if $vcpus > $maxcpus;
3624 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3625 die "online cpu unplug is not yet possible\n"
3626 if $vcpus < $currentvcpus;
3628 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3629 die "vcpus in running vm is different than configuration\n"
3630 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3632 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3633 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3637 sub qemu_memory_hotplug {
3638 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3640 return $value if !check_running($vmid);
3642 my $memory = $conf->{memory} || $defaults->{memory};
3643 $value = $defaults->{memory} if !$value;
3644 return $value if $value == $memory;
3646 my $static_memory = $STATICMEM;
3647 my $dimm_memory = $memory - $static_memory;
3649 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3650 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3654 $sockets = $conf->{sockets} if $conf->{sockets};
3656 if($value > $memory) {
3658 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3659 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3661 return if $current_size <= $conf->{memory};
3663 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3665 eval { qemu_objectdel($vmid, "mem-
$name"); };
3669 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3671 eval { qemu_objectdel($vmid, "mem-
$name"); };
3674 #update conf after each succesful module hotplug
3675 $conf->{memory} = $current_size;
3676 update_config_nolock($vmid, $conf, 1);
3681 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3682 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3684 return if $current_size >= $conf->{memory};
3685 print "try to unplug memory dimm
$name\n";
3689 eval { qemu_devicedel($vmid, $name) };
3691 my $dimm_list = qemu_dimm_list($vmid);
3692 last if !$dimm_list->{$name};
3693 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3697 #update conf after each succesful module unplug
3698 $conf->{memory} = $current_size;
3700 eval { qemu_objectdel($vmid, "mem-
$name"); };
3701 update_config_nolock($vmid, $conf, 1);
3706 sub qemu_dimm_list {
3709 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3712 foreach my $dimm (@$dimmarray) {
3714 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3715 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3716 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3717 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3718 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3723 sub qemu_block_set_io_throttle {
3724 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3726 return if !check_running($vmid) ;
3728 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));
3732 # old code, only used to shutdown old VM after update
3734 my ($fh, $timeout) = @_;
3736 my $sel = new IO::Select;
3743 while (scalar (@ready = $sel->can_read($timeout))) {
3745 if ($count = $fh->sysread($buf, 8192)) {
3746 if ($buf =~ /^(.*)\(qemu\) $/s) {
3753 if (!defined($count)) {
3760 die "monitor
read timeout
\n" if !scalar(@ready);
3765 # old code, only used to shutdown old VM after update
3766 sub vm_monitor_command {
3767 my ($vmid, $cmdstr, $nocheck) = @_;
3772 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3774 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3776 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3777 die "unable to
connect to VM
$vmid socket - $!\n";
3781 # hack: migrate sometime blocks the monitor (when migrate_downtime
3783 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3784 $timeout = 60*60; # 1 hour
3788 my $data = __read_avail($sock, $timeout);
3790 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3791 die "got unexpected qemu monitor banner
\n";
3794 my $sel = new IO::Select;
3797 if (!scalar(my @ready = $sel->can_write($timeout))) {
3798 die "monitor
write error
- timeout
";
3801 my $fullcmd = "$cmdstr\r";
3803 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3806 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3807 die "monitor
write error
- $!";
3810 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3814 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3815 $timeout = 60*60; # 1 hour
3816 } elsif ($cmdstr =~ m/^(eject|change)/) {
3817 $timeout = 60; # note: cdrom mount command is slow
3819 if ($res = __read_avail($sock, $timeout)) {
3821 my @lines = split("\r?
\n", $res);
3823 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3825 $res = join("\n", @lines);
3833 syslog("err
", "VM
$vmid monitor command failed
- $err");
3840 sub qemu_block_resize {
3841 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3843 my $running = check_running($vmid);
3845 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3847 return if !$running;
3849 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3853 sub qemu_volume_snapshot {
3854 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3856 my $running = check_running($vmid);
3858 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3859 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3861 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3865 sub qemu_volume_snapshot_delete {
3866 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3868 my $running = check_running($vmid);
3870 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3872 return if !$running;
3874 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3877 sub set_migration_caps {
3883 "auto-converge
" => 1,
3885 "x-rdma-pin-all
" => 0,
3890 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3892 for my $supported_capability (@$supported_capabilities) {
3894 capability => $supported_capability->{capability},
3895 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3899 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3902 my $fast_plug_option = {
3911 # hotplug changes in [PENDING]
3912 # $selection hash can be used to only apply specified options, for
3913 # example: { cores => 1 } (only apply changed 'cores')
3914 # $errors ref is used to return error messages
3915 sub vmconfig_hotplug_pending {
3916 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3918 my $defaults = load_defaults();
3920 # commit values which do not have any impact on running VM first
3921 # Note: those option cannot raise errors, we we do not care about
3922 # $selection and always apply them.
3924 my $add_error = sub {
3925 my ($opt, $msg) = @_;
3926 $errors->{$opt} = "hotplug problem
- $msg";
3930 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3931 if ($fast_plug_option->{$opt}) {
3932 $conf->{$opt} = $conf->{pending}->{$opt};
3933 delete $conf->{pending}->{$opt};
3939 update_config_nolock($vmid, $conf, 1);
3940 $conf = load_config($vmid); # update/reload
3943 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3945 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3946 while (my ($opt, $force) = each %$pending_delete_hash) {
3947 next if $selection && !$selection->{$opt};
3949 if ($opt eq 'hotplug') {
3950 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3951 } elsif ($opt eq 'tablet') {
3952 die "skip
\n" if !$hotplug_features->{usb};
3953 if ($defaults->{tablet}) {
3954 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3956 vm_deviceunplug($vmid, $conf, $opt);
3958 } elsif ($opt eq 'vcpus') {
3959 die "skip
\n" if !$hotplug_features->{cpu};
3960 qemu_cpu_hotplug($vmid, $conf, undef);
3961 } elsif ($opt eq 'balloon') {
3962 # enable balloon device is not hotpluggable
3963 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3964 } elsif ($fast_plug_option->{$opt}) {
3966 } elsif ($opt =~ m/^net(\d+)$/) {
3967 die "skip
\n" if !$hotplug_features->{network};
3968 vm_deviceunplug($vmid, $conf, $opt);
3969 } elsif (valid_drivename($opt)) {
3970 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3971 vm_deviceunplug($vmid, $conf, $opt);
3972 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3973 } elsif ($opt =~ m/^memory$/) {
3974 die "skip
\n" if !$hotplug_features->{memory};
3975 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3976 } elsif ($opt eq 'cpuunits') {
3977 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3978 } elsif ($opt eq 'cpulimit') {
3979 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3985 &$add_error($opt, $err) if $err ne "skip
\n";
3987 # save new config if hotplug was successful
3988 delete $conf->{$opt};
3989 vmconfig_undelete_pending_option($conf, $opt);
3990 update_config_nolock($vmid, $conf, 1);
3991 $conf = load_config($vmid); # update/reload
3995 foreach my $opt (keys %{$conf->{pending}}) {
3996 next if $selection && !$selection->{$opt};
3997 my $value = $conf->{pending}->{$opt};
3999 if ($opt eq 'hotplug') {
4000 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4001 } elsif ($opt eq 'tablet') {
4002 die "skip
\n" if !$hotplug_features->{usb};
4004 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4005 } elsif ($value == 0) {
4006 vm_deviceunplug($vmid, $conf, $opt);
4008 } elsif ($opt eq 'vcpus') {
4009 die "skip
\n" if !$hotplug_features->{cpu};
4010 qemu_cpu_hotplug($vmid, $conf, $value);
4011 } elsif ($opt eq 'balloon') {
4012 # enable/disable balloning device is not hotpluggable
4013 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4014 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4015 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4017 # allow manual ballooning if shares is set to zero
4018 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4019 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4020 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4022 } elsif ($opt =~ m/^net(\d+)$/) {
4023 # some changes can be done without hotplug
4024 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4025 $vmid, $opt, $value);
4026 } elsif (valid_drivename($opt)) {
4027 # some changes can be done without hotplug
4028 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4029 $vmid, $opt, $value, 1);
4030 } elsif ($opt =~ m/^memory$/) { #dimms
4031 die "skip
\n" if !$hotplug_features->{memory};
4032 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4033 } elsif ($opt eq 'cpuunits') {
4034 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4035 } elsif ($opt eq 'cpulimit') {
4036 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4037 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4039 die "skip
\n"; # skip non-hot-pluggable options
4043 &$add_error($opt, $err) if $err ne "skip
\n";
4045 # save new config if hotplug was successful
4046 $conf->{$opt} = $value;
4047 delete $conf->{pending}->{$opt};
4048 update_config_nolock($vmid, $conf, 1);
4049 $conf = load_config($vmid); # update/reload
4054 sub try_deallocate_drive {
4055 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4057 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4058 my $volid = $drive->{file};
4059 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4060 my $sid = PVE::Storage::parse_volume_id($volid);
4061 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4063 # check if the disk is really unused
4064 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4065 my $path = PVE::Storage::path($storecfg, $volid);
4066 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4067 if $used_paths->{$path};
4068 PVE::Storage::vdisk_free($storecfg, $volid);
4071 # If vm is not owner of this disk remove from config
4079 sub vmconfig_delete_or_detach_drive {
4080 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4082 my $drive = parse_drive($opt, $conf->{$opt});
4084 my $rpcenv = PVE::RPCEnvironment::get();
4085 my $authuser = $rpcenv->get_user();
4088 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4089 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4091 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4095 sub vmconfig_apply_pending {
4096 my ($vmid, $conf, $storecfg) = @_;
4100 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4101 while (my ($opt, $force) = each %$pending_delete_hash) {
4102 die "internal error
" if $opt =~ m/^unused/;
4103 $conf = load_config($vmid); # update/reload
4104 if (!defined($conf->{$opt})) {
4105 vmconfig_undelete_pending_option($conf, $opt);
4106 update_config_nolock($vmid, $conf, 1);
4107 } elsif (valid_drivename($opt)) {
4108 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4109 vmconfig_undelete_pending_option($conf, $opt);
4110 delete $conf->{$opt};
4111 update_config_nolock($vmid, $conf, 1);
4113 vmconfig_undelete_pending_option($conf, $opt);
4114 delete $conf->{$opt};
4115 update_config_nolock($vmid, $conf, 1);
4119 $conf = load_config($vmid); # update/reload
4121 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4122 $conf = load_config($vmid); # update/reload
4124 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4125 # skip if nothing changed
4126 } elsif (valid_drivename($opt)) {
4127 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4128 if defined($conf->{$opt});
4129 $conf->{$opt} = $conf->{pending}->{$opt};
4131 $conf->{$opt} = $conf->{pending}->{$opt};
4134 delete $conf->{pending}->{$opt};
4135 update_config_nolock($vmid, $conf, 1);
4139 my $safe_num_ne = sub {
4142 return 0 if !defined($a) && !defined($b);
4143 return 1 if !defined($a);
4144 return 1 if !defined($b);
4149 my $safe_string_ne = sub {
4152 return 0 if !defined($a) && !defined($b);
4153 return 1 if !defined($a);
4154 return 1 if !defined($b);
4159 sub vmconfig_update_net {
4160 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4162 my $newnet = parse_net($value);
4164 if ($conf->{$opt}) {
4165 my $oldnet = parse_net($conf->{$opt});
4167 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4168 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4169 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4170 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4172 # for non online change, we try to hot-unplug
4173 die "skip
\n" if !$hotplug;
4174 vm_deviceunplug($vmid, $conf, $opt);
4177 die "internal error
" if $opt !~ m/net(\d+)/;
4178 my $iface = "tap
${vmid
}i
$1";
4180 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4181 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4184 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4185 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4186 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4187 PVE::Network::tap_unplug($iface);
4188 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4191 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4192 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4200 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4206 sub vmconfig_update_disk {
4207 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4209 # fixme: do we need force?
4211 my $drive = parse_drive($opt, $value);
4213 if ($conf->{$opt}) {
4215 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4217 my $media = $drive->{media} || 'disk';
4218 my $oldmedia = $old_drive->{media} || 'disk';
4219 die "unable to change media type
\n" if $media ne $oldmedia;
4221 if (!drive_is_cdrom($old_drive)) {
4223 if ($drive->{file} ne $old_drive->{file}) {
4225 die "skip
\n" if !$hotplug;
4227 # unplug and register as unused
4228 vm_deviceunplug($vmid, $conf, $opt);
4229 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4232 # update existing disk
4234 # skip non hotpluggable value
4235 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4236 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4237 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4238 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4243 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4244 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4245 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4246 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4247 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4248 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4249 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4250 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4251 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4252 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4253 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4254 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4256 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4257 ($drive->{mbps} || 0)*1024*1024,
4258 ($drive->{mbps_rd} || 0)*1024*1024,
4259 ($drive->{mbps_wr} || 0)*1024*1024,
4260 $drive->{iops} || 0,
4261 $drive->{iops_rd} || 0,
4262 $drive->{iops_wr} || 0,
4263 ($drive->{mbps_max} || 0)*1024*1024,
4264 ($drive->{mbps_rd_max} || 0)*1024*1024,
4265 ($drive->{mbps_wr_max} || 0)*1024*1024,
4266 $drive->{iops_max} || 0,
4267 $drive->{iops_rd_max} || 0,
4268 $drive->{iops_wr_max} || 0);
4277 if ($drive->{file} eq 'none') {
4278 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4280 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4281 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4282 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4290 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4292 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4296 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4297 $forcemachine, $spice_ticket) = @_;
4299 lock_config($vmid, sub {
4300 my $conf = load_config($vmid, $migratedfrom);
4302 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4304 check_lock($conf) if !$skiplock;
4306 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4308 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4309 vmconfig_apply_pending($vmid, $conf, $storecfg);
4310 $conf = load_config($vmid); # update/reload
4313 my $defaults = load_defaults();
4315 # set environment variable useful inside network script
4316 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4318 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4320 my $migrate_port = 0;
4323 if ($statefile eq 'tcp') {
4324 my $localip = "localhost
";
4325 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4326 my $nodename = PVE::INotify::nodename();
4327 if ($datacenterconf->{migration_unsecure}) {
4328 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4329 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4331 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4332 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4333 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4334 push @$cmd, '-incoming', $migrate_uri;
4337 push @$cmd, '-loadstate', $statefile;
4344 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4345 my $d = parse_hostpci($conf->{"hostpci
$i"});
4347 my $pcidevices = $d->{pciid};
4348 foreach my $pcidevice (@$pcidevices) {
4349 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4351 my $info = pci_device_info("0000:$pciid");
4352 die "IOMMU
not present
\n" if !check_iommu_support();
4353 die "no pci device info
for device
'$pciid'\n" if !$info;
4354 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4355 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4359 PVE::Storage::activate_volumes($storecfg, $vollist);
4361 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4364 die "start failed
: $err" if $err;
4366 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4368 if ($statefile && $statefile ne 'tcp') {
4369 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4373 if ($migratedfrom) {
4376 set_migration_caps($vmid);
4381 print "spice listens on port
$spice_port\n";
4382 if ($spice_ticket) {
4383 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4384 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4390 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4391 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4392 if $conf->{balloon};
4395 foreach my $opt (keys %$conf) {
4396 next if $opt !~ m/^net\d+$/;
4397 my $nicconf = parse_net($conf->{$opt});
4398 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4402 vm_mon_cmd_nocheck($vmid, 'qom-set',
4403 path => "machine
/peripheral/balloon0
",
4404 property => "guest-stats-polling-interval
",
4405 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4411 my ($vmid, $execute, %params) = @_;
4413 my $cmd = { execute => $execute, arguments => \%params };
4414 vm_qmp_command($vmid, $cmd);
4417 sub vm_mon_cmd_nocheck {
4418 my ($vmid, $execute, %params) = @_;
4420 my $cmd = { execute => $execute, arguments => \%params };
4421 vm_qmp_command($vmid, $cmd, 1);
4424 sub vm_qmp_command {
4425 my ($vmid, $cmd, $nocheck) = @_;
4430 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4431 $timeout = $cmd->{arguments}->{timeout};
4432 delete $cmd->{arguments}->{timeout};
4436 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4437 my $sname = qmp_socket($vmid);
4438 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4439 my $qmpclient = PVE::QMPClient->new();
4441 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4442 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4443 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4444 if scalar(%{$cmd->{arguments}});
4445 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4447 die "unable to open monitor socket\n";
4451 syslog("err", "VM $vmid qmp command failed - $err");
4458 sub vm_human_monitor_command {
4459 my ($vmid, $cmdline) = @_;
4464 execute => 'human-monitor-command
',
4465 arguments => { 'command-line
' => $cmdline},
4468 return vm_qmp_command($vmid, $cmd);
4471 sub vm_commandline {
4472 my ($storecfg, $vmid) = @_;
4474 my $conf = load_config($vmid);
4476 my $defaults = load_defaults();
4478 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4480 return join(' ', @$cmd);
4484 my ($vmid, $skiplock) = @_;
4486 lock_config($vmid, sub {
4488 my $conf = load_config($vmid);
4490 check_lock($conf) if !$skiplock;
4492 vm_mon_cmd($vmid, "system_reset");
4496 sub get_vm_volumes {
4500 foreach_volid($conf, sub {
4501 my ($volid, $is_cdrom) = @_;
4503 return if $volid =~ m|^/|;
4505 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4508 push @$vollist, $volid;
4514 sub vm_stop_cleanup {
4515 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4520 my $vollist = get_vm_volumes($conf);
4521 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4524 foreach my $ext (qw(mon qmp pid vnc qga)) {
4525 unlink "/var/run/qemu-server/${vmid}.$ext";
4528 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4530 warn $@ if $@; # avoid errors - just warn
4533 # Note: use $nockeck to skip tests if VM configuration file exists.
4534 # We need that when migration VMs to other nodes (files already moved)
4535 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4537 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4539 $force = 1 if !defined($force) && !$shutdown;
4542 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4543 kill 15, $pid if $pid;
4544 my $conf = load_config
($vmid, $migratedfrom);
4545 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4549 lock_config
($vmid, sub {
4551 my $pid = check_running
($vmid, $nocheck);
4556 $conf = load_config
($vmid);
4557 check_lock
($conf) if !$skiplock;
4558 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4559 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4560 $timeout = $opts->{down
} if $opts->{down
};
4564 $timeout = 60 if !defined($timeout);
4568 if (defined($conf) && $conf->{agent
}) {
4569 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4571 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4574 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4581 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4586 if ($count >= $timeout) {
4588 warn "VM still running - terminating now with SIGTERM\n";
4591 die "VM quit/powerdown failed - got timeout\n";
4594 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4599 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4602 die "VM quit/powerdown failed\n";
4610 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4615 if ($count >= $timeout) {
4616 warn "VM still running - terminating now with SIGKILL\n";
4621 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4626 my ($vmid, $skiplock) = @_;
4628 lock_config
($vmid, sub {
4630 my $conf = load_config
($vmid);
4632 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4634 vm_mon_cmd
($vmid, "stop");
4639 my ($vmid, $skiplock, $nocheck) = @_;
4641 lock_config
($vmid, sub {
4645 my $conf = load_config
($vmid);
4647 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4649 vm_mon_cmd
($vmid, "cont");
4652 vm_mon_cmd_nocheck
($vmid, "cont");
4658 my ($vmid, $skiplock, $key) = @_;
4660 lock_config
($vmid, sub {
4662 my $conf = load_config
($vmid);
4664 # there is no qmp command, so we use the human monitor command
4665 vm_human_monitor_command
($vmid, "sendkey $key");
4670 my ($storecfg, $vmid, $skiplock) = @_;
4672 lock_config
($vmid, sub {
4674 my $conf = load_config
($vmid);
4676 check_lock
($conf) if !$skiplock;
4678 if (!check_running
($vmid)) {
4679 destroy_vm
($storecfg, $vmid);
4681 die "VM $vmid is running - destroy failed\n";
4689 my ($filename, $buf) = @_;
4691 my $fh = IO
::File-
>new($filename, "w");
4692 return undef if !$fh;
4694 my $res = print $fh $buf;
4701 sub pci_device_info
{
4706 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4707 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4709 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4710 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4712 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4713 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4715 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4716 return undef if !defined($product) || $product !~ s/^0x//;
4721 product
=> $product,
4727 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4736 my $name = $dev->{name
};
4738 my $fn = "$pcisysfs/devices/$name/reset";
4740 return file_write
($fn, "1");
4743 sub pci_dev_bind_to_vfio
{
4746 my $name = $dev->{name
};
4748 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4750 if (!-d
$vfio_basedir) {
4751 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4753 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4755 my $testdir = "$vfio_basedir/$name";
4756 return 1 if -d
$testdir;
4758 my $data = "$dev->{vendor} $dev->{product}";
4759 return undef if !file_write
("$vfio_basedir/new_id", $data);
4761 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4762 if (!file_write
($fn, $name)) {
4763 return undef if -f
$fn;
4766 $fn = "$vfio_basedir/bind";
4767 if (! -d
$testdir) {
4768 return undef if !file_write
($fn, $name);
4774 sub pci_dev_group_bind_to_vfio
{
4777 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4779 if (!-d
$vfio_basedir) {
4780 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4782 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4784 # get IOMMU group devices
4785 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4786 my @devs = grep /^0000:/, readdir($D);
4789 foreach my $pciid (@devs) {
4790 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4792 # pci bridges, switches or root ports are not supported
4793 # they have a pci_bus subdirectory so skip them
4794 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4796 my $info = pci_device_info
($1);
4797 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4803 sub print_pci_addr
{
4804 my ($id, $bridges) = @_;
4808 piix3
=> { bus
=> 0, addr
=> 1 },
4809 #addr2 : first videocard
4810 balloon0
=> { bus
=> 0, addr
=> 3 },
4811 watchdog
=> { bus
=> 0, addr
=> 4 },
4812 scsihw0
=> { bus
=> 0, addr
=> 5 },
4813 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4814 scsihw1
=> { bus
=> 0, addr
=> 6 },
4815 ahci0
=> { bus
=> 0, addr
=> 7 },
4816 qga0
=> { bus
=> 0, addr
=> 8 },
4817 spice
=> { bus
=> 0, addr
=> 9 },
4818 virtio0
=> { bus
=> 0, addr
=> 10 },
4819 virtio1
=> { bus
=> 0, addr
=> 11 },
4820 virtio2
=> { bus
=> 0, addr
=> 12 },
4821 virtio3
=> { bus
=> 0, addr
=> 13 },
4822 virtio4
=> { bus
=> 0, addr
=> 14 },
4823 virtio5
=> { bus
=> 0, addr
=> 15 },
4824 hostpci0
=> { bus
=> 0, addr
=> 16 },
4825 hostpci1
=> { bus
=> 0, addr
=> 17 },
4826 net0
=> { bus
=> 0, addr
=> 18 },
4827 net1
=> { bus
=> 0, addr
=> 19 },
4828 net2
=> { bus
=> 0, addr
=> 20 },
4829 net3
=> { bus
=> 0, addr
=> 21 },
4830 net4
=> { bus
=> 0, addr
=> 22 },
4831 net5
=> { bus
=> 0, addr
=> 23 },
4832 vga1
=> { bus
=> 0, addr
=> 24 },
4833 vga2
=> { bus
=> 0, addr
=> 25 },
4834 vga3
=> { bus
=> 0, addr
=> 26 },
4835 hostpci2
=> { bus
=> 0, addr
=> 27 },
4836 hostpci3
=> { bus
=> 0, addr
=> 28 },
4837 #addr29 : usb-host (pve-usb.cfg)
4838 'pci.1' => { bus
=> 0, addr
=> 30 },
4839 'pci.2' => { bus
=> 0, addr
=> 31 },
4840 'net6' => { bus
=> 1, addr
=> 1 },
4841 'net7' => { bus
=> 1, addr
=> 2 },
4842 'net8' => { bus
=> 1, addr
=> 3 },
4843 'net9' => { bus
=> 1, addr
=> 4 },
4844 'net10' => { bus
=> 1, addr
=> 5 },
4845 'net11' => { bus
=> 1, addr
=> 6 },
4846 'net12' => { bus
=> 1, addr
=> 7 },
4847 'net13' => { bus
=> 1, addr
=> 8 },
4848 'net14' => { bus
=> 1, addr
=> 9 },
4849 'net15' => { bus
=> 1, addr
=> 10 },
4850 'net16' => { bus
=> 1, addr
=> 11 },
4851 'net17' => { bus
=> 1, addr
=> 12 },
4852 'net18' => { bus
=> 1, addr
=> 13 },
4853 'net19' => { bus
=> 1, addr
=> 14 },
4854 'net20' => { bus
=> 1, addr
=> 15 },
4855 'net21' => { bus
=> 1, addr
=> 16 },
4856 'net22' => { bus
=> 1, addr
=> 17 },
4857 'net23' => { bus
=> 1, addr
=> 18 },
4858 'net24' => { bus
=> 1, addr
=> 19 },
4859 'net25' => { bus
=> 1, addr
=> 20 },
4860 'net26' => { bus
=> 1, addr
=> 21 },
4861 'net27' => { bus
=> 1, addr
=> 22 },
4862 'net28' => { bus
=> 1, addr
=> 23 },
4863 'net29' => { bus
=> 1, addr
=> 24 },
4864 'net30' => { bus
=> 1, addr
=> 25 },
4865 'net31' => { bus
=> 1, addr
=> 26 },
4866 'virtio6' => { bus
=> 2, addr
=> 1 },
4867 'virtio7' => { bus
=> 2, addr
=> 2 },
4868 'virtio8' => { bus
=> 2, addr
=> 3 },
4869 'virtio9' => { bus
=> 2, addr
=> 4 },
4870 'virtio10' => { bus
=> 2, addr
=> 5 },
4871 'virtio11' => { bus
=> 2, addr
=> 6 },
4872 'virtio12' => { bus
=> 2, addr
=> 7 },
4873 'virtio13' => { bus
=> 2, addr
=> 8 },
4874 'virtio14' => { bus
=> 2, addr
=> 9 },
4875 'virtio15' => { bus
=> 2, addr
=> 10 },
4876 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4877 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4878 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4879 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4880 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4881 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4882 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4883 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4884 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4885 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4886 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4887 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4888 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4889 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4890 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4891 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4892 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4893 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4894 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4895 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4896 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4897 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4898 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4899 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4900 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4901 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4902 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4903 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4904 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4905 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4906 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4910 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4911 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4912 my $bus = $devices->{$id}->{bus
};
4913 $res = ",bus=pci.$bus,addr=$addr";
4914 $bridges->{$bus} = 1 if $bridges;
4920 sub print_pcie_addr
{
4925 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4926 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4927 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4928 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4931 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4932 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4933 my $bus = $devices->{$id}->{bus
};
4934 $res = ",bus=$bus,addr=$addr";
4940 # vzdump restore implementaion
4942 sub tar_archive_read_firstfile
{
4943 my $archive = shift;
4945 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4947 # try to detect archive type first
4948 my $pid = open (TMP
, "tar tf '$archive'|") ||
4949 die "unable to open file '$archive'\n";
4950 my $firstfile = <TMP
>;
4954 die "ERROR: archive contaions no data\n" if !$firstfile;
4960 sub tar_restore_cleanup
{
4961 my ($storecfg, $statfile) = @_;
4963 print STDERR
"starting cleanup\n";
4965 if (my $fd = IO
::File-
>new($statfile, "r")) {
4966 while (defined(my $line = <$fd>)) {
4967 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4970 if ($volid =~ m
|^/|) {
4971 unlink $volid || die 'unlink failed\n';
4973 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4975 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4977 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4979 print STDERR
"unable to parse line in statfile - $line";
4986 sub restore_archive
{
4987 my ($archive, $vmid, $user, $opts) = @_;
4989 my $format = $opts->{format
};
4992 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4993 $format = 'tar' if !$format;
4995 } elsif ($archive =~ m/\.tar$/) {
4996 $format = 'tar' if !$format;
4997 } elsif ($archive =~ m/.tar.lzo$/) {
4998 $format = 'tar' if !$format;
5000 } elsif ($archive =~ m/\.vma$/) {
5001 $format = 'vma' if !$format;
5002 } elsif ($archive =~ m/\.vma\.gz$/) {
5003 $format = 'vma' if !$format;
5005 } elsif ($archive =~ m/\.vma\.lzo$/) {
5006 $format = 'vma' if !$format;
5009 $format = 'vma' if !$format; # default
5012 # try to detect archive format
5013 if ($format eq 'tar') {
5014 return restore_tar_archive
($archive, $vmid, $user, $opts);
5016 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5020 sub restore_update_config_line
{
5021 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5023 return if $line =~ m/^\#qmdump\#/;
5024 return if $line =~ m/^\#vzdump\#/;
5025 return if $line =~ m/^lock:/;
5026 return if $line =~ m/^unused\d+:/;
5027 return if $line =~ m/^parent:/;
5028 return if $line =~ m/^template:/; # restored VM is never a template
5030 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5031 # try to convert old 1.X settings
5032 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5033 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5034 my ($model, $macaddr) = split(/\=/, $devconfig);
5035 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5038 bridge
=> "vmbr$ind",
5039 macaddr
=> $macaddr,
5041 my $netstr = print_net
($net);
5043 print $outfd "net$cookie->{netcount}: $netstr\n";
5044 $cookie->{netcount
}++;
5046 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5047 my ($id, $netstr) = ($1, $2);
5048 my $net = parse_net
($netstr);
5049 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5050 $netstr = print_net
($net);
5051 print $outfd "$id: $netstr\n";
5052 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5055 if ($line =~ m/backup=no/) {
5056 print $outfd "#$line";
5057 } elsif ($virtdev && $map->{$virtdev}) {
5058 my $di = parse_drive
($virtdev, $value);
5059 delete $di->{format
}; # format can change on restore
5060 $di->{file
} = $map->{$virtdev};
5061 $value = print_drive
($vmid, $di);
5062 print $outfd "$virtdev: $value\n";
5072 my ($cfg, $vmid) = @_;
5074 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5076 my $volid_hash = {};
5077 foreach my $storeid (keys %$info) {
5078 foreach my $item (@{$info->{$storeid}}) {
5079 next if !($item->{volid
} && $item->{size
});
5080 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5081 $volid_hash->{$item->{volid
}} = $item;
5088 sub get_used_paths
{
5089 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5093 my $scan_config = sub {
5094 my ($cref, $snapname) = @_;
5096 foreach my $key (keys %$cref) {
5097 my $value = $cref->{$key};
5098 if (valid_drivename
($key)) {
5099 next if $skip_drive && $key eq $skip_drive;
5100 my $drive = parse_drive
($key, $value);
5101 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5102 if ($drive->{file
} =~ m!^/!) {
5103 $used_path->{$drive->{file
}}++; # = 1;
5105 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5107 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5109 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5110 $used_path->{$path}++; # = 1;
5116 &$scan_config($conf);
5120 if ($scan_snapshots) {
5121 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5122 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5129 sub update_disksize
{
5130 my ($vmid, $conf, $volid_hash) = @_;
5136 # Note: it is allowed to define multiple storages with same path (alias), so
5137 # we need to check both 'volid' and real 'path' (two different volid can point
5138 # to the same path).
5143 foreach my $opt (keys %$conf) {
5144 if (valid_drivename
($opt)) {
5145 my $drive = parse_drive
($opt, $conf->{$opt});
5146 my $volid = $drive->{file
};
5149 $used->{$volid} = 1;
5150 if ($volid_hash->{$volid} &&
5151 (my $path = $volid_hash->{$volid}->{path
})) {
5152 $usedpath->{$path} = 1;
5155 next if drive_is_cdrom
($drive);
5156 next if !$volid_hash->{$volid};
5158 $drive->{size
} = $volid_hash->{$volid}->{size
};
5159 my $new = print_drive
($vmid, $drive);
5160 if ($new ne $conf->{$opt}) {
5162 $conf->{$opt} = $new;
5167 # remove 'unusedX' entry if volume is used
5168 foreach my $opt (keys %$conf) {
5169 next if $opt !~ m/^unused\d+$/;
5170 my $volid = $conf->{$opt};
5171 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5172 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5174 delete $conf->{$opt};
5178 foreach my $volid (sort keys %$volid_hash) {
5179 next if $volid =~ m/vm-$vmid-state-/;
5180 next if $used->{$volid};
5181 my $path = $volid_hash->{$volid}->{path
};
5182 next if !$path; # just to be sure
5183 next if $usedpath->{$path};
5185 add_unused_volume
($conf, $volid);
5186 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5193 my ($vmid, $nolock) = @_;
5195 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5197 my $volid_hash = scan_volids
($cfg, $vmid);
5199 my $updatefn = sub {
5202 my $conf = load_config
($vmid);
5207 foreach my $volid (keys %$volid_hash) {
5208 my $info = $volid_hash->{$volid};
5209 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5212 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5214 update_config_nolock
($vmid, $conf, 1) if $changes;
5217 if (defined($vmid)) {
5221 lock_config
($vmid, $updatefn, $vmid);
5224 my $vmlist = config_list
();
5225 foreach my $vmid (keys %$vmlist) {
5229 lock_config
($vmid, $updatefn, $vmid);
5235 sub restore_vma_archive
{
5236 my ($archive, $vmid, $user, $opts, $comp) = @_;
5238 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5239 my $readfrom = $archive;
5244 my $qarchive = PVE
::Tools
::shellquote
($archive);
5245 if ($comp eq 'gzip') {
5246 $uncomp = "zcat $qarchive|";
5247 } elsif ($comp eq 'lzop') {
5248 $uncomp = "lzop -d -c $qarchive|";
5250 die "unknown compression method '$comp'\n";
5255 my $tmpdir = "/var/tmp/vzdumptmp$$";
5258 # disable interrupts (always do cleanups)
5259 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5260 warn "got interrupt - ignored\n";
5263 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5264 POSIX
::mkfifo
($mapfifo, 0600);
5267 my $openfifo = sub {
5268 open($fifofh, '>', $mapfifo) || die $!;
5271 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5278 my $rpcenv = PVE
::RPCEnvironment
::get
();
5280 my $conffile = config_file
($vmid);
5281 my $tmpfn = "$conffile.$$.tmp";
5283 # Note: $oldconf is undef if VM does not exists
5284 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5286 my $print_devmap = sub {
5287 my $virtdev_hash = {};
5289 my $cfgfn = "$tmpdir/qemu-server.conf";
5291 # we can read the config - that is already extracted
5292 my $fh = IO
::File-
>new($cfgfn, "r") ||
5293 "unable to read qemu-server.conf - $!\n";
5295 while (defined(my $line = <$fh>)) {
5296 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5297 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5298 die "archive does not contain data for drive '$virtdev'\n"
5299 if !$devinfo->{$devname};
5300 if (defined($opts->{storage
})) {
5301 $storeid = $opts->{storage
} || 'local';
5302 } elsif (!$storeid) {
5305 $format = 'raw' if !$format;
5306 $devinfo->{$devname}->{devname
} = $devname;
5307 $devinfo->{$devname}->{virtdev
} = $virtdev;
5308 $devinfo->{$devname}->{format
} = $format;
5309 $devinfo->{$devname}->{storeid
} = $storeid;
5311 # check permission on storage
5312 my $pool = $opts->{pool
}; # todo: do we need that?
5313 if ($user ne 'root@pam') {
5314 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5317 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5321 foreach my $devname (keys %$devinfo) {
5322 die "found no device mapping information for device '$devname'\n"
5323 if !$devinfo->{$devname}->{virtdev
};
5326 my $cfg = cfs_read_file
('storage.cfg');
5328 # create empty/temp config
5330 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5331 foreach_drive
($oldconf, sub {
5332 my ($ds, $drive) = @_;
5334 return if drive_is_cdrom
($drive);
5336 my $volid = $drive->{file
};
5338 return if !$volid || $volid =~ m
|^/|;
5340 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5341 return if !$path || !$owner || ($owner != $vmid);
5343 # Note: only delete disk we want to restore
5344 # other volumes will become unused
5345 if ($virtdev_hash->{$ds}) {
5346 PVE
::Storage
::vdisk_free
($cfg, $volid);
5352 foreach my $virtdev (sort keys %$virtdev_hash) {
5353 my $d = $virtdev_hash->{$virtdev};
5354 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5355 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5357 # test if requested format is supported
5358 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5359 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5360 $d->{format
} = $defFormat if !$supported;
5362 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5363 $d->{format
}, undef, $alloc_size);
5364 print STDERR
"new volume ID is '$volid'\n";
5365 $d->{volid
} = $volid;
5366 my $path = PVE
::Storage
::path
($cfg, $volid);
5368 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5370 my $write_zeros = 1;
5371 # fixme: what other storages types initialize volumes with zero?
5372 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5373 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5377 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5379 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5380 $map->{$virtdev} = $volid;
5383 $fh->seek(0, 0) || die "seek failed - $!\n";
5385 my $outfd = new IO
::File
($tmpfn, "w") ||
5386 die "unable to write config for VM $vmid\n";
5388 my $cookie = { netcount
=> 0 };
5389 while (defined(my $line = <$fh>)) {
5390 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5399 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5400 die "interrupted by signal\n";
5402 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5404 $oldtimeout = alarm($timeout);
5411 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5412 my ($dev_id, $size, $devname) = ($1, $2, $3);
5413 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5414 } elsif ($line =~ m/^CTIME: /) {
5415 # we correctly received the vma config, so we can disable
5416 # the timeout now for disk allocation (set to 10 minutes, so
5417 # that we always timeout if something goes wrong)
5420 print $fifofh "done\n";
5421 my $tmp = $oldtimeout || 0;
5422 $oldtimeout = undef;
5428 print "restore vma archive: $cmd\n";
5429 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5433 alarm($oldtimeout) if $oldtimeout;
5436 foreach my $devname (keys %$devinfo) {
5437 my $volid = $devinfo->{$devname}->{volid
};
5438 push @$vollist, $volid if $volid;
5441 my $cfg = cfs_read_file
('storage.cfg');
5442 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5450 foreach my $devname (keys %$devinfo) {
5451 my $volid = $devinfo->{$devname}->{volid
};
5454 if ($volid =~ m
|^/|) {
5455 unlink $volid || die 'unlink failed\n';
5457 PVE
::Storage
::vdisk_free
($cfg, $volid);
5459 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5461 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5468 rename($tmpfn, $conffile) ||
5469 die "unable to commit configuration file '$conffile'\n";
5471 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5473 eval { rescan
($vmid, 1); };
5477 sub restore_tar_archive
{
5478 my ($archive, $vmid, $user, $opts) = @_;
5480 if ($archive ne '-') {
5481 my $firstfile = tar_archive_read_firstfile
($archive);
5482 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5483 if $firstfile ne 'qemu-server.conf';
5486 my $storecfg = cfs_read_file
('storage.cfg');
5488 # destroy existing data - keep empty config
5489 my $vmcfgfn = config_file
($vmid);
5490 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5492 my $tocmd = "/usr/lib/qemu-server/qmextract";
5494 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5495 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5496 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5497 $tocmd .= ' --info' if $opts->{info
};
5499 # tar option "xf" does not autodetect compression when read from STDIN,
5500 # so we pipe to zcat
5501 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5502 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5504 my $tmpdir = "/var/tmp/vzdumptmp$$";
5507 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5508 local $ENV{VZDUMP_VMID
} = $vmid;
5509 local $ENV{VZDUMP_USER
} = $user;
5511 my $conffile = config_file
($vmid);
5512 my $tmpfn = "$conffile.$$.tmp";
5514 # disable interrupts (always do cleanups)
5515 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5516 print STDERR
"got interrupt - ignored\n";
5521 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5522 die "interrupted by signal\n";
5525 if ($archive eq '-') {
5526 print "extracting archive from STDIN\n";
5527 run_command
($cmd, input
=> "<&STDIN");
5529 print "extracting archive '$archive'\n";
5533 return if $opts->{info
};
5537 my $statfile = "$tmpdir/qmrestore.stat";
5538 if (my $fd = IO
::File-
>new($statfile, "r")) {
5539 while (defined (my $line = <$fd>)) {
5540 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5541 $map->{$1} = $2 if $1;
5543 print STDERR
"unable to parse line in statfile - $line\n";
5549 my $confsrc = "$tmpdir/qemu-server.conf";
5551 my $srcfd = new IO
::File
($confsrc, "r") ||
5552 die "unable to open file '$confsrc'\n";
5554 my $outfd = new IO
::File
($tmpfn, "w") ||
5555 die "unable to write config for VM $vmid\n";
5557 my $cookie = { netcount
=> 0 };
5558 while (defined (my $line = <$srcfd>)) {
5559 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5571 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5578 rename $tmpfn, $conffile ||
5579 die "unable to commit configuration file '$conffile'\n";
5581 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5583 eval { rescan
($vmid, 1); };
5588 # Internal snapshots
5590 # NOTE: Snapshot create/delete involves several non-atomic
5591 # action, and can take a long time.
5592 # So we try to avoid locking the file and use 'lock' variable
5593 # inside the config file instead.
5595 my $snapshot_copy_config = sub {
5596 my ($source, $dest) = @_;
5598 foreach my $k (keys %$source) {
5599 next if $k eq 'snapshots';
5600 next if $k eq 'snapstate';
5601 next if $k eq 'snaptime';
5602 next if $k eq 'vmstate';
5603 next if $k eq 'lock';
5604 next if $k eq 'digest';
5605 next if $k eq 'description';
5606 next if $k =~ m/^unused\d+$/;
5608 $dest->{$k} = $source->{$k};
5612 my $snapshot_apply_config = sub {
5613 my ($conf, $snap) = @_;
5615 # copy snapshot list
5617 snapshots
=> $conf->{snapshots
},
5620 # keep description and list of unused disks
5621 foreach my $k (keys %$conf) {
5622 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5623 $newconf->{$k} = $conf->{$k};
5626 &$snapshot_copy_config($snap, $newconf);
5631 sub foreach_writable_storage
{
5632 my ($conf, $func) = @_;
5636 foreach my $ds (keys %$conf) {
5637 next if !valid_drivename
($ds);
5639 my $drive = parse_drive
($ds, $conf->{$ds});
5641 next if drive_is_cdrom
($drive);
5643 my $volid = $drive->{file
};
5645 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5646 $sidhash->{$sid} = $sid if $sid;
5649 foreach my $sid (sort keys %$sidhash) {
5654 my $alloc_vmstate_volid = sub {
5655 my ($storecfg, $vmid, $conf, $snapname) = @_;
5657 # Note: we try to be smart when selecting a $target storage
5661 # search shared storage first
5662 foreach_writable_storage
($conf, sub {
5664 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5665 return if !$scfg->{shared
};
5667 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5671 # now search local storage
5672 foreach_writable_storage
($conf, sub {
5674 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5675 return if $scfg->{shared
};
5677 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5681 $target = 'local' if !$target;
5683 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5684 # we abort live save after $conf->{memory}, so we need at max twice that space
5685 my $size = $conf->{memory
}*2 + $driver_state_size;
5687 my $name = "vm-$vmid-state-$snapname";
5688 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5689 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5690 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5695 my $snapshot_prepare = sub {
5696 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5700 my $updatefn = sub {
5702 my $conf = load_config
($vmid);
5704 die "you can't take a snapshot if it's a template\n"
5705 if is_template
($conf);
5709 $conf->{lock} = 'snapshot';
5711 die "snapshot name '$snapname' already used\n"
5712 if defined($conf->{snapshots
}->{$snapname});
5714 my $storecfg = PVE
::Storage
::config
();
5715 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5717 $snap = $conf->{snapshots
}->{$snapname} = {};
5719 if ($save_vmstate && check_running
($vmid)) {
5720 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5723 &$snapshot_copy_config($conf, $snap);
5725 $snap->{snapstate
} = "prepare";
5726 $snap->{snaptime
} = time();
5727 $snap->{description
} = $comment if $comment;
5729 # always overwrite machine if we save vmstate. This makes sure we
5730 # can restore it later using correct machine type
5731 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5733 update_config_nolock
($vmid, $conf, 1);
5736 lock_config
($vmid, $updatefn);
5741 my $snapshot_commit = sub {
5742 my ($vmid, $snapname) = @_;
5744 my $updatefn = sub {
5746 my $conf = load_config
($vmid);
5748 die "missing snapshot lock\n"
5749 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5751 my $has_machine_config = defined($conf->{machine
});
5753 my $snap = $conf->{snapshots
}->{$snapname};
5755 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5757 die "wrong snapshot state\n"
5758 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5760 delete $snap->{snapstate
};
5761 delete $conf->{lock};
5763 my $newconf = &$snapshot_apply_config($conf, $snap);
5765 delete $newconf->{machine
} if !$has_machine_config;
5767 $newconf->{parent
} = $snapname;
5769 update_config_nolock
($vmid, $newconf, 1);
5772 lock_config
($vmid, $updatefn);
5775 sub snapshot_rollback
{
5776 my ($vmid, $snapname) = @_;
5780 my $storecfg = PVE
::Storage
::config
();
5782 my $conf = load_config
($vmid);
5784 my $get_snapshot_config = sub {
5786 die "you can't rollback if vm is a template\n" if is_template
($conf);
5788 my $res = $conf->{snapshots
}->{$snapname};
5790 die "snapshot '$snapname' does not exist\n" if !defined($res);
5795 my $snap = &$get_snapshot_config();
5797 foreach_drive
($snap, sub {
5798 my ($ds, $drive) = @_;
5800 return if drive_is_cdrom
($drive);
5802 my $volid = $drive->{file
};
5804 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5807 my $updatefn = sub {
5809 $conf = load_config
($vmid);
5811 $snap = &$get_snapshot_config();
5813 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5814 if $snap->{snapstate
};
5818 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5821 die "unable to rollback vm $vmid: vm is running\n"
5822 if check_running
($vmid);
5825 $conf->{lock} = 'rollback';
5827 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5828 delete $conf->{lock};
5834 my $has_machine_config = defined($conf->{machine
});
5836 # copy snapshot config to current config
5837 $conf = &$snapshot_apply_config($conf, $snap);
5838 $conf->{parent
} = $snapname;
5840 # Note: old code did not store 'machine', so we try to be smart
5841 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5842 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5843 # we remove the 'machine' configuration if not explicitly specified
5844 # in the original config.
5845 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5848 update_config_nolock
($vmid, $conf, 1);
5850 if (!$prepare && $snap->{vmstate
}) {
5851 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5852 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5856 lock_config
($vmid, $updatefn);
5858 foreach_drive
($snap, sub {
5859 my ($ds, $drive) = @_;
5861 return if drive_is_cdrom
($drive);
5863 my $volid = $drive->{file
};
5864 my $device = "drive-$ds";
5866 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5870 lock_config
($vmid, $updatefn);
5873 my $savevm_wait = sub {
5877 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5878 if (!$stat->{status
}) {
5879 die "savevm not active\n";
5880 } elsif ($stat->{status
} eq 'active') {
5883 } elsif ($stat->{status
} eq 'completed') {
5886 die "query-savevm returned status '$stat->{status}'\n";
5891 sub do_snapshots_with_qemu
{
5892 my ($storecfg, $volid) = @_;
5894 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5896 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5897 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5901 if ($volid =~ m/\.(qcow2|qed)$/){
5908 sub snapshot_create
{
5909 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5911 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5913 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5915 my $config = load_config
($vmid);
5917 my $running = check_running
($vmid);
5919 my $freezefs = $running && $config->{agent
};
5920 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5925 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5926 warn "guest-fsfreeze-freeze problems - $@" if $@;
5930 # create internal snapshots of all drives
5932 my $storecfg = PVE
::Storage
::config
();
5935 if ($snap->{vmstate
}) {
5936 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5937 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5938 &$savevm_wait($vmid);
5940 vm_mon_cmd
($vmid, "savevm-start");
5944 foreach_drive
($snap, sub {
5945 my ($ds, $drive) = @_;
5947 return if drive_is_cdrom
($drive);
5949 my $volid = $drive->{file
};
5950 my $device = "drive-$ds";
5952 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5953 $drivehash->{$ds} = 1;
5959 eval { vm_mon_cmd
($vmid, "savevm-end") };
5963 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5964 warn "guest-fsfreeze-thaw problems - $@" if $@;
5967 # savevm-end is async, we need to wait
5969 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5970 if (!$stat->{bytes
}) {
5973 print "savevm not yet finished\n";
5981 warn "snapshot create failed: starting cleanup\n";
5982 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5987 &$snapshot_commit($vmid, $snapname);
5990 # Note: $drivehash is only set when called from snapshot_create.
5991 sub snapshot_delete
{
5992 my ($vmid, $snapname, $force, $drivehash) = @_;
5999 my $unlink_parent = sub {
6000 my ($confref, $new_parent) = @_;
6002 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6004 $confref->{parent
} = $new_parent;
6006 delete $confref->{parent
};
6011 my $updatefn = sub {
6012 my ($remove_drive) = @_;
6014 my $conf = load_config
($vmid);
6018 die "you can't delete a snapshot if vm is a template\n"
6019 if is_template
($conf);
6022 $snap = $conf->{snapshots
}->{$snapname};
6024 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6026 # remove parent refs
6028 &$unlink_parent($conf, $snap->{parent
});
6029 foreach my $sn (keys %{$conf->{snapshots
}}) {
6030 next if $sn eq $snapname;
6031 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6035 if ($remove_drive) {
6036 if ($remove_drive eq 'vmstate') {
6037 delete $snap->{$remove_drive};
6039 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6040 my $volid = $drive->{file
};
6041 delete $snap->{$remove_drive};
6042 add_unused_volume
($conf, $volid);
6047 $snap->{snapstate
} = 'delete';
6049 delete $conf->{snapshots
}->{$snapname};
6050 delete $conf->{lock} if $drivehash;
6051 foreach my $volid (@$unused) {
6052 add_unused_volume
($conf, $volid);
6056 update_config_nolock
($vmid, $conf, 1);
6059 lock_config
($vmid, $updatefn);
6061 # now remove vmstate file
6063 my $storecfg = PVE
::Storage
::config
();
6065 if ($snap->{vmstate
}) {
6066 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6068 die $err if !$force;
6071 # save changes (remove vmstate from snapshot)
6072 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6075 # now remove all internal snapshots
6076 foreach_drive
($snap, sub {
6077 my ($ds, $drive) = @_;
6079 return if drive_is_cdrom
($drive);
6081 my $volid = $drive->{file
};
6082 my $device = "drive-$ds";
6084 if (!$drivehash || $drivehash->{$ds}) {
6085 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6087 die $err if !$force;
6092 # save changes (remove drive fron snapshot)
6093 lock_config
($vmid, $updatefn, $ds) if !$force;
6094 push @$unused, $volid;
6097 # now cleanup config
6099 lock_config
($vmid, $updatefn);
6103 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6106 foreach_drive
($conf, sub {
6107 my ($ds, $drive) = @_;
6109 return if drive_is_cdrom
($drive);
6110 my $volid = $drive->{file
};
6111 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6114 return $err ?
0 : 1;
6117 sub template_create
{
6118 my ($vmid, $conf, $disk) = @_;
6120 my $storecfg = PVE
::Storage
::config
();
6122 foreach_drive
($conf, sub {
6123 my ($ds, $drive) = @_;
6125 return if drive_is_cdrom
($drive);
6126 return if $disk && $ds ne $disk;
6128 my $volid = $drive->{file
};
6129 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6131 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6132 $drive->{file
} = $voliddst;
6133 $conf->{$ds} = print_drive
($vmid, $drive);
6134 update_config_nolock
($vmid, $conf, 1);
6141 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6144 sub qemu_img_convert
{
6145 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6147 my $storecfg = PVE
::Storage
::config
();
6148 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6149 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6151 if ($src_storeid && $dst_storeid) {
6152 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6153 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6155 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6156 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6158 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6159 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6162 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6163 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6164 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6168 if($line =~ m/\((\S+)\/100\
%\)/){
6170 my $transferred = int($size * $percent / 100);
6171 my $remaining = $size - $transferred;
6173 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6178 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6180 die "copy failed: $err" if $err;
6184 sub qemu_img_format
{
6185 my ($scfg, $volname) = @_;
6187 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6194 sub qemu_drive_mirror
{
6195 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6197 my $storecfg = PVE
::Storage
::config
();
6198 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6200 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6202 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6204 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6206 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6207 $opts->{format
} = $format if $format;
6209 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6212 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6214 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6215 my $stat = @$stats[0];
6216 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6217 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6219 my $busy = $stat->{busy
};
6220 my $ready = $stat->{ready
};
6222 if (my $total = $stat->{len
}) {
6223 my $transferred = $stat->{offset
} || 0;
6224 my $remaining = $total - $transferred;
6225 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6227 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6231 if ($stat->{ready
} eq 'true') {
6233 last if $vmiddst != $vmid;
6235 # try to switch the disk if source and destination are on the same guest
6236 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6238 die $@ if $@ !~ m/cannot be completed/;
6247 my $cancel_job = sub {
6248 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6250 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6251 my $stat = @$stats[0];
6258 eval { &$cancel_job(); };
6259 die "mirroring error: $err";
6262 if ($vmiddst != $vmid) {
6263 # if we clone a disk for a new target vm, we don't switch the disk
6264 &$cancel_job(); # so we call block-job-cancel
6269 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6270 $newvmid, $storage, $format, $full, $newvollist) = @_;
6275 print "create linked clone of drive $drivename ($drive->{file})\n";
6276 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6277 push @$newvollist, $newvolid;
6279 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6280 $storeid = $storage if $storage;
6282 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6284 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6285 $format = qemu_img_format
($scfg, $volname);
6288 # test if requested format is supported - else use default
6289 my $supported = grep { $_ eq $format } @$validFormats;
6290 $format = $defFormat if !$supported;
6292 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6294 print "create full clone of drive $drivename ($drive->{file})\n";
6295 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6296 push @$newvollist, $newvolid;
6298 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6300 if (!$running || $snapname) {
6301 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6303 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6307 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6310 $disk->{format
} = undef;
6311 $disk->{file
} = $newvolid;
6312 $disk->{size
} = $size;
6317 # this only works if VM is running
6318 sub get_current_qemu_machine
{
6321 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6322 my $res = vm_qmp_command
($vmid, $cmd);
6324 my ($current, $default);
6325 foreach my $e (@$res) {
6326 $default = $e->{name
} if $e->{'is-default'};
6327 $current = $e->{name
} if $e->{'is-current'};
6330 # fallback to the default machine if current is not supported by qemu
6331 return $current || $default || 'pc';
6334 sub qemu_machine_feature_enabled
{
6335 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6340 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6342 $current_major = $3;
6343 $current_minor = $4;
6345 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6347 $current_major = $1;
6348 $current_minor = $2;
6351 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6356 sub qemu_machine_pxe
{
6357 my ($vmid, $conf, $machine) = @_;
6359 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6361 foreach my $opt (keys %$conf) {
6362 next if $opt !~ m/^net(\d+)$/;
6363 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6365 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6366 return $machine.".pxe" if $romfile =~ m/pxe/;
6372 sub qemu_use_old_bios_files
{
6373 my ($machine_type) = @_;
6375 return if !$machine_type;
6377 my $use_old_bios_files = undef;
6379 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6381 $use_old_bios_files = 1;
6383 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6384 # load new efi bios files on migration. So this hack is required to allow
6385 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6386 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6387 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6390 return ($use_old_bios_files, $machine_type);
6397 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6398 my (undef, $id, $function) = @_;
6399 my $res = { id
=> $id, function
=> $function};
6400 push @{$devices->{$id}}, $res;
6406 sub vm_iothreads_list
{
6409 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6412 foreach my $iothread (@$res) {
6413 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6420 my ($conf, $drive) = @_;
6424 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6426 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6432 my $controller = int($drive->{index} / $maxdev);
6433 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6435 return ($maxdev, $controller, $controller_prefix);
6438 # bash completion helper
6440 sub complete_backup_archives
{
6441 my ($cmdname, $pname, $cvalue) = @_;
6443 my $cfg = PVE
::Storage
::config
();
6447 if ($cvalue =~ m/^([^:]+):/) {
6451 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6454 foreach my $id (keys %$data) {
6455 foreach my $item (@{$data->{$id}}) {
6456 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6457 push @$res, $item->{volid
} if defined($item->{volid
});
6464 my $complete_vmid_full = sub {
6467 my $idlist = vmstatus
();
6471 foreach my $id (keys %$idlist) {
6472 my $d = $idlist->{$id};
6473 if (defined($running)) {
6474 next if $d->{template
};
6475 next if $running && $d->{status
} ne 'running';
6476 next if !$running && $d->{status
} eq 'running';
6485 return &$complete_vmid_full();
6488 sub complete_vmid_stopped
{
6489 return &$complete_vmid_full(0);
6492 sub complete_vmid_running
{
6493 return &$complete_vmid_full(1);
6496 sub complete_storage
{
6498 my $cfg = PVE
::Storage
::config
();
6499 my $ids = $cfg->{ids
};
6502 foreach my $sid (keys %$ids) {
6503 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);