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, $hotplug) = @_;
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";
1281 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1283 if ($net->{bridge
}) {
1284 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1286 $netdev = "type=user,id=$netid,hostname=$vmname";
1289 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1294 sub drive_is_cdrom
{
1297 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1306 foreach my $kvp (split(/,/, $data)) {
1308 if ($kvp =~ m/^memory=(\S+)$/) {
1309 $res->{memory
} = $1;
1310 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1311 $res->{policy
} = $1;
1312 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1313 $res->{cpus
}->{start
} = $1;
1314 $res->{cpus
}->{end
} = $3;
1315 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1316 $res->{hostnodes
}->{start
} = $1;
1317 $res->{hostnodes
}->{end
} = $3;
1329 return undef if !$value;
1332 my @list = split(/,/, $value);
1336 foreach my $kv (@list) {
1338 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1341 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1344 my $pcidevices = lspci
($2);
1345 $res->{pciid
} = $pcidevices->{$2};
1347 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1348 $res->{rombar
} = $1;
1349 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1350 $res->{'x-vga'} = $1;
1351 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1352 $res->{pcie
} = 1 if $1 == 1;
1354 warn "unknown hostpci setting '$kv'\n";
1358 return undef if !$found;
1363 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1369 foreach my $kvp (split(/,/, $data)) {
1371 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) {
1373 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1374 $res->{model
} = $model;
1375 $res->{macaddr
} = $mac;
1376 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1377 $res->{bridge
} = $1;
1378 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1379 $res->{queues
} = $1;
1380 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1382 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1384 } elsif ($kvp =~ m/^firewall=([01])$/) {
1385 $res->{firewall
} = $1;
1386 } elsif ($kvp =~ m/^link_down=([01])$/) {
1387 $res->{link_down
} = $1;
1394 return undef if !$res->{model
};
1402 my $res = "$net->{model}";
1403 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1404 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1405 $res .= ",rate=$net->{rate}" if $net->{rate
};
1406 $res .= ",tag=$net->{tag}" if $net->{tag
};
1407 $res .= ",firewall=1" if $net->{firewall
};
1408 $res .= ",link_down=1" if $net->{link_down
};
1409 $res .= ",queues=$net->{queues}" if $net->{queues
};
1414 sub add_random_macs
{
1415 my ($settings) = @_;
1417 foreach my $opt (keys %$settings) {
1418 next if $opt !~ m/^net(\d+)$/;
1419 my $net = parse_net
($settings->{$opt});
1421 $settings->{$opt} = print_net
($net);
1425 sub add_unused_volume
{
1426 my ($config, $volid) = @_;
1429 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1430 my $test = "unused$ind";
1431 if (my $vid = $config->{$test}) {
1432 return if $vid eq $volid; # do not add duplicates
1438 die "To many unused volume - please delete them first.\n" if !$key;
1440 $config->{$key} = $volid;
1445 sub vm_is_volid_owner
{
1446 my ($storecfg, $vmid, $volid) = @_;
1448 if ($volid !~ m
|^/|) {
1450 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1451 if ($owner && ($owner == $vmid)) {
1459 sub split_flagged_list
{
1460 my $text = shift || '';
1461 $text =~ s/[,;]/ /g;
1463 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1466 sub join_flagged_list
{
1467 my ($how, $lst) = @_;
1468 join $how, map { $lst->{$_} . $_ } keys %$lst;
1471 sub vmconfig_delete_pending_option
{
1472 my ($conf, $key, $force) = @_;
1474 delete $conf->{pending
}->{$key};
1475 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1476 $pending_delete_hash->{$key} = $force ?
'!' : '';
1477 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1480 sub vmconfig_undelete_pending_option
{
1481 my ($conf, $key) = @_;
1483 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1484 delete $pending_delete_hash->{$key};
1486 if (%$pending_delete_hash) {
1487 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1489 delete $conf->{pending
}->{delete};
1493 sub vmconfig_register_unused_drive
{
1494 my ($storecfg, $vmid, $conf, $drive) = @_;
1496 if (!drive_is_cdrom
($drive)) {
1497 my $volid = $drive->{file
};
1498 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1499 add_unused_volume
($conf, $volid, $vmid);
1504 sub vmconfig_cleanup_pending
{
1507 # remove pending changes when nothing changed
1509 foreach my $opt (keys %{$conf->{pending
}}) {
1510 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1512 delete $conf->{pending
}->{$opt};
1516 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1517 my $pending_delete_hash = {};
1518 while (my ($opt, $force) = each %$current_delete_hash) {
1519 if (defined($conf->{$opt})) {
1520 $pending_delete_hash->{$opt} = $force;
1526 if (%$pending_delete_hash) {
1527 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1529 delete $conf->{pending
}->{delete};
1535 my $valid_smbios1_options = {
1536 manufacturer
=> '\S+',
1540 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1545 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1551 foreach my $kvp (split(/,/, $data)) {
1552 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1553 my ($k, $v) = split(/=/, $kvp);
1554 return undef if !defined($k) || !defined($v);
1555 return undef if !$valid_smbios1_options->{$k};
1556 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1567 foreach my $k (keys %$smbios1) {
1568 next if !defined($smbios1->{$k});
1569 next if !$valid_smbios1_options->{$k};
1570 $data .= ',' if $data;
1571 $data .= "$k=$smbios1->{$k}";
1576 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1577 sub verify_smbios1
{
1578 my ($value, $noerr) = @_;
1580 return $value if parse_smbios1
($value);
1582 return undef if $noerr;
1584 die "unable to parse smbios (type 1) options\n";
1587 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1588 sub verify_bootdisk
{
1589 my ($value, $noerr) = @_;
1591 return $value if valid_drivename
($value);
1593 return undef if $noerr;
1595 die "invalid boot disk '$value'\n";
1598 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1600 my ($value, $noerr) = @_;
1602 return $value if parse_numa
($value);
1604 return undef if $noerr;
1606 die "unable to parse numa options\n";
1609 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1611 my ($value, $noerr) = @_;
1613 return $value if parse_net
($value);
1615 return undef if $noerr;
1617 die "unable to parse network options\n";
1620 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1622 my ($value, $noerr) = @_;
1624 return $value if parse_drive
(undef, $value);
1626 return undef if $noerr;
1628 die "unable to parse drive options\n";
1631 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1632 sub verify_hostpci
{
1633 my ($value, $noerr) = @_;
1635 return $value if parse_hostpci
($value);
1637 return undef if $noerr;
1639 die "unable to parse pci id\n";
1642 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1643 sub verify_watchdog
{
1644 my ($value, $noerr) = @_;
1646 return $value if parse_watchdog
($value);
1648 return undef if $noerr;
1650 die "unable to parse watchdog options\n";
1653 sub parse_watchdog
{
1656 return undef if !$value;
1660 foreach my $p (split(/,/, $value)) {
1661 next if $p =~ m/^\s*$/;
1663 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1665 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1666 $res->{action
} = $2;
1675 sub parse_usb_device
{
1678 return undef if !$value;
1680 my @dl = split(/,/, $value);
1684 foreach my $v (@dl) {
1685 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1687 $res->{vendorid
} = $2;
1688 $res->{productid
} = $4;
1689 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1691 $res->{hostbus
} = $1;
1692 $res->{hostport
} = $2;
1693 } elsif ($v =~ m/^spice$/) {
1700 return undef if !$found;
1705 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1706 sub verify_usb_device
{
1707 my ($value, $noerr) = @_;
1709 return $value if parse_usb_device
($value);
1711 return undef if $noerr;
1713 die "unable to parse usb device\n";
1716 # add JSON properties for create and set function
1717 sub json_config_properties
{
1720 foreach my $opt (keys %$confdesc) {
1721 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1722 $prop->{$opt} = $confdesc->{$opt};
1729 my ($key, $value) = @_;
1731 die "unknown setting '$key'\n" if !$confdesc->{$key};
1733 my $type = $confdesc->{$key}->{type
};
1735 if (!defined($value)) {
1736 die "got undefined value\n";
1739 if ($value =~ m/[\n\r]/) {
1740 die "property contains a line feed\n";
1743 if ($type eq 'boolean') {
1744 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1745 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1746 die "type check ('boolean') failed - got '$value'\n";
1747 } elsif ($type eq 'integer') {
1748 return int($1) if $value =~ m/^(\d+)$/;
1749 die "type check ('integer') failed - got '$value'\n";
1750 } elsif ($type eq 'number') {
1751 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1752 die "type check ('number') failed - got '$value'\n";
1753 } elsif ($type eq 'string') {
1754 if (my $fmt = $confdesc->{$key}->{format
}) {
1755 if ($fmt eq 'pve-qm-drive') {
1756 # special case - we need to pass $key to parse_drive()
1757 my $drive = parse_drive
($key, $value);
1758 return $value if $drive;
1759 die "unable to parse drive options\n";
1761 PVE
::JSONSchema
::check_format
($fmt, $value);
1764 $value =~ s/^\"(.*)\"$/$1/;
1767 die "internal error"
1771 sub lock_config_full
{
1772 my ($vmid, $timeout, $code, @param) = @_;
1774 my $filename = config_file_lock
($vmid);
1776 my $res = lock_file
($filename, $timeout, $code, @param);
1783 sub lock_config_mode
{
1784 my ($vmid, $timeout, $shared, $code, @param) = @_;
1786 my $filename = config_file_lock
($vmid);
1788 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1796 my ($vmid, $code, @param) = @_;
1798 return lock_config_full
($vmid, 10, $code, @param);
1801 sub cfs_config_path
{
1802 my ($vmid, $node) = @_;
1804 $node = $nodename if !$node;
1805 return "nodes/$node/qemu-server/$vmid.conf";
1808 sub check_iommu_support
{
1809 #fixme : need to check IOMMU support
1810 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1818 my ($vmid, $node) = @_;
1820 my $cfspath = cfs_config_path
($vmid, $node);
1821 return "/etc/pve/$cfspath";
1824 sub config_file_lock
{
1827 return "$lock_dir/lock-$vmid.conf";
1833 my $conf = config_file
($vmid);
1834 utime undef, undef, $conf;
1838 my ($storecfg, $vmid, $keep_empty_config) = @_;
1840 my $conffile = config_file
($vmid);
1842 my $conf = load_config
($vmid);
1846 # only remove disks owned by this VM
1847 foreach_drive
($conf, sub {
1848 my ($ds, $drive) = @_;
1850 return if drive_is_cdrom
($drive);
1852 my $volid = $drive->{file
};
1854 return if !$volid || $volid =~ m
|^/|;
1856 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1857 return if !$path || !$owner || ($owner != $vmid);
1859 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1862 if ($keep_empty_config) {
1863 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1868 # also remove unused disk
1870 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1873 PVE
::Storage
::foreach_volid
($dl, sub {
1874 my ($volid, $sid, $volname, $d) = @_;
1875 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1885 my ($vmid, $node) = @_;
1887 my $cfspath = cfs_config_path
($vmid, $node);
1889 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1891 die "no such VM ('$vmid')\n" if !defined($conf);
1896 sub parse_vm_config
{
1897 my ($filename, $raw) = @_;
1899 return undef if !defined($raw);
1902 digest
=> Digest
::SHA
::sha1_hex
($raw),
1907 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1908 || die "got strange filename '$filename'";
1916 my @lines = split(/\n/, $raw);
1917 foreach my $line (@lines) {
1918 next if $line =~ m/^\s*$/;
1920 if ($line =~ m/^\[PENDING\]\s*$/i) {
1921 $section = 'pending';
1922 if (defined($descr)) {
1924 $conf->{description
} = $descr;
1927 $conf = $res->{$section} = {};
1930 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1932 if (defined($descr)) {
1934 $conf->{description
} = $descr;
1937 $conf = $res->{snapshots
}->{$section} = {};
1941 if ($line =~ m/^\#(.*)\s*$/) {
1942 $descr = '' if !defined($descr);
1943 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1947 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1948 $descr = '' if !defined($descr);
1949 $descr .= PVE
::Tools
::decode_text
($2);
1950 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1951 $conf->{snapstate
} = $1;
1952 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1955 $conf->{$key} = $value;
1956 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1958 if ($section eq 'pending') {
1959 $conf->{delete} = $value; # we parse this later
1961 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1963 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1966 eval { $value = check_type
($key, $value); };
1968 warn "vm $vmid - unable to parse value of '$key' - $@";
1970 my $fmt = $confdesc->{$key}->{format
};
1971 if ($fmt && $fmt eq 'pve-qm-drive') {
1972 my $v = parse_drive
($key, $value);
1973 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1974 $v->{file
} = $volid;
1975 $value = print_drive
($vmid, $v);
1977 warn "vm $vmid - unable to parse value of '$key'\n";
1982 if ($key eq 'cdrom') {
1983 $conf->{ide2
} = $value;
1985 $conf->{$key} = $value;
1991 if (defined($descr)) {
1993 $conf->{description
} = $descr;
1995 delete $res->{snapstate
}; # just to be sure
2000 sub write_vm_config
{
2001 my ($filename, $conf) = @_;
2003 delete $conf->{snapstate
}; # just to be sure
2005 if ($conf->{cdrom
}) {
2006 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2007 $conf->{ide2
} = $conf->{cdrom
};
2008 delete $conf->{cdrom
};
2011 # we do not use 'smp' any longer
2012 if ($conf->{sockets
}) {
2013 delete $conf->{smp
};
2014 } elsif ($conf->{smp
}) {
2015 $conf->{sockets
} = $conf->{smp
};
2016 delete $conf->{cores
};
2017 delete $conf->{smp
};
2020 my $used_volids = {};
2022 my $cleanup_config = sub {
2023 my ($cref, $pending, $snapname) = @_;
2025 foreach my $key (keys %$cref) {
2026 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2027 $key eq 'snapstate' || $key eq 'pending';
2028 my $value = $cref->{$key};
2029 if ($key eq 'delete') {
2030 die "propertry 'delete' is only allowed in [PENDING]\n"
2032 # fixme: check syntax?
2035 eval { $value = check_type
($key, $value); };
2036 die "unable to parse value of '$key' - $@" if $@;
2038 $cref->{$key} = $value;
2040 if (!$snapname && valid_drivename
($key)) {
2041 my $drive = parse_drive
($key, $value);
2042 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2047 &$cleanup_config($conf);
2049 &$cleanup_config($conf->{pending
}, 1);
2051 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2052 die "internal error" if $snapname eq 'pending';
2053 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2056 # remove 'unusedX' settings if we re-add a volume
2057 foreach my $key (keys %$conf) {
2058 my $value = $conf->{$key};
2059 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2060 delete $conf->{$key};
2064 my $generate_raw_config = sub {
2065 my ($conf, $pending) = @_;
2069 # add description as comment to top of file
2070 if (defined(my $descr = $conf->{description
})) {
2072 foreach my $cl (split(/\n/, $descr)) {
2073 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2076 $raw .= "#\n" if $pending;
2080 foreach my $key (sort keys %$conf) {
2081 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2082 $raw .= "$key: $conf->{$key}\n";
2087 my $raw = &$generate_raw_config($conf);
2089 if (scalar(keys %{$conf->{pending
}})){
2090 $raw .= "\n[PENDING]\n";
2091 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2094 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2095 $raw .= "\n[$snapname]\n";
2096 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2102 sub update_config_nolock
{
2103 my ($vmid, $conf, $skiplock) = @_;
2105 check_lock
($conf) if !$skiplock;
2107 my $cfspath = cfs_config_path
($vmid);
2109 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2113 my ($vmid, $conf, $skiplock) = @_;
2115 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2122 # we use static defaults from our JSON schema configuration
2123 foreach my $key (keys %$confdesc) {
2124 if (defined(my $default = $confdesc->{$key}->{default})) {
2125 $res->{$key} = $default;
2129 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2130 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2136 my $vmlist = PVE
::Cluster
::get_vmlist
();
2138 return $res if !$vmlist || !$vmlist->{ids
};
2139 my $ids = $vmlist->{ids
};
2141 foreach my $vmid (keys %$ids) {
2142 my $d = $ids->{$vmid};
2143 next if !$d->{node
} || $d->{node
} ne $nodename;
2144 next if !$d->{type
} || $d->{type
} ne 'qemu';
2145 $res->{$vmid}->{exists} = 1;
2150 # test if VM uses local resources (to prevent migration)
2151 sub check_local_resources
{
2152 my ($conf, $noerr) = @_;
2156 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2157 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2159 foreach my $k (keys %$conf) {
2160 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2161 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2164 die "VM uses local resources\n" if $loc_res && !$noerr;
2169 # check if used storages are available on all nodes (use by migrate)
2170 sub check_storage_availability
{
2171 my ($storecfg, $conf, $node) = @_;
2173 foreach_drive
($conf, sub {
2174 my ($ds, $drive) = @_;
2176 my $volid = $drive->{file
};
2179 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2182 # check if storage is available on both nodes
2183 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2184 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2188 # list nodes where all VM images are available (used by has_feature API)
2190 my ($conf, $storecfg) = @_;
2192 my $nodelist = PVE
::Cluster
::get_nodelist
();
2193 my $nodehash = { map { $_ => 1 } @$nodelist };
2194 my $nodename = PVE
::INotify
::nodename
();
2196 foreach_drive
($conf, sub {
2197 my ($ds, $drive) = @_;
2199 my $volid = $drive->{file
};
2202 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2204 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2205 if ($scfg->{disable
}) {
2207 } elsif (my $avail = $scfg->{nodes
}) {
2208 foreach my $node (keys %$nodehash) {
2209 delete $nodehash->{$node} if !$avail->{$node};
2211 } elsif (!$scfg->{shared
}) {
2212 foreach my $node (keys %$nodehash) {
2213 delete $nodehash->{$node} if $node ne $nodename
2225 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2229 my ($pidfile, $pid) = @_;
2231 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2235 return undef if !$line;
2236 my @param = split(/\0/, $line);
2238 my $cmd = $param[0];
2239 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2241 for (my $i = 0; $i < scalar (@param); $i++) {
2244 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2245 my $p = $param[$i+1];
2246 return 1 if $p && ($p eq $pidfile);
2255 my ($vmid, $nocheck, $node) = @_;
2257 my $filename = config_file
($vmid, $node);
2259 die "unable to find configuration file for VM $vmid - no such machine\n"
2260 if !$nocheck && ! -f
$filename;
2262 my $pidfile = pidfile_name
($vmid);
2264 if (my $fd = IO
::File-
>new("<$pidfile")) {
2269 my $mtime = $st->mtime;
2270 if ($mtime > time()) {
2271 warn "file '$filename' modified in future\n";
2274 if ($line =~ m/^(\d+)$/) {
2276 if (check_cmdline
($pidfile, $pid)) {
2277 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2289 my $vzlist = config_list
();
2291 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2293 while (defined(my $de = $fd->read)) {
2294 next if $de !~ m/^(\d+)\.pid$/;
2296 next if !defined($vzlist->{$vmid});
2297 if (my $pid = check_running
($vmid)) {
2298 $vzlist->{$vmid}->{pid
} = $pid;
2306 my ($storecfg, $conf) = @_;
2308 my $bootdisk = $conf->{bootdisk
};
2309 return undef if !$bootdisk;
2310 return undef if !valid_drivename
($bootdisk);
2312 return undef if !$conf->{$bootdisk};
2314 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2315 return undef if !defined($drive);
2317 return undef if drive_is_cdrom
($drive);
2319 my $volid = $drive->{file
};
2320 return undef if !$volid;
2322 return $drive->{size
};
2325 my $last_proc_pid_stat;
2327 # get VM status information
2328 # This must be fast and should not block ($full == false)
2329 # We only query KVM using QMP if $full == true (this can be slow)
2331 my ($opt_vmid, $full) = @_;
2335 my $storecfg = PVE
::Storage
::config
();
2337 my $list = vzlist
();
2338 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2340 my $cpucount = $cpuinfo->{cpus
} || 1;
2342 foreach my $vmid (keys %$list) {
2343 next if $opt_vmid && ($vmid ne $opt_vmid);
2345 my $cfspath = cfs_config_path
($vmid);
2346 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2349 $d->{pid
} = $list->{$vmid}->{pid
};
2351 # fixme: better status?
2352 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2354 my $size = disksize
($storecfg, $conf);
2355 if (defined($size)) {
2356 $d->{disk
} = 0; # no info available
2357 $d->{maxdisk
} = $size;
2363 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2364 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2365 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2367 $d->{name
} = $conf->{name
} || "VM $vmid";
2368 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2370 if ($conf->{balloon
}) {
2371 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2372 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2383 $d->{diskwrite
} = 0;
2385 $d->{template
} = is_template
($conf);
2390 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2391 foreach my $dev (keys %$netdev) {
2392 next if $dev !~ m/^tap([1-9]\d*)i/;
2394 my $d = $res->{$vmid};
2397 $d->{netout
} += $netdev->{$dev}->{receive
};
2398 $d->{netin
} += $netdev->{$dev}->{transmit
};
2401 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2402 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2407 my $ctime = gettimeofday
;
2409 foreach my $vmid (keys %$list) {
2411 my $d = $res->{$vmid};
2412 my $pid = $d->{pid
};
2415 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2416 next if !$pstat; # not running
2418 my $used = $pstat->{utime} + $pstat->{stime
};
2420 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2422 if ($pstat->{vsize
}) {
2423 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2426 my $old = $last_proc_pid_stat->{$pid};
2428 $last_proc_pid_stat->{$pid} = {
2436 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2438 if ($dtime > 1000) {
2439 my $dutime = $used - $old->{used
};
2441 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2442 $last_proc_pid_stat->{$pid} = {
2448 $d->{cpu
} = $old->{cpu
};
2452 return $res if !$full;
2454 my $qmpclient = PVE
::QMPClient-
>new();
2456 my $ballooncb = sub {
2457 my ($vmid, $resp) = @_;
2459 my $info = $resp->{'return'};
2460 return if !$info->{max_mem
};
2462 my $d = $res->{$vmid};
2464 # use memory assigned to VM
2465 $d->{maxmem
} = $info->{max_mem
};
2466 $d->{balloon
} = $info->{actual
};
2468 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2469 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2470 $d->{freemem
} = $info->{free_mem
};
2473 $d->{ballooninfo
} = $info;
2476 my $blockstatscb = sub {
2477 my ($vmid, $resp) = @_;
2478 my $data = $resp->{'return'} || [];
2479 my $totalrdbytes = 0;
2480 my $totalwrbytes = 0;
2482 for my $blockstat (@$data) {
2483 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2484 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2486 $blockstat->{device
} =~ s/drive-//;
2487 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2489 $res->{$vmid}->{diskread
} = $totalrdbytes;
2490 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2493 my $statuscb = sub {
2494 my ($vmid, $resp) = @_;
2496 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2497 # this fails if ballon driver is not loaded, so this must be
2498 # the last commnand (following command are aborted if this fails).
2499 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2501 my $status = 'unknown';
2502 if (!defined($status = $resp->{'return'}->{status
})) {
2503 warn "unable to get VM status\n";
2507 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2510 foreach my $vmid (keys %$list) {
2511 next if $opt_vmid && ($vmid ne $opt_vmid);
2512 next if !$res->{$vmid}->{pid
}; # not running
2513 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2516 $qmpclient->queue_execute(undef, 1);
2518 foreach my $vmid (keys %$list) {
2519 next if $opt_vmid && ($vmid ne $opt_vmid);
2520 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2527 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2530 my $current_size = 1024;
2531 my $dimm_size = 512;
2532 return if $current_size == $memory;
2534 for (my $j = 0; $j < 8; $j++) {
2535 for (my $i = 0; $i < 32; $i++) {
2536 my $name = "dimm${dimm_id}";
2538 my $numanode = $i % $sockets;
2539 $current_size += $dimm_size;
2540 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2541 return $current_size if $current_size >= $memory;
2547 sub foreach_reverse_dimm
{
2548 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2551 my $current_size = 4177920;
2552 my $dimm_size = 65536;
2553 return if $current_size == $memory;
2555 for (my $j = 0; $j < 8; $j++) {
2556 for (my $i = 0; $i < 32; $i++) {
2557 my $name = "dimm${dimm_id}";
2559 my $numanode = $i % $sockets;
2560 $current_size -= $dimm_size;
2561 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2562 return $current_size if $current_size <= $memory;
2569 my ($conf, $func) = @_;
2571 foreach my $ds (keys %$conf) {
2572 next if !valid_drivename
($ds);
2574 my $drive = parse_drive
($ds, $conf->{$ds});
2577 &$func($ds, $drive);
2582 my ($conf, $func) = @_;
2586 my $test_volid = sub {
2587 my ($volid, $is_cdrom) = @_;
2591 $volhash->{$volid} = $is_cdrom || 0;
2594 foreach_drive
($conf, sub {
2595 my ($ds, $drive) = @_;
2596 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2599 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2600 my $snap = $conf->{snapshots
}->{$snapname};
2601 &$test_volid($snap->{vmstate
}, 0);
2602 foreach_drive
($snap, sub {
2603 my ($ds, $drive) = @_;
2604 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2608 foreach my $volid (keys %$volhash) {
2609 &$func($volid, $volhash->{$volid});
2613 sub vga_conf_has_spice
{
2616 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2621 sub config_to_command
{
2622 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2625 my $globalFlags = [];
2626 my $machineFlags = [];
2632 my $kvmver = kvm_user_version
();
2633 my $vernum = 0; # unknown
2634 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2635 $vernum = $1*1000000+$2*1000;
2636 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2637 $vernum = $1*1000000+$2*1000+$3;
2640 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2642 my $have_ovz = -f
'/proc/vz/vestat';
2644 my $q35 = machine_type_is_q35
($conf);
2645 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2646 my $machine_type = $forcemachine || $conf->{machine
};
2647 my $use_old_bios_files = undef;
2648 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2650 my $cpuunits = defined($conf->{cpuunits
}) ?
2651 $conf->{cpuunits
} : $defaults->{cpuunits
};
2653 push @$cmd, '/usr/bin/systemd-run';
2654 push @$cmd, '--scope';
2655 push @$cmd, '--slice', "qemu";
2656 push @$cmd, '--unit', $vmid;
2657 push @$cmd, '-p', "CPUShares=$cpuunits";
2658 if ($conf->{cpulimit
}) {
2659 my $cpulimit = int($conf->{cpulimit
} * 100);
2660 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2663 push @$cmd, '/usr/bin/kvm';
2665 push @$cmd, '-id', $vmid;
2669 my $qmpsocket = qmp_socket
($vmid);
2670 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2671 push @$cmd, '-mon', "chardev=qmp,mode=control";
2673 my $socket = vnc_socket
($vmid);
2674 push @$cmd, '-vnc', "unix:$socket,x509,password";
2676 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2678 push @$cmd, '-daemonize';
2680 if ($conf->{smbios1
}) {
2681 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2685 # the q35 chipset support native usb2, so we enable usb controller
2686 # by default for this machine type
2687 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2689 $pciaddr = print_pci_addr
("piix3", $bridges);
2690 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2693 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2694 next if !$conf->{"usb$i"};
2697 # include usb device config
2698 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2701 my $vga = $conf->{vga
};
2703 my $qxlnum = vga_conf_has_spice
($vga);
2704 $vga = 'qxl' if $qxlnum;
2707 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2708 $conf->{ostype
} eq 'win7' ||
2709 $conf->{ostype
} eq 'w2k8')) {
2716 # enable absolute mouse coordinates (needed by vnc)
2718 if (defined($conf->{tablet
})) {
2719 $tablet = $conf->{tablet
};
2721 $tablet = $defaults->{tablet
};
2722 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2723 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2726 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2729 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2730 my $d = parse_hostpci
($conf->{"hostpci$i"});
2733 my $pcie = $d->{pcie
};
2735 die "q35 machine model is not enabled" if !$q35;
2736 $pciaddr = print_pcie_addr
("hostpci$i");
2738 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2741 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2742 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2743 if ($xvga && $xvga ne '') {
2744 push @$cpuFlags, 'kvm=off';
2747 my $pcidevices = $d->{pciid
};
2748 my $multifunction = 1 if @$pcidevices > 1;
2751 foreach my $pcidevice (@$pcidevices) {
2753 my $id = "hostpci$i";
2754 $id .= ".$j" if $multifunction;
2755 my $addr = $pciaddr;
2756 $addr .= ".$j" if $multifunction;
2757 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2760 $devicestr .= "$rombar$xvga";
2761 $devicestr .= ",multifunction=on" if $multifunction;
2764 push @$devices, '-device', $devicestr;
2770 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2771 my $d = parse_usb_device
($conf->{"usb$i"});
2773 if ($d->{vendorid
} && $d->{productid
}) {
2774 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2775 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2776 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2777 } elsif ($d->{spice
}) {
2778 # usb redir support for spice
2779 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2780 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2785 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2786 if (my $path = $conf->{"serial$i"}) {
2787 if ($path eq 'socket') {
2788 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2789 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2790 push @$devices, '-device', "isa-serial,chardev=serial$i";
2792 die "no such serial device\n" if ! -c
$path;
2793 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2794 push @$devices, '-device', "isa-serial,chardev=serial$i";
2800 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2801 if (my $path = $conf->{"parallel$i"}) {
2802 die "no such parallel device\n" if ! -c
$path;
2803 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2804 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2805 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2809 my $vmname = $conf->{name
} || "vm$vmid";
2811 push @$cmd, '-name', $vmname;
2814 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2815 $sockets = $conf->{sockets
} if $conf->{sockets
};
2817 my $cores = $conf->{cores
} || 1;
2819 my $maxcpus = $sockets * $cores;
2821 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2823 my $allowed_vcpus = $cpuinfo->{cpus
};
2825 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2826 if ($allowed_vcpus < $maxcpus);
2828 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2830 push @$cmd, '-nodefaults';
2832 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2834 my $bootindex_hash = {};
2836 foreach my $o (split(//, $bootorder)) {
2837 $bootindex_hash->{$o} = $i*100;
2841 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2843 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2845 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2847 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2850 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2852 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2853 my $useLocaltime = $conf->{localtime};
2855 if (my $ost = $conf->{ostype
}) {
2856 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2858 if ($ost =~ m/^w/) { # windows
2859 $useLocaltime = 1 if !defined($conf->{localtime});
2861 # use time drift fix when acpi is enabled
2862 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2863 $tdf = 1 if !defined($conf->{tdf
});
2867 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2869 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2870 push @$cmd, '-no-hpet';
2871 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2872 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2873 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2874 push @$cpuFlags , 'hv_time' if !$nokvm;
2877 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2881 if ($ost eq 'win7' || $ost eq 'win8') {
2882 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2886 push @$rtcFlags, 'driftfix=slew' if $tdf;
2889 push @$machineFlags, 'accel=tcg';
2891 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2894 if ($machine_type) {
2895 push @$machineFlags, "type=${machine_type}";
2898 if ($conf->{startdate
}) {
2899 push @$rtcFlags, "base=$conf->{startdate}";
2900 } elsif ($useLocaltime) {
2901 push @$rtcFlags, 'base=localtime';
2904 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2905 $cpu = $conf->{cpu
} if $conf->{cpu
};
2907 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2909 push @$cpuFlags , '-x2apic'
2910 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2912 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2914 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2916 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2918 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2919 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2920 push @$cpuFlags , '-kvm_steal_time' if !$nokvm;
2923 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2925 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2927 push @$cmd, '-cpu', $cpu;
2929 my $memory = $conf->{memory
} || $defaults->{memory
};
2930 my $static_memory = 0;
2931 my $dimm_memory = 0;
2933 if ($hotplug_features->{memory
}) {
2934 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2935 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2936 $static_memory = $STATICMEM;
2937 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2938 $dimm_memory = $memory - $static_memory;
2939 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2943 $static_memory = $memory;
2944 push @$cmd, '-m', $static_memory;
2947 if ($conf->{numa
}) {
2949 my $numa_totalmemory = undef;
2950 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2951 next if !$conf->{"numa$i"};
2952 my $numa = parse_numa
($conf->{"numa$i"});
2955 die "missing numa node$i memory value\n" if !$numa->{memory
};
2956 my $numa_memory = $numa->{memory
};
2957 $numa_totalmemory += $numa_memory;
2958 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2961 my $cpus_start = $numa->{cpus
}->{start
};
2962 die "missing numa node$i cpus\n" if !defined($cpus_start);
2963 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2964 my $cpus = $cpus_start;
2965 if (defined($cpus_end)) {
2966 $cpus .= "-$cpus_end";
2967 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2971 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2972 if (defined($hostnodes_start)) {
2973 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2974 my $hostnodes = $hostnodes_start;
2975 if (defined($hostnodes_end)) {
2976 $hostnodes .= "-$hostnodes_end";
2977 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2980 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2981 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2982 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2986 my $policy = $numa->{policy
};
2987 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2988 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2991 push @$cmd, '-object', $numa_object;
2992 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2995 die "total memory for NUMA nodes must be equal to vm static memory\n"
2996 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2998 #if no custom tology, we split memory and cores across numa nodes
2999 if(!$numa_totalmemory) {
3001 my $numa_memory = ($static_memory / $sockets) . "M";
3003 for (my $i = 0; $i < $sockets; $i++) {
3005 my $cpustart = ($cores * $i);
3006 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3007 my $cpus = $cpustart;
3008 $cpus .= "-$cpuend" if $cpuend;
3010 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3011 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3016 if ($hotplug_features->{memory
}) {
3017 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3018 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3019 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3020 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3022 #if dimm_memory is not aligned to dimm map
3023 if($current_size > $memory) {
3024 $conf->{memory
} = $current_size;
3025 update_config_nolock
($vmid, $conf, 1);
3030 push @$cmd, '-S' if $conf->{freeze
};
3032 # set keyboard layout
3033 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3034 push @$cmd, '-k', $kb if $kb;
3037 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3038 #push @$cmd, '-soundhw', 'es1370';
3039 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3041 if($conf->{agent
}) {
3042 my $qgasocket = qmp_socket
($vmid, 1);
3043 my $pciaddr = print_pci_addr
("qga0", $bridges);
3044 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3045 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3046 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3053 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3054 for(my $i = 1; $i < $qxlnum; $i++){
3055 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3056 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3059 # assume other OS works like Linux
3060 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3061 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3065 my $pciaddr = print_pci_addr
("spice", $bridges);
3067 my $nodename = PVE
::INotify
::nodename
();
3068 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3069 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3071 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3073 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3074 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3075 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3078 # enable balloon by default, unless explicitly disabled
3079 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3080 $pciaddr = print_pci_addr
("balloon0", $bridges);
3081 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3084 if ($conf->{watchdog
}) {
3085 my $wdopts = parse_watchdog
($conf->{watchdog
});
3086 $pciaddr = print_pci_addr
("watchdog", $bridges);
3087 my $watchdog = $wdopts->{model
} || 'i6300esb';
3088 push @$devices, '-device', "$watchdog$pciaddr";
3089 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3093 my $scsicontroller = {};
3094 my $ahcicontroller = {};
3095 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3097 # Add iscsi initiator name if available
3098 if (my $initiator = get_initiator_name
()) {
3099 push @$devices, '-iscsi', "initiator-name=$initiator";
3102 foreach_drive
($conf, sub {
3103 my ($ds, $drive) = @_;
3105 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3106 push @$vollist, $drive->{file
};
3109 $use_virtio = 1 if $ds =~ m/^virtio/;
3111 if (drive_is_cdrom
($drive)) {
3112 if ($bootindex_hash->{d
}) {
3113 $drive->{bootindex
} = $bootindex_hash->{d
};
3114 $bootindex_hash->{d
} += 1;
3117 if ($bootindex_hash->{c
}) {
3118 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3119 $bootindex_hash->{c
} += 1;
3123 if($drive->{interface
} eq 'virtio'){
3124 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3127 if ($drive->{interface
} eq 'scsi') {
3129 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3131 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3132 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3135 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3136 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3137 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3141 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3142 $queues = ",num_queues=$drive->{queues}";
3145 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3146 $scsicontroller->{$controller}=1;
3149 if ($drive->{interface
} eq 'sata') {
3150 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3151 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3152 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3153 $ahcicontroller->{$controller}=1;
3156 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3157 push @$devices, '-drive',$drive_cmd;
3158 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3161 for (my $i = 0; $i < $MAX_NETS; $i++) {
3162 next if !$conf->{"net$i"};
3163 my $d = parse_net
($conf->{"net$i"});
3166 $use_virtio = 1 if $d->{model
} eq 'virtio';
3168 if ($bootindex_hash->{n
}) {
3169 $d->{bootindex
} = $bootindex_hash->{n
};
3170 $bootindex_hash->{n
} += 1;
3173 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3174 push @$devices, '-netdev', $netdevfull;
3176 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3177 push @$devices, '-device', $netdevicefull;
3182 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3187 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3189 while (my ($k, $v) = each %$bridges) {
3190 $pciaddr = print_pci_addr
("pci.$k");
3191 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3196 if ($conf->{args
}) {
3197 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3201 push @$cmd, @$devices;
3202 push @$cmd, '-rtc', join(',', @$rtcFlags)
3203 if scalar(@$rtcFlags);
3204 push @$cmd, '-machine', join(',', @$machineFlags)
3205 if scalar(@$machineFlags);
3206 push @$cmd, '-global', join(',', @$globalFlags)
3207 if scalar(@$globalFlags);
3209 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3214 return "${var_run_tmpdir}/$vmid.vnc";
3220 my $res = vm_mon_cmd
($vmid, 'query-spice');
3222 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3226 my ($vmid, $qga) = @_;
3227 my $sockettype = $qga ?
'qga' : 'qmp';
3228 return "${var_run_tmpdir}/$vmid.$sockettype";
3233 return "${var_run_tmpdir}/$vmid.pid";
3236 sub vm_devices_list
{
3239 my $res = vm_mon_cmd
($vmid, 'query-pci');
3241 foreach my $pcibus (@$res) {
3242 foreach my $device (@{$pcibus->{devices
}}) {
3243 next if !$device->{'qdev_id'};
3244 if ($device->{'pci_bridge'}) {
3245 $devices->{$device->{'qdev_id'}} = 1;
3246 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3247 next if !$bridge_device->{'qdev_id'};
3248 $devices->{$bridge_device->{'qdev_id'}} = 1;
3249 $devices->{$device->{'qdev_id'}}++;
3252 $devices->{$device->{'qdev_id'}} = 1;
3257 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3258 foreach my $block (@$resblock) {
3259 if($block->{device
} =~ m/^drive-(\S+)/){
3264 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3265 foreach my $mice (@$resmice) {
3266 if ($mice->{name
} eq 'QEMU HID Tablet') {
3267 $devices->{tablet
} = 1;
3276 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3278 my $q35 = machine_type_is_q35
($conf);
3280 my $devices_list = vm_devices_list
($vmid);
3281 return 1 if defined($devices_list->{$deviceid});
3283 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3285 if ($deviceid eq 'tablet') {
3287 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3289 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3291 qemu_iothread_add
($vmid, $deviceid, $device);
3293 qemu_driveadd
($storecfg, $vmid, $device);
3294 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3296 qemu_deviceadd
($vmid, $devicefull);
3297 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3299 eval { qemu_drivedel
($vmid, $deviceid); };
3304 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3307 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3308 my $pciaddr = print_pci_addr
($deviceid);
3309 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3311 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3313 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3314 qemu_iothread_add
($vmid, $deviceid, $device);
3315 $devicefull .= ",iothread=iothread-$deviceid";
3318 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3319 $devicefull .= ",num_queues=$device->{queues}";
3322 qemu_deviceadd
($vmid, $devicefull);
3323 qemu_deviceaddverify
($vmid, $deviceid);
3325 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3327 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3328 qemu_driveadd
($storecfg, $vmid, $device);
3330 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3331 eval { qemu_deviceadd
($vmid, $devicefull); };
3333 eval { qemu_drivedel
($vmid, $deviceid); };
3338 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3340 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3342 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3343 my $use_old_bios_files = undef;
3344 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3346 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3347 qemu_deviceadd
($vmid, $netdevicefull);
3348 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3350 eval { qemu_netdevdel
($vmid, $deviceid); };
3355 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3358 my $pciaddr = print_pci_addr
($deviceid);
3359 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3361 qemu_deviceadd
($vmid, $devicefull);
3362 qemu_deviceaddverify
($vmid, $deviceid);
3365 die "can't hotplug device '$deviceid'\n";
3371 # fixme: this should raise exceptions on error!
3372 sub vm_deviceunplug
{
3373 my ($vmid, $conf, $deviceid) = @_;
3375 my $devices_list = vm_devices_list
($vmid);
3376 return 1 if !defined($devices_list->{$deviceid});
3378 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3380 if ($deviceid eq 'tablet') {
3382 qemu_devicedel
($vmid, $deviceid);
3384 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3386 qemu_devicedel
($vmid, $deviceid);
3387 qemu_devicedelverify
($vmid, $deviceid);
3388 qemu_drivedel
($vmid, $deviceid);
3389 qemu_iothread_del
($conf, $vmid, $deviceid);
3391 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3393 qemu_devicedel
($vmid, $deviceid);
3394 qemu_devicedelverify
($vmid, $deviceid);
3395 qemu_iothread_del
($conf, $vmid, $deviceid);
3397 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3399 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3400 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3401 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3403 qemu_devicedel
($vmid, $deviceid);
3404 qemu_drivedel
($vmid, $deviceid);
3405 qemu_deletescsihw
($conf, $vmid, $deviceid);
3407 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3409 qemu_devicedel
($vmid, $deviceid);
3410 qemu_devicedelverify
($vmid, $deviceid);
3411 qemu_netdevdel
($vmid, $deviceid);
3414 die "can't unplug device '$deviceid'\n";
3420 sub qemu_deviceadd
{
3421 my ($vmid, $devicefull) = @_;
3423 $devicefull = "driver=".$devicefull;
3424 my %options = split(/[=,]/, $devicefull);
3426 vm_mon_cmd
($vmid, "device_add" , %options);
3429 sub qemu_devicedel
{
3430 my ($vmid, $deviceid) = @_;
3432 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3435 sub qemu_iothread_add
{
3436 my($vmid, $deviceid, $device) = @_;
3438 if ($device->{iothread
}) {
3439 my $iothreads = vm_iothreads_list
($vmid);
3440 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3444 sub qemu_iothread_del
{
3445 my($conf, $vmid, $deviceid) = @_;
3447 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3448 if ($device->{iothread
}) {
3449 my $iothreads = vm_iothreads_list
($vmid);
3450 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3454 sub qemu_objectadd
{
3455 my($vmid, $objectid, $qomtype) = @_;
3457 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3462 sub qemu_objectdel
{
3463 my($vmid, $objectid) = @_;
3465 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3471 my ($storecfg, $vmid, $device) = @_;
3473 my $drive = print_drive_full
($storecfg, $vmid, $device);
3474 $drive =~ s/\\/\\\\/g;
3475 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3477 # If the command succeeds qemu prints: "OK
"
3478 return 1 if $ret =~ m/OK/s;
3480 die "adding drive failed
: $ret\n";
3484 my($vmid, $deviceid) = @_;
3486 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3489 return 1 if $ret eq "";
3491 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3492 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3494 die "deleting drive
$deviceid failed
: $ret\n";
3497 sub qemu_deviceaddverify {
3498 my ($vmid, $deviceid) = @_;
3500 for (my $i = 0; $i <= 5; $i++) {
3501 my $devices_list = vm_devices_list($vmid);
3502 return 1 if defined($devices_list->{$deviceid});
3506 die "error on hotplug device
'$deviceid'\n";
3510 sub qemu_devicedelverify {
3511 my ($vmid, $deviceid) = @_;
3513 # need to verify that the device is correctly removed as device_del
3514 # is async and empty return is not reliable
3516 for (my $i = 0; $i <= 5; $i++) {
3517 my $devices_list = vm_devices_list($vmid);
3518 return 1 if !defined($devices_list->{$deviceid});
3522 die "error on hot-unplugging device
'$deviceid'\n";
3525 sub qemu_findorcreatescsihw {
3526 my ($storecfg, $conf, $vmid, $device) = @_;
3528 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3530 my $scsihwid="$controller_prefix$controller";
3531 my $devices_list = vm_devices_list($vmid);
3533 if(!defined($devices_list->{$scsihwid})) {
3534 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3540 sub qemu_deletescsihw {
3541 my ($conf, $vmid, $opt) = @_;
3543 my $device = parse_drive($opt, $conf->{$opt});
3545 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3546 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3550 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3552 my $devices_list = vm_devices_list($vmid);
3553 foreach my $opt (keys %{$devices_list}) {
3554 if (PVE::QemuServer::valid_drivename($opt)) {
3555 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3556 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3562 my $scsihwid="scsihw
$controller";
3564 vm_deviceunplug($vmid, $conf, $scsihwid);
3569 sub qemu_add_pci_bridge {
3570 my ($storecfg, $conf, $vmid, $device) = @_;
3576 print_pci_addr($device, $bridges);
3578 while (my ($k, $v) = each %$bridges) {
3581 return 1 if !defined($bridgeid) || $bridgeid < 1;
3583 my $bridge = "pci
.$bridgeid";
3584 my $devices_list = vm_devices_list($vmid);
3586 if (!defined($devices_list->{$bridge})) {
3587 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3593 sub qemu_set_link_status {
3594 my ($vmid, $device, $up) = @_;
3596 vm_mon_cmd($vmid, "set_link
", name => $device,
3597 up => $up ? JSON::true : JSON::false);
3600 sub qemu_netdevadd {
3601 my ($vmid, $conf, $device, $deviceid) = @_;
3603 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3604 my %options = split(/[=,]/, $netdev);
3606 vm_mon_cmd($vmid, "netdev_add
", %options);
3610 sub qemu_netdevdel {
3611 my ($vmid, $deviceid) = @_;
3613 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3616 sub qemu_cpu_hotplug {
3617 my ($vmid, $conf, $vcpus) = @_;
3620 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3621 $sockets = $conf->{sockets} if $conf->{sockets};
3622 my $cores = $conf->{cores} || 1;
3623 my $maxcpus = $sockets * $cores;
3625 $vcpus = $maxcpus if !$vcpus;
3627 die "you can
't add more vcpus than maxcpus\n"
3628 if $vcpus > $maxcpus;
3630 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3631 die "online cpu unplug is not yet possible\n"
3632 if $vcpus < $currentvcpus;
3634 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3635 die "vcpus in running vm is different than configuration\n"
3636 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3638 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3639 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3643 sub qemu_memory_hotplug {
3644 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3646 return $value if !check_running($vmid);
3648 my $memory = $conf->{memory} || $defaults->{memory};
3649 $value = $defaults->{memory} if !$value;
3650 return $value if $value == $memory;
3652 my $static_memory = $STATICMEM;
3653 my $dimm_memory = $memory - $static_memory;
3655 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3656 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3660 $sockets = $conf->{sockets} if $conf->{sockets};
3662 if($value > $memory) {
3664 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3665 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3667 return if $current_size <= $conf->{memory};
3669 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3671 eval { qemu_objectdel($vmid, "mem-
$name"); };
3675 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3677 eval { qemu_objectdel($vmid, "mem-
$name"); };
3680 #update conf after each succesful module hotplug
3681 $conf->{memory} = $current_size;
3682 update_config_nolock($vmid, $conf, 1);
3687 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3688 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3690 return if $current_size >= $conf->{memory};
3691 print "try to unplug memory dimm
$name\n";
3695 eval { qemu_devicedel($vmid, $name) };
3697 my $dimm_list = qemu_dimm_list($vmid);
3698 last if !$dimm_list->{$name};
3699 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3703 #update conf after each succesful module unplug
3704 $conf->{memory} = $current_size;
3706 eval { qemu_objectdel($vmid, "mem-
$name"); };
3707 update_config_nolock($vmid, $conf, 1);
3712 sub qemu_dimm_list {
3715 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3718 foreach my $dimm (@$dimmarray) {
3720 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3721 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3722 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3723 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3724 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3729 sub qemu_block_set_io_throttle {
3730 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3732 return if !check_running($vmid) ;
3734 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));
3738 # old code, only used to shutdown old VM after update
3740 my ($fh, $timeout) = @_;
3742 my $sel = new IO::Select;
3749 while (scalar (@ready = $sel->can_read($timeout))) {
3751 if ($count = $fh->sysread($buf, 8192)) {
3752 if ($buf =~ /^(.*)\(qemu\) $/s) {
3759 if (!defined($count)) {
3766 die "monitor
read timeout
\n" if !scalar(@ready);
3771 # old code, only used to shutdown old VM after update
3772 sub vm_monitor_command {
3773 my ($vmid, $cmdstr, $nocheck) = @_;
3778 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3780 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3782 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3783 die "unable to
connect to VM
$vmid socket - $!\n";
3787 # hack: migrate sometime blocks the monitor (when migrate_downtime
3789 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3790 $timeout = 60*60; # 1 hour
3794 my $data = __read_avail($sock, $timeout);
3796 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3797 die "got unexpected qemu monitor banner
\n";
3800 my $sel = new IO::Select;
3803 if (!scalar(my @ready = $sel->can_write($timeout))) {
3804 die "monitor
write error
- timeout
";
3807 my $fullcmd = "$cmdstr\r";
3809 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3812 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3813 die "monitor
write error
- $!";
3816 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3820 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3821 $timeout = 60*60; # 1 hour
3822 } elsif ($cmdstr =~ m/^(eject|change)/) {
3823 $timeout = 60; # note: cdrom mount command is slow
3825 if ($res = __read_avail($sock, $timeout)) {
3827 my @lines = split("\r?
\n", $res);
3829 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3831 $res = join("\n", @lines);
3839 syslog("err
", "VM
$vmid monitor command failed
- $err");
3846 sub qemu_block_resize {
3847 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3849 my $running = check_running($vmid);
3851 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3853 return if !$running;
3855 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3859 sub qemu_volume_snapshot {
3860 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3862 my $running = check_running($vmid);
3864 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3865 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3867 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3871 sub qemu_volume_snapshot_delete {
3872 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3874 my $running = check_running($vmid);
3876 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3878 return if !$running;
3880 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3883 sub set_migration_caps {
3889 "auto-converge
" => 1,
3891 "x-rdma-pin-all
" => 0,
3896 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3898 for my $supported_capability (@$supported_capabilities) {
3900 capability => $supported_capability->{capability},
3901 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3905 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3908 my $fast_plug_option = {
3917 # hotplug changes in [PENDING]
3918 # $selection hash can be used to only apply specified options, for
3919 # example: { cores => 1 } (only apply changed 'cores')
3920 # $errors ref is used to return error messages
3921 sub vmconfig_hotplug_pending {
3922 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3924 my $defaults = load_defaults();
3926 # commit values which do not have any impact on running VM first
3927 # Note: those option cannot raise errors, we we do not care about
3928 # $selection and always apply them.
3930 my $add_error = sub {
3931 my ($opt, $msg) = @_;
3932 $errors->{$opt} = "hotplug problem
- $msg";
3936 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3937 if ($fast_plug_option->{$opt}) {
3938 $conf->{$opt} = $conf->{pending}->{$opt};
3939 delete $conf->{pending}->{$opt};
3945 update_config_nolock($vmid, $conf, 1);
3946 $conf = load_config($vmid); # update/reload
3949 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3951 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3952 while (my ($opt, $force) = each %$pending_delete_hash) {
3953 next if $selection && !$selection->{$opt};
3955 if ($opt eq 'hotplug') {
3956 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3957 } elsif ($opt eq 'tablet') {
3958 die "skip
\n" if !$hotplug_features->{usb};
3959 if ($defaults->{tablet}) {
3960 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3962 vm_deviceunplug($vmid, $conf, $opt);
3964 } elsif ($opt eq 'vcpus') {
3965 die "skip
\n" if !$hotplug_features->{cpu};
3966 qemu_cpu_hotplug($vmid, $conf, undef);
3967 } elsif ($opt eq 'balloon') {
3968 # enable balloon device is not hotpluggable
3969 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3970 } elsif ($fast_plug_option->{$opt}) {
3972 } elsif ($opt =~ m/^net(\d+)$/) {
3973 die "skip
\n" if !$hotplug_features->{network};
3974 vm_deviceunplug($vmid, $conf, $opt);
3975 } elsif (valid_drivename($opt)) {
3976 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3977 vm_deviceunplug($vmid, $conf, $opt);
3978 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3979 } elsif ($opt =~ m/^memory$/) {
3980 die "skip
\n" if !$hotplug_features->{memory};
3981 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3982 } elsif ($opt eq 'cpuunits') {
3983 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3984 } elsif ($opt eq 'cpulimit') {
3985 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3991 &$add_error($opt, $err) if $err ne "skip
\n";
3993 # save new config if hotplug was successful
3994 delete $conf->{$opt};
3995 vmconfig_undelete_pending_option($conf, $opt);
3996 update_config_nolock($vmid, $conf, 1);
3997 $conf = load_config($vmid); # update/reload
4001 foreach my $opt (keys %{$conf->{pending}}) {
4002 next if $selection && !$selection->{$opt};
4003 my $value = $conf->{pending}->{$opt};
4005 if ($opt eq 'hotplug') {
4006 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4007 } elsif ($opt eq 'tablet') {
4008 die "skip
\n" if !$hotplug_features->{usb};
4010 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4011 } elsif ($value == 0) {
4012 vm_deviceunplug($vmid, $conf, $opt);
4014 } elsif ($opt eq 'vcpus') {
4015 die "skip
\n" if !$hotplug_features->{cpu};
4016 qemu_cpu_hotplug($vmid, $conf, $value);
4017 } elsif ($opt eq 'balloon') {
4018 # enable/disable balloning device is not hotpluggable
4019 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4020 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4021 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4023 # allow manual ballooning if shares is set to zero
4024 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4025 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4026 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4028 } elsif ($opt =~ m/^net(\d+)$/) {
4029 # some changes can be done without hotplug
4030 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4031 $vmid, $opt, $value);
4032 } elsif (valid_drivename($opt)) {
4033 # some changes can be done without hotplug
4034 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4035 $vmid, $opt, $value, 1);
4036 } elsif ($opt =~ m/^memory$/) { #dimms
4037 die "skip
\n" if !$hotplug_features->{memory};
4038 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4039 } elsif ($opt eq 'cpuunits') {
4040 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4041 } elsif ($opt eq 'cpulimit') {
4042 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4043 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4045 die "skip
\n"; # skip non-hot-pluggable options
4049 &$add_error($opt, $err) if $err ne "skip
\n";
4051 # save new config if hotplug was successful
4052 $conf->{$opt} = $value;
4053 delete $conf->{pending}->{$opt};
4054 update_config_nolock($vmid, $conf, 1);
4055 $conf = load_config($vmid); # update/reload
4060 sub try_deallocate_drive {
4061 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4063 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4064 my $volid = $drive->{file};
4065 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4066 my $sid = PVE::Storage::parse_volume_id($volid);
4067 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4069 # check if the disk is really unused
4070 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4071 my $path = PVE::Storage::path($storecfg, $volid);
4072 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4073 if $used_paths->{$path};
4074 PVE::Storage::vdisk_free($storecfg, $volid);
4077 # If vm is not owner of this disk remove from config
4085 sub vmconfig_delete_or_detach_drive {
4086 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4088 my $drive = parse_drive($opt, $conf->{$opt});
4090 my $rpcenv = PVE::RPCEnvironment::get();
4091 my $authuser = $rpcenv->get_user();
4094 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4095 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4097 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4101 sub vmconfig_apply_pending {
4102 my ($vmid, $conf, $storecfg) = @_;
4106 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4107 while (my ($opt, $force) = each %$pending_delete_hash) {
4108 die "internal error
" if $opt =~ m/^unused/;
4109 $conf = load_config($vmid); # update/reload
4110 if (!defined($conf->{$opt})) {
4111 vmconfig_undelete_pending_option($conf, $opt);
4112 update_config_nolock($vmid, $conf, 1);
4113 } elsif (valid_drivename($opt)) {
4114 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4115 vmconfig_undelete_pending_option($conf, $opt);
4116 delete $conf->{$opt};
4117 update_config_nolock($vmid, $conf, 1);
4119 vmconfig_undelete_pending_option($conf, $opt);
4120 delete $conf->{$opt};
4121 update_config_nolock($vmid, $conf, 1);
4125 $conf = load_config($vmid); # update/reload
4127 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4128 $conf = load_config($vmid); # update/reload
4130 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4131 # skip if nothing changed
4132 } elsif (valid_drivename($opt)) {
4133 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4134 if defined($conf->{$opt});
4135 $conf->{$opt} = $conf->{pending}->{$opt};
4137 $conf->{$opt} = $conf->{pending}->{$opt};
4140 delete $conf->{pending}->{$opt};
4141 update_config_nolock($vmid, $conf, 1);
4145 my $safe_num_ne = sub {
4148 return 0 if !defined($a) && !defined($b);
4149 return 1 if !defined($a);
4150 return 1 if !defined($b);
4155 my $safe_string_ne = sub {
4158 return 0 if !defined($a) && !defined($b);
4159 return 1 if !defined($a);
4160 return 1 if !defined($b);
4165 sub vmconfig_update_net {
4166 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4168 my $newnet = parse_net($value);
4170 if ($conf->{$opt}) {
4171 my $oldnet = parse_net($conf->{$opt});
4173 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4174 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4175 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4176 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4178 # for non online change, we try to hot-unplug
4179 die "skip
\n" if !$hotplug;
4180 vm_deviceunplug($vmid, $conf, $opt);
4183 die "internal error
" if $opt !~ m/net(\d+)/;
4184 my $iface = "tap
${vmid
}i
$1";
4186 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4187 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4190 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4191 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4192 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4193 PVE::Network::tap_unplug($iface);
4194 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4197 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4198 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4206 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4212 sub vmconfig_update_disk {
4213 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4215 # fixme: do we need force?
4217 my $drive = parse_drive($opt, $value);
4219 if ($conf->{$opt}) {
4221 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4223 my $media = $drive->{media} || 'disk';
4224 my $oldmedia = $old_drive->{media} || 'disk';
4225 die "unable to change media type
\n" if $media ne $oldmedia;
4227 if (!drive_is_cdrom($old_drive)) {
4229 if ($drive->{file} ne $old_drive->{file}) {
4231 die "skip
\n" if !$hotplug;
4233 # unplug and register as unused
4234 vm_deviceunplug($vmid, $conf, $opt);
4235 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4238 # update existing disk
4240 # skip non hotpluggable value
4241 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4242 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4243 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4244 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4249 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4250 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4251 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4252 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4253 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4254 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4255 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4256 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4257 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4258 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4259 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4260 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4262 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4263 ($drive->{mbps} || 0)*1024*1024,
4264 ($drive->{mbps_rd} || 0)*1024*1024,
4265 ($drive->{mbps_wr} || 0)*1024*1024,
4266 $drive->{iops} || 0,
4267 $drive->{iops_rd} || 0,
4268 $drive->{iops_wr} || 0,
4269 ($drive->{mbps_max} || 0)*1024*1024,
4270 ($drive->{mbps_rd_max} || 0)*1024*1024,
4271 ($drive->{mbps_wr_max} || 0)*1024*1024,
4272 $drive->{iops_max} || 0,
4273 $drive->{iops_rd_max} || 0,
4274 $drive->{iops_wr_max} || 0);
4283 if ($drive->{file} eq 'none') {
4284 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4286 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4287 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4288 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4296 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4298 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4302 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4303 $forcemachine, $spice_ticket) = @_;
4305 lock_config($vmid, sub {
4306 my $conf = load_config($vmid, $migratedfrom);
4308 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4310 check_lock($conf) if !$skiplock;
4312 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4314 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4315 vmconfig_apply_pending($vmid, $conf, $storecfg);
4316 $conf = load_config($vmid); # update/reload
4319 my $defaults = load_defaults();
4321 # set environment variable useful inside network script
4322 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4324 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4326 my $migrate_port = 0;
4329 if ($statefile eq 'tcp') {
4330 my $localip = "localhost
";
4331 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4332 my $nodename = PVE::INotify::nodename();
4333 if ($datacenterconf->{migration_unsecure}) {
4334 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4335 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4337 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4338 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4339 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4340 push @$cmd, '-incoming', $migrate_uri;
4343 push @$cmd, '-loadstate', $statefile;
4350 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4351 my $d = parse_hostpci($conf->{"hostpci
$i"});
4353 my $pcidevices = $d->{pciid};
4354 foreach my $pcidevice (@$pcidevices) {
4355 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4357 my $info = pci_device_info("0000:$pciid");
4358 die "IOMMU
not present
\n" if !check_iommu_support();
4359 die "no pci device info
for device
'$pciid'\n" if !$info;
4360 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4361 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4365 PVE::Storage::activate_volumes($storecfg, $vollist);
4367 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4370 die "start failed
: $err" if $err;
4372 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4374 if ($statefile && $statefile ne 'tcp') {
4375 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4379 if ($migratedfrom) {
4382 set_migration_caps($vmid);
4387 print "spice listens on port
$spice_port\n";
4388 if ($spice_ticket) {
4389 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4390 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4396 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4397 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4398 if $conf->{balloon};
4401 foreach my $opt (keys %$conf) {
4402 next if $opt !~ m/^net\d+$/;
4403 my $nicconf = parse_net($conf->{$opt});
4404 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4408 vm_mon_cmd_nocheck($vmid, 'qom-set',
4409 path => "machine
/peripheral/balloon0
",
4410 property => "guest-stats-polling-interval
",
4411 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4417 my ($vmid, $execute, %params) = @_;
4419 my $cmd = { execute => $execute, arguments => \%params };
4420 vm_qmp_command($vmid, $cmd);
4423 sub vm_mon_cmd_nocheck {
4424 my ($vmid, $execute, %params) = @_;
4426 my $cmd = { execute => $execute, arguments => \%params };
4427 vm_qmp_command($vmid, $cmd, 1);
4430 sub vm_qmp_command {
4431 my ($vmid, $cmd, $nocheck) = @_;
4436 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4437 $timeout = $cmd->{arguments}->{timeout};
4438 delete $cmd->{arguments}->{timeout};
4442 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4443 my $sname = qmp_socket($vmid);
4444 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4445 my $qmpclient = PVE::QMPClient->new();
4447 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4448 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4449 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4450 if scalar(%{$cmd->{arguments}});
4451 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4453 die "unable to open monitor socket\n";
4457 syslog("err", "VM $vmid qmp command failed - $err");
4464 sub vm_human_monitor_command {
4465 my ($vmid, $cmdline) = @_;
4470 execute => 'human-monitor-command
',
4471 arguments => { 'command-line
' => $cmdline},
4474 return vm_qmp_command($vmid, $cmd);
4477 sub vm_commandline {
4478 my ($storecfg, $vmid) = @_;
4480 my $conf = load_config($vmid);
4482 my $defaults = load_defaults();
4484 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4486 return join(' ', @$cmd);
4490 my ($vmid, $skiplock) = @_;
4492 lock_config($vmid, sub {
4494 my $conf = load_config($vmid);
4496 check_lock($conf) if !$skiplock;
4498 vm_mon_cmd($vmid, "system_reset");
4502 sub get_vm_volumes {
4506 foreach_volid($conf, sub {
4507 my ($volid, $is_cdrom) = @_;
4509 return if $volid =~ m|^/|;
4511 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4514 push @$vollist, $volid;
4520 sub vm_stop_cleanup {
4521 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4526 my $vollist = get_vm_volumes($conf);
4527 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4530 foreach my $ext (qw(mon qmp pid vnc qga)) {
4531 unlink "/var/run/qemu-server/${vmid}.$ext";
4534 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4536 warn $@ if $@; # avoid errors - just warn
4539 # Note: use $nockeck to skip tests if VM configuration file exists.
4540 # We need that when migration VMs to other nodes (files already moved)
4541 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4543 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4545 $force = 1 if !defined($force) && !$shutdown;
4548 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4549 kill 15, $pid if $pid;
4550 my $conf = load_config
($vmid, $migratedfrom);
4551 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4555 lock_config
($vmid, sub {
4557 my $pid = check_running
($vmid, $nocheck);
4562 $conf = load_config
($vmid);
4563 check_lock
($conf) if !$skiplock;
4564 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4565 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4566 $timeout = $opts->{down
} if $opts->{down
};
4570 $timeout = 60 if !defined($timeout);
4574 if (defined($conf) && $conf->{agent
}) {
4575 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4577 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4580 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4587 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4592 if ($count >= $timeout) {
4594 warn "VM still running - terminating now with SIGTERM\n";
4597 die "VM quit/powerdown failed - got timeout\n";
4600 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4605 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4608 die "VM quit/powerdown failed\n";
4616 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4621 if ($count >= $timeout) {
4622 warn "VM still running - terminating now with SIGKILL\n";
4627 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4632 my ($vmid, $skiplock) = @_;
4634 lock_config
($vmid, sub {
4636 my $conf = load_config
($vmid);
4638 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4640 vm_mon_cmd
($vmid, "stop");
4645 my ($vmid, $skiplock, $nocheck) = @_;
4647 lock_config
($vmid, sub {
4651 my $conf = load_config
($vmid);
4653 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4655 vm_mon_cmd
($vmid, "cont");
4658 vm_mon_cmd_nocheck
($vmid, "cont");
4664 my ($vmid, $skiplock, $key) = @_;
4666 lock_config
($vmid, sub {
4668 my $conf = load_config
($vmid);
4670 # there is no qmp command, so we use the human monitor command
4671 vm_human_monitor_command
($vmid, "sendkey $key");
4676 my ($storecfg, $vmid, $skiplock) = @_;
4678 lock_config
($vmid, sub {
4680 my $conf = load_config
($vmid);
4682 check_lock
($conf) if !$skiplock;
4684 if (!check_running
($vmid)) {
4685 destroy_vm
($storecfg, $vmid);
4687 die "VM $vmid is running - destroy failed\n";
4695 my ($filename, $buf) = @_;
4697 my $fh = IO
::File-
>new($filename, "w");
4698 return undef if !$fh;
4700 my $res = print $fh $buf;
4707 sub pci_device_info
{
4712 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4713 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4715 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4716 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4718 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4719 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4721 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4722 return undef if !defined($product) || $product !~ s/^0x//;
4727 product
=> $product,
4733 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4742 my $name = $dev->{name
};
4744 my $fn = "$pcisysfs/devices/$name/reset";
4746 return file_write
($fn, "1");
4749 sub pci_dev_bind_to_vfio
{
4752 my $name = $dev->{name
};
4754 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4756 if (!-d
$vfio_basedir) {
4757 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4759 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4761 my $testdir = "$vfio_basedir/$name";
4762 return 1 if -d
$testdir;
4764 my $data = "$dev->{vendor} $dev->{product}";
4765 return undef if !file_write
("$vfio_basedir/new_id", $data);
4767 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4768 if (!file_write
($fn, $name)) {
4769 return undef if -f
$fn;
4772 $fn = "$vfio_basedir/bind";
4773 if (! -d
$testdir) {
4774 return undef if !file_write
($fn, $name);
4780 sub pci_dev_group_bind_to_vfio
{
4783 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4785 if (!-d
$vfio_basedir) {
4786 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4788 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4790 # get IOMMU group devices
4791 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4792 my @devs = grep /^0000:/, readdir($D);
4795 foreach my $pciid (@devs) {
4796 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4798 # pci bridges, switches or root ports are not supported
4799 # they have a pci_bus subdirectory so skip them
4800 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4802 my $info = pci_device_info
($1);
4803 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4809 sub print_pci_addr
{
4810 my ($id, $bridges) = @_;
4814 piix3
=> { bus
=> 0, addr
=> 1 },
4815 #addr2 : first videocard
4816 balloon0
=> { bus
=> 0, addr
=> 3 },
4817 watchdog
=> { bus
=> 0, addr
=> 4 },
4818 scsihw0
=> { bus
=> 0, addr
=> 5 },
4819 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4820 scsihw1
=> { bus
=> 0, addr
=> 6 },
4821 ahci0
=> { bus
=> 0, addr
=> 7 },
4822 qga0
=> { bus
=> 0, addr
=> 8 },
4823 spice
=> { bus
=> 0, addr
=> 9 },
4824 virtio0
=> { bus
=> 0, addr
=> 10 },
4825 virtio1
=> { bus
=> 0, addr
=> 11 },
4826 virtio2
=> { bus
=> 0, addr
=> 12 },
4827 virtio3
=> { bus
=> 0, addr
=> 13 },
4828 virtio4
=> { bus
=> 0, addr
=> 14 },
4829 virtio5
=> { bus
=> 0, addr
=> 15 },
4830 hostpci0
=> { bus
=> 0, addr
=> 16 },
4831 hostpci1
=> { bus
=> 0, addr
=> 17 },
4832 net0
=> { bus
=> 0, addr
=> 18 },
4833 net1
=> { bus
=> 0, addr
=> 19 },
4834 net2
=> { bus
=> 0, addr
=> 20 },
4835 net3
=> { bus
=> 0, addr
=> 21 },
4836 net4
=> { bus
=> 0, addr
=> 22 },
4837 net5
=> { bus
=> 0, addr
=> 23 },
4838 vga1
=> { bus
=> 0, addr
=> 24 },
4839 vga2
=> { bus
=> 0, addr
=> 25 },
4840 vga3
=> { bus
=> 0, addr
=> 26 },
4841 hostpci2
=> { bus
=> 0, addr
=> 27 },
4842 hostpci3
=> { bus
=> 0, addr
=> 28 },
4843 #addr29 : usb-host (pve-usb.cfg)
4844 'pci.1' => { bus
=> 0, addr
=> 30 },
4845 'pci.2' => { bus
=> 0, addr
=> 31 },
4846 'net6' => { bus
=> 1, addr
=> 1 },
4847 'net7' => { bus
=> 1, addr
=> 2 },
4848 'net8' => { bus
=> 1, addr
=> 3 },
4849 'net9' => { bus
=> 1, addr
=> 4 },
4850 'net10' => { bus
=> 1, addr
=> 5 },
4851 'net11' => { bus
=> 1, addr
=> 6 },
4852 'net12' => { bus
=> 1, addr
=> 7 },
4853 'net13' => { bus
=> 1, addr
=> 8 },
4854 'net14' => { bus
=> 1, addr
=> 9 },
4855 'net15' => { bus
=> 1, addr
=> 10 },
4856 'net16' => { bus
=> 1, addr
=> 11 },
4857 'net17' => { bus
=> 1, addr
=> 12 },
4858 'net18' => { bus
=> 1, addr
=> 13 },
4859 'net19' => { bus
=> 1, addr
=> 14 },
4860 'net20' => { bus
=> 1, addr
=> 15 },
4861 'net21' => { bus
=> 1, addr
=> 16 },
4862 'net22' => { bus
=> 1, addr
=> 17 },
4863 'net23' => { bus
=> 1, addr
=> 18 },
4864 'net24' => { bus
=> 1, addr
=> 19 },
4865 'net25' => { bus
=> 1, addr
=> 20 },
4866 'net26' => { bus
=> 1, addr
=> 21 },
4867 'net27' => { bus
=> 1, addr
=> 22 },
4868 'net28' => { bus
=> 1, addr
=> 23 },
4869 'net29' => { bus
=> 1, addr
=> 24 },
4870 'net30' => { bus
=> 1, addr
=> 25 },
4871 'net31' => { bus
=> 1, addr
=> 26 },
4872 'virtio6' => { bus
=> 2, addr
=> 1 },
4873 'virtio7' => { bus
=> 2, addr
=> 2 },
4874 'virtio8' => { bus
=> 2, addr
=> 3 },
4875 'virtio9' => { bus
=> 2, addr
=> 4 },
4876 'virtio10' => { bus
=> 2, addr
=> 5 },
4877 'virtio11' => { bus
=> 2, addr
=> 6 },
4878 'virtio12' => { bus
=> 2, addr
=> 7 },
4879 'virtio13' => { bus
=> 2, addr
=> 8 },
4880 'virtio14' => { bus
=> 2, addr
=> 9 },
4881 'virtio15' => { bus
=> 2, addr
=> 10 },
4882 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4883 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4884 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4885 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4886 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4887 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4888 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4889 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4890 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4891 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4892 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4893 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4894 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4895 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4896 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4897 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4898 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4899 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4900 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4901 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4902 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4903 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4904 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4905 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4906 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4907 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4908 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4909 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4910 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4911 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4912 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4916 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4917 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4918 my $bus = $devices->{$id}->{bus
};
4919 $res = ",bus=pci.$bus,addr=$addr";
4920 $bridges->{$bus} = 1 if $bridges;
4926 sub print_pcie_addr
{
4931 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4932 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4933 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4934 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4937 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4938 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4939 my $bus = $devices->{$id}->{bus
};
4940 $res = ",bus=$bus,addr=$addr";
4946 # vzdump restore implementaion
4948 sub tar_archive_read_firstfile
{
4949 my $archive = shift;
4951 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4953 # try to detect archive type first
4954 my $pid = open (TMP
, "tar tf '$archive'|") ||
4955 die "unable to open file '$archive'\n";
4956 my $firstfile = <TMP
>;
4960 die "ERROR: archive contaions no data\n" if !$firstfile;
4966 sub tar_restore_cleanup
{
4967 my ($storecfg, $statfile) = @_;
4969 print STDERR
"starting cleanup\n";
4971 if (my $fd = IO
::File-
>new($statfile, "r")) {
4972 while (defined(my $line = <$fd>)) {
4973 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4976 if ($volid =~ m
|^/|) {
4977 unlink $volid || die 'unlink failed\n';
4979 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4981 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4983 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4985 print STDERR
"unable to parse line in statfile - $line";
4992 sub restore_archive
{
4993 my ($archive, $vmid, $user, $opts) = @_;
4995 my $format = $opts->{format
};
4998 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4999 $format = 'tar' if !$format;
5001 } elsif ($archive =~ m/\.tar$/) {
5002 $format = 'tar' if !$format;
5003 } elsif ($archive =~ m/.tar.lzo$/) {
5004 $format = 'tar' if !$format;
5006 } elsif ($archive =~ m/\.vma$/) {
5007 $format = 'vma' if !$format;
5008 } elsif ($archive =~ m/\.vma\.gz$/) {
5009 $format = 'vma' if !$format;
5011 } elsif ($archive =~ m/\.vma\.lzo$/) {
5012 $format = 'vma' if !$format;
5015 $format = 'vma' if !$format; # default
5018 # try to detect archive format
5019 if ($format eq 'tar') {
5020 return restore_tar_archive
($archive, $vmid, $user, $opts);
5022 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5026 sub restore_update_config_line
{
5027 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5029 return if $line =~ m/^\#qmdump\#/;
5030 return if $line =~ m/^\#vzdump\#/;
5031 return if $line =~ m/^lock:/;
5032 return if $line =~ m/^unused\d+:/;
5033 return if $line =~ m/^parent:/;
5034 return if $line =~ m/^template:/; # restored VM is never a template
5036 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5037 # try to convert old 1.X settings
5038 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5039 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5040 my ($model, $macaddr) = split(/\=/, $devconfig);
5041 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5044 bridge
=> "vmbr$ind",
5045 macaddr
=> $macaddr,
5047 my $netstr = print_net
($net);
5049 print $outfd "net$cookie->{netcount}: $netstr\n";
5050 $cookie->{netcount
}++;
5052 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5053 my ($id, $netstr) = ($1, $2);
5054 my $net = parse_net
($netstr);
5055 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5056 $netstr = print_net
($net);
5057 print $outfd "$id: $netstr\n";
5058 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5061 if ($line =~ m/backup=no/) {
5062 print $outfd "#$line";
5063 } elsif ($virtdev && $map->{$virtdev}) {
5064 my $di = parse_drive
($virtdev, $value);
5065 delete $di->{format
}; # format can change on restore
5066 $di->{file
} = $map->{$virtdev};
5067 $value = print_drive
($vmid, $di);
5068 print $outfd "$virtdev: $value\n";
5078 my ($cfg, $vmid) = @_;
5080 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5082 my $volid_hash = {};
5083 foreach my $storeid (keys %$info) {
5084 foreach my $item (@{$info->{$storeid}}) {
5085 next if !($item->{volid
} && $item->{size
});
5086 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5087 $volid_hash->{$item->{volid
}} = $item;
5094 sub get_used_paths
{
5095 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5099 my $scan_config = sub {
5100 my ($cref, $snapname) = @_;
5102 foreach my $key (keys %$cref) {
5103 my $value = $cref->{$key};
5104 if (valid_drivename
($key)) {
5105 next if $skip_drive && $key eq $skip_drive;
5106 my $drive = parse_drive
($key, $value);
5107 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5108 if ($drive->{file
} =~ m!^/!) {
5109 $used_path->{$drive->{file
}}++; # = 1;
5111 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5113 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5115 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5116 $used_path->{$path}++; # = 1;
5122 &$scan_config($conf);
5126 if ($scan_snapshots) {
5127 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5128 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5135 sub update_disksize
{
5136 my ($vmid, $conf, $volid_hash) = @_;
5142 # Note: it is allowed to define multiple storages with same path (alias), so
5143 # we need to check both 'volid' and real 'path' (two different volid can point
5144 # to the same path).
5149 foreach my $opt (keys %$conf) {
5150 if (valid_drivename
($opt)) {
5151 my $drive = parse_drive
($opt, $conf->{$opt});
5152 my $volid = $drive->{file
};
5155 $used->{$volid} = 1;
5156 if ($volid_hash->{$volid} &&
5157 (my $path = $volid_hash->{$volid}->{path
})) {
5158 $usedpath->{$path} = 1;
5161 next if drive_is_cdrom
($drive);
5162 next if !$volid_hash->{$volid};
5164 $drive->{size
} = $volid_hash->{$volid}->{size
};
5165 my $new = print_drive
($vmid, $drive);
5166 if ($new ne $conf->{$opt}) {
5168 $conf->{$opt} = $new;
5173 # remove 'unusedX' entry if volume is used
5174 foreach my $opt (keys %$conf) {
5175 next if $opt !~ m/^unused\d+$/;
5176 my $volid = $conf->{$opt};
5177 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5178 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5180 delete $conf->{$opt};
5184 foreach my $volid (sort keys %$volid_hash) {
5185 next if $volid =~ m/vm-$vmid-state-/;
5186 next if $used->{$volid};
5187 my $path = $volid_hash->{$volid}->{path
};
5188 next if !$path; # just to be sure
5189 next if $usedpath->{$path};
5191 add_unused_volume
($conf, $volid);
5192 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5199 my ($vmid, $nolock) = @_;
5201 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5203 my $volid_hash = scan_volids
($cfg, $vmid);
5205 my $updatefn = sub {
5208 my $conf = load_config
($vmid);
5213 foreach my $volid (keys %$volid_hash) {
5214 my $info = $volid_hash->{$volid};
5215 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5218 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5220 update_config_nolock
($vmid, $conf, 1) if $changes;
5223 if (defined($vmid)) {
5227 lock_config
($vmid, $updatefn, $vmid);
5230 my $vmlist = config_list
();
5231 foreach my $vmid (keys %$vmlist) {
5235 lock_config
($vmid, $updatefn, $vmid);
5241 sub restore_vma_archive
{
5242 my ($archive, $vmid, $user, $opts, $comp) = @_;
5244 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5245 my $readfrom = $archive;
5250 my $qarchive = PVE
::Tools
::shellquote
($archive);
5251 if ($comp eq 'gzip') {
5252 $uncomp = "zcat $qarchive|";
5253 } elsif ($comp eq 'lzop') {
5254 $uncomp = "lzop -d -c $qarchive|";
5256 die "unknown compression method '$comp'\n";
5261 my $tmpdir = "/var/tmp/vzdumptmp$$";
5264 # disable interrupts (always do cleanups)
5265 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5266 warn "got interrupt - ignored\n";
5269 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5270 POSIX
::mkfifo
($mapfifo, 0600);
5273 my $openfifo = sub {
5274 open($fifofh, '>', $mapfifo) || die $!;
5277 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5284 my $rpcenv = PVE
::RPCEnvironment
::get
();
5286 my $conffile = config_file
($vmid);
5287 my $tmpfn = "$conffile.$$.tmp";
5289 # Note: $oldconf is undef if VM does not exists
5290 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5292 my $print_devmap = sub {
5293 my $virtdev_hash = {};
5295 my $cfgfn = "$tmpdir/qemu-server.conf";
5297 # we can read the config - that is already extracted
5298 my $fh = IO
::File-
>new($cfgfn, "r") ||
5299 "unable to read qemu-server.conf - $!\n";
5301 while (defined(my $line = <$fh>)) {
5302 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5303 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5304 die "archive does not contain data for drive '$virtdev'\n"
5305 if !$devinfo->{$devname};
5306 if (defined($opts->{storage
})) {
5307 $storeid = $opts->{storage
} || 'local';
5308 } elsif (!$storeid) {
5311 $format = 'raw' if !$format;
5312 $devinfo->{$devname}->{devname
} = $devname;
5313 $devinfo->{$devname}->{virtdev
} = $virtdev;
5314 $devinfo->{$devname}->{format
} = $format;
5315 $devinfo->{$devname}->{storeid
} = $storeid;
5317 # check permission on storage
5318 my $pool = $opts->{pool
}; # todo: do we need that?
5319 if ($user ne 'root@pam') {
5320 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5323 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5327 foreach my $devname (keys %$devinfo) {
5328 die "found no device mapping information for device '$devname'\n"
5329 if !$devinfo->{$devname}->{virtdev
};
5332 my $cfg = cfs_read_file
('storage.cfg');
5334 # create empty/temp config
5336 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5337 foreach_drive
($oldconf, sub {
5338 my ($ds, $drive) = @_;
5340 return if drive_is_cdrom
($drive);
5342 my $volid = $drive->{file
};
5344 return if !$volid || $volid =~ m
|^/|;
5346 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5347 return if !$path || !$owner || ($owner != $vmid);
5349 # Note: only delete disk we want to restore
5350 # other volumes will become unused
5351 if ($virtdev_hash->{$ds}) {
5352 PVE
::Storage
::vdisk_free
($cfg, $volid);
5358 foreach my $virtdev (sort keys %$virtdev_hash) {
5359 my $d = $virtdev_hash->{$virtdev};
5360 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5361 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5363 # test if requested format is supported
5364 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5365 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5366 $d->{format
} = $defFormat if !$supported;
5368 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5369 $d->{format
}, undef, $alloc_size);
5370 print STDERR
"new volume ID is '$volid'\n";
5371 $d->{volid
} = $volid;
5372 my $path = PVE
::Storage
::path
($cfg, $volid);
5374 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5376 my $write_zeros = 1;
5377 # fixme: what other storages types initialize volumes with zero?
5378 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5379 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5383 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5385 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5386 $map->{$virtdev} = $volid;
5389 $fh->seek(0, 0) || die "seek failed - $!\n";
5391 my $outfd = new IO
::File
($tmpfn, "w") ||
5392 die "unable to write config for VM $vmid\n";
5394 my $cookie = { netcount
=> 0 };
5395 while (defined(my $line = <$fh>)) {
5396 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5405 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5406 die "interrupted by signal\n";
5408 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5410 $oldtimeout = alarm($timeout);
5417 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5418 my ($dev_id, $size, $devname) = ($1, $2, $3);
5419 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5420 } elsif ($line =~ m/^CTIME: /) {
5421 # we correctly received the vma config, so we can disable
5422 # the timeout now for disk allocation (set to 10 minutes, so
5423 # that we always timeout if something goes wrong)
5426 print $fifofh "done\n";
5427 my $tmp = $oldtimeout || 0;
5428 $oldtimeout = undef;
5434 print "restore vma archive: $cmd\n";
5435 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5439 alarm($oldtimeout) if $oldtimeout;
5442 foreach my $devname (keys %$devinfo) {
5443 my $volid = $devinfo->{$devname}->{volid
};
5444 push @$vollist, $volid if $volid;
5447 my $cfg = cfs_read_file
('storage.cfg');
5448 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5456 foreach my $devname (keys %$devinfo) {
5457 my $volid = $devinfo->{$devname}->{volid
};
5460 if ($volid =~ m
|^/|) {
5461 unlink $volid || die 'unlink failed\n';
5463 PVE
::Storage
::vdisk_free
($cfg, $volid);
5465 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5467 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5474 rename($tmpfn, $conffile) ||
5475 die "unable to commit configuration file '$conffile'\n";
5477 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5479 eval { rescan
($vmid, 1); };
5483 sub restore_tar_archive
{
5484 my ($archive, $vmid, $user, $opts) = @_;
5486 if ($archive ne '-') {
5487 my $firstfile = tar_archive_read_firstfile
($archive);
5488 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5489 if $firstfile ne 'qemu-server.conf';
5492 my $storecfg = cfs_read_file
('storage.cfg');
5494 # destroy existing data - keep empty config
5495 my $vmcfgfn = config_file
($vmid);
5496 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5498 my $tocmd = "/usr/lib/qemu-server/qmextract";
5500 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5501 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5502 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5503 $tocmd .= ' --info' if $opts->{info
};
5505 # tar option "xf" does not autodetect compression when read from STDIN,
5506 # so we pipe to zcat
5507 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5508 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5510 my $tmpdir = "/var/tmp/vzdumptmp$$";
5513 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5514 local $ENV{VZDUMP_VMID
} = $vmid;
5515 local $ENV{VZDUMP_USER
} = $user;
5517 my $conffile = config_file
($vmid);
5518 my $tmpfn = "$conffile.$$.tmp";
5520 # disable interrupts (always do cleanups)
5521 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5522 print STDERR
"got interrupt - ignored\n";
5527 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5528 die "interrupted by signal\n";
5531 if ($archive eq '-') {
5532 print "extracting archive from STDIN\n";
5533 run_command
($cmd, input
=> "<&STDIN");
5535 print "extracting archive '$archive'\n";
5539 return if $opts->{info
};
5543 my $statfile = "$tmpdir/qmrestore.stat";
5544 if (my $fd = IO
::File-
>new($statfile, "r")) {
5545 while (defined (my $line = <$fd>)) {
5546 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5547 $map->{$1} = $2 if $1;
5549 print STDERR
"unable to parse line in statfile - $line\n";
5555 my $confsrc = "$tmpdir/qemu-server.conf";
5557 my $srcfd = new IO
::File
($confsrc, "r") ||
5558 die "unable to open file '$confsrc'\n";
5560 my $outfd = new IO
::File
($tmpfn, "w") ||
5561 die "unable to write config for VM $vmid\n";
5563 my $cookie = { netcount
=> 0 };
5564 while (defined (my $line = <$srcfd>)) {
5565 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5577 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5584 rename $tmpfn, $conffile ||
5585 die "unable to commit configuration file '$conffile'\n";
5587 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5589 eval { rescan
($vmid, 1); };
5594 # Internal snapshots
5596 # NOTE: Snapshot create/delete involves several non-atomic
5597 # action, and can take a long time.
5598 # So we try to avoid locking the file and use 'lock' variable
5599 # inside the config file instead.
5601 my $snapshot_copy_config = sub {
5602 my ($source, $dest) = @_;
5604 foreach my $k (keys %$source) {
5605 next if $k eq 'snapshots';
5606 next if $k eq 'snapstate';
5607 next if $k eq 'snaptime';
5608 next if $k eq 'vmstate';
5609 next if $k eq 'lock';
5610 next if $k eq 'digest';
5611 next if $k eq 'description';
5612 next if $k =~ m/^unused\d+$/;
5614 $dest->{$k} = $source->{$k};
5618 my $snapshot_apply_config = sub {
5619 my ($conf, $snap) = @_;
5621 # copy snapshot list
5623 snapshots
=> $conf->{snapshots
},
5626 # keep description and list of unused disks
5627 foreach my $k (keys %$conf) {
5628 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5629 $newconf->{$k} = $conf->{$k};
5632 &$snapshot_copy_config($snap, $newconf);
5637 sub foreach_writable_storage
{
5638 my ($conf, $func) = @_;
5642 foreach my $ds (keys %$conf) {
5643 next if !valid_drivename
($ds);
5645 my $drive = parse_drive
($ds, $conf->{$ds});
5647 next if drive_is_cdrom
($drive);
5649 my $volid = $drive->{file
};
5651 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5652 $sidhash->{$sid} = $sid if $sid;
5655 foreach my $sid (sort keys %$sidhash) {
5660 my $alloc_vmstate_volid = sub {
5661 my ($storecfg, $vmid, $conf, $snapname) = @_;
5663 # Note: we try to be smart when selecting a $target storage
5667 # search shared storage first
5668 foreach_writable_storage
($conf, sub {
5670 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5671 return if !$scfg->{shared
};
5673 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5677 # now search local storage
5678 foreach_writable_storage
($conf, sub {
5680 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5681 return if $scfg->{shared
};
5683 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5687 $target = 'local' if !$target;
5689 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5690 # we abort live save after $conf->{memory}, so we need at max twice that space
5691 my $size = $conf->{memory
}*2 + $driver_state_size;
5693 my $name = "vm-$vmid-state-$snapname";
5694 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5695 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5696 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5701 my $snapshot_prepare = sub {
5702 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5706 my $updatefn = sub {
5708 my $conf = load_config
($vmid);
5710 die "you can't take a snapshot if it's a template\n"
5711 if is_template
($conf);
5715 $conf->{lock} = 'snapshot';
5717 die "snapshot name '$snapname' already used\n"
5718 if defined($conf->{snapshots
}->{$snapname});
5720 my $storecfg = PVE
::Storage
::config
();
5721 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5723 $snap = $conf->{snapshots
}->{$snapname} = {};
5725 if ($save_vmstate && check_running
($vmid)) {
5726 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5729 &$snapshot_copy_config($conf, $snap);
5731 $snap->{snapstate
} = "prepare";
5732 $snap->{snaptime
} = time();
5733 $snap->{description
} = $comment if $comment;
5735 # always overwrite machine if we save vmstate. This makes sure we
5736 # can restore it later using correct machine type
5737 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5739 update_config_nolock
($vmid, $conf, 1);
5742 lock_config
($vmid, $updatefn);
5747 my $snapshot_commit = sub {
5748 my ($vmid, $snapname) = @_;
5750 my $updatefn = sub {
5752 my $conf = load_config
($vmid);
5754 die "missing snapshot lock\n"
5755 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5757 my $has_machine_config = defined($conf->{machine
});
5759 my $snap = $conf->{snapshots
}->{$snapname};
5761 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5763 die "wrong snapshot state\n"
5764 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5766 delete $snap->{snapstate
};
5767 delete $conf->{lock};
5769 my $newconf = &$snapshot_apply_config($conf, $snap);
5771 delete $newconf->{machine
} if !$has_machine_config;
5773 $newconf->{parent
} = $snapname;
5775 update_config_nolock
($vmid, $newconf, 1);
5778 lock_config
($vmid, $updatefn);
5781 sub snapshot_rollback
{
5782 my ($vmid, $snapname) = @_;
5786 my $storecfg = PVE
::Storage
::config
();
5788 my $conf = load_config
($vmid);
5790 my $get_snapshot_config = sub {
5792 die "you can't rollback if vm is a template\n" if is_template
($conf);
5794 my $res = $conf->{snapshots
}->{$snapname};
5796 die "snapshot '$snapname' does not exist\n" if !defined($res);
5801 my $snap = &$get_snapshot_config();
5803 foreach_drive
($snap, sub {
5804 my ($ds, $drive) = @_;
5806 return if drive_is_cdrom
($drive);
5808 my $volid = $drive->{file
};
5810 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5813 my $updatefn = sub {
5815 $conf = load_config
($vmid);
5817 $snap = &$get_snapshot_config();
5819 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5820 if $snap->{snapstate
};
5824 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5827 die "unable to rollback vm $vmid: vm is running\n"
5828 if check_running
($vmid);
5831 $conf->{lock} = 'rollback';
5833 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5834 delete $conf->{lock};
5840 my $has_machine_config = defined($conf->{machine
});
5842 # copy snapshot config to current config
5843 $conf = &$snapshot_apply_config($conf, $snap);
5844 $conf->{parent
} = $snapname;
5846 # Note: old code did not store 'machine', so we try to be smart
5847 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5848 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5849 # we remove the 'machine' configuration if not explicitly specified
5850 # in the original config.
5851 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5854 update_config_nolock
($vmid, $conf, 1);
5856 if (!$prepare && $snap->{vmstate
}) {
5857 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5858 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5862 lock_config
($vmid, $updatefn);
5864 foreach_drive
($snap, sub {
5865 my ($ds, $drive) = @_;
5867 return if drive_is_cdrom
($drive);
5869 my $volid = $drive->{file
};
5870 my $device = "drive-$ds";
5872 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5876 lock_config
($vmid, $updatefn);
5879 my $savevm_wait = sub {
5883 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5884 if (!$stat->{status
}) {
5885 die "savevm not active\n";
5886 } elsif ($stat->{status
} eq 'active') {
5889 } elsif ($stat->{status
} eq 'completed') {
5892 die "query-savevm returned status '$stat->{status}'\n";
5897 sub do_snapshots_with_qemu
{
5898 my ($storecfg, $volid) = @_;
5900 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5902 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5903 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5907 if ($volid =~ m/\.(qcow2|qed)$/){
5914 sub snapshot_create
{
5915 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5917 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5919 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5921 my $config = load_config
($vmid);
5923 my $running = check_running
($vmid);
5925 my $freezefs = $running && $config->{agent
};
5926 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5931 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5932 warn "guest-fsfreeze-freeze problems - $@" if $@;
5936 # create internal snapshots of all drives
5938 my $storecfg = PVE
::Storage
::config
();
5941 if ($snap->{vmstate
}) {
5942 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5943 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5944 &$savevm_wait($vmid);
5946 vm_mon_cmd
($vmid, "savevm-start");
5950 foreach_drive
($snap, sub {
5951 my ($ds, $drive) = @_;
5953 return if drive_is_cdrom
($drive);
5955 my $volid = $drive->{file
};
5956 my $device = "drive-$ds";
5958 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5959 $drivehash->{$ds} = 1;
5965 eval { vm_mon_cmd
($vmid, "savevm-end") };
5969 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5970 warn "guest-fsfreeze-thaw problems - $@" if $@;
5973 # savevm-end is async, we need to wait
5975 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5976 if (!$stat->{bytes
}) {
5979 print "savevm not yet finished\n";
5987 warn "snapshot create failed: starting cleanup\n";
5988 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5993 &$snapshot_commit($vmid, $snapname);
5996 # Note: $drivehash is only set when called from snapshot_create.
5997 sub snapshot_delete
{
5998 my ($vmid, $snapname, $force, $drivehash) = @_;
6005 my $unlink_parent = sub {
6006 my ($confref, $new_parent) = @_;
6008 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6010 $confref->{parent
} = $new_parent;
6012 delete $confref->{parent
};
6017 my $updatefn = sub {
6018 my ($remove_drive) = @_;
6020 my $conf = load_config
($vmid);
6024 die "you can't delete a snapshot if vm is a template\n"
6025 if is_template
($conf);
6028 $snap = $conf->{snapshots
}->{$snapname};
6030 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6032 # remove parent refs
6034 &$unlink_parent($conf, $snap->{parent
});
6035 foreach my $sn (keys %{$conf->{snapshots
}}) {
6036 next if $sn eq $snapname;
6037 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6041 if ($remove_drive) {
6042 if ($remove_drive eq 'vmstate') {
6043 delete $snap->{$remove_drive};
6045 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6046 my $volid = $drive->{file
};
6047 delete $snap->{$remove_drive};
6048 add_unused_volume
($conf, $volid);
6053 $snap->{snapstate
} = 'delete';
6055 delete $conf->{snapshots
}->{$snapname};
6056 delete $conf->{lock} if $drivehash;
6057 foreach my $volid (@$unused) {
6058 add_unused_volume
($conf, $volid);
6062 update_config_nolock
($vmid, $conf, 1);
6065 lock_config
($vmid, $updatefn);
6067 # now remove vmstate file
6069 my $storecfg = PVE
::Storage
::config
();
6071 if ($snap->{vmstate
}) {
6072 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6074 die $err if !$force;
6077 # save changes (remove vmstate from snapshot)
6078 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6081 # now remove all internal snapshots
6082 foreach_drive
($snap, sub {
6083 my ($ds, $drive) = @_;
6085 return if drive_is_cdrom
($drive);
6087 my $volid = $drive->{file
};
6088 my $device = "drive-$ds";
6090 if (!$drivehash || $drivehash->{$ds}) {
6091 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6093 die $err if !$force;
6098 # save changes (remove drive fron snapshot)
6099 lock_config
($vmid, $updatefn, $ds) if !$force;
6100 push @$unused, $volid;
6103 # now cleanup config
6105 lock_config
($vmid, $updatefn);
6109 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6112 foreach_drive
($conf, sub {
6113 my ($ds, $drive) = @_;
6115 return if drive_is_cdrom
($drive);
6116 my $volid = $drive->{file
};
6117 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6120 return $err ?
0 : 1;
6123 sub template_create
{
6124 my ($vmid, $conf, $disk) = @_;
6126 my $storecfg = PVE
::Storage
::config
();
6128 foreach_drive
($conf, sub {
6129 my ($ds, $drive) = @_;
6131 return if drive_is_cdrom
($drive);
6132 return if $disk && $ds ne $disk;
6134 my $volid = $drive->{file
};
6135 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6137 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6138 $drive->{file
} = $voliddst;
6139 $conf->{$ds} = print_drive
($vmid, $drive);
6140 update_config_nolock
($vmid, $conf, 1);
6147 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6150 sub qemu_img_convert
{
6151 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6153 my $storecfg = PVE
::Storage
::config
();
6154 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6155 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6157 if ($src_storeid && $dst_storeid) {
6158 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6159 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6161 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6162 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6164 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6165 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6168 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6169 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6170 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6174 if($line =~ m/\((\S+)\/100\
%\)/){
6176 my $transferred = int($size * $percent / 100);
6177 my $remaining = $size - $transferred;
6179 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6184 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6186 die "copy failed: $err" if $err;
6190 sub qemu_img_format
{
6191 my ($scfg, $volname) = @_;
6193 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6200 sub qemu_drive_mirror
{
6201 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6203 my $storecfg = PVE
::Storage
::config
();
6204 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6206 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6208 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6210 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6212 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6213 $opts->{format
} = $format if $format;
6215 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6218 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6220 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6221 my $stat = @$stats[0];
6222 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6223 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6225 my $busy = $stat->{busy
};
6226 my $ready = $stat->{ready
};
6228 if (my $total = $stat->{len
}) {
6229 my $transferred = $stat->{offset
} || 0;
6230 my $remaining = $total - $transferred;
6231 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6233 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6237 if ($stat->{ready
} eq 'true') {
6239 last if $vmiddst != $vmid;
6241 # try to switch the disk if source and destination are on the same guest
6242 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6244 die $@ if $@ !~ m/cannot be completed/;
6253 my $cancel_job = sub {
6254 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6256 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6257 my $stat = @$stats[0];
6264 eval { &$cancel_job(); };
6265 die "mirroring error: $err";
6268 if ($vmiddst != $vmid) {
6269 # if we clone a disk for a new target vm, we don't switch the disk
6270 &$cancel_job(); # so we call block-job-cancel
6275 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6276 $newvmid, $storage, $format, $full, $newvollist) = @_;
6281 print "create linked clone of drive $drivename ($drive->{file})\n";
6282 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6283 push @$newvollist, $newvolid;
6285 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6286 $storeid = $storage if $storage;
6288 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6290 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6291 $format = qemu_img_format
($scfg, $volname);
6294 # test if requested format is supported - else use default
6295 my $supported = grep { $_ eq $format } @$validFormats;
6296 $format = $defFormat if !$supported;
6298 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6300 print "create full clone of drive $drivename ($drive->{file})\n";
6301 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6302 push @$newvollist, $newvolid;
6304 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6306 if (!$running || $snapname) {
6307 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6309 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6313 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6316 $disk->{format
} = undef;
6317 $disk->{file
} = $newvolid;
6318 $disk->{size
} = $size;
6323 # this only works if VM is running
6324 sub get_current_qemu_machine
{
6327 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6328 my $res = vm_qmp_command
($vmid, $cmd);
6330 my ($current, $default);
6331 foreach my $e (@$res) {
6332 $default = $e->{name
} if $e->{'is-default'};
6333 $current = $e->{name
} if $e->{'is-current'};
6336 # fallback to the default machine if current is not supported by qemu
6337 return $current || $default || 'pc';
6340 sub qemu_machine_feature_enabled
{
6341 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6346 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6348 $current_major = $3;
6349 $current_minor = $4;
6351 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6353 $current_major = $1;
6354 $current_minor = $2;
6357 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6362 sub qemu_machine_pxe
{
6363 my ($vmid, $conf, $machine) = @_;
6365 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6367 foreach my $opt (keys %$conf) {
6368 next if $opt !~ m/^net(\d+)$/;
6369 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6371 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6372 return $machine.".pxe" if $romfile =~ m/pxe/;
6378 sub qemu_use_old_bios_files
{
6379 my ($machine_type) = @_;
6381 return if !$machine_type;
6383 my $use_old_bios_files = undef;
6385 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6387 $use_old_bios_files = 1;
6389 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6390 # load new efi bios files on migration. So this hack is required to allow
6391 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6392 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6393 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6396 return ($use_old_bios_files, $machine_type);
6403 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6404 my (undef, $id, $function) = @_;
6405 my $res = { id
=> $id, function
=> $function};
6406 push @{$devices->{$id}}, $res;
6412 sub vm_iothreads_list
{
6415 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6418 foreach my $iothread (@$res) {
6419 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6426 my ($conf, $drive) = @_;
6430 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6432 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6438 my $controller = int($drive->{index} / $maxdev);
6439 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6441 return ($maxdev, $controller, $controller_prefix);
6444 # bash completion helper
6446 sub complete_backup_archives
{
6447 my ($cmdname, $pname, $cvalue) = @_;
6449 my $cfg = PVE
::Storage
::config
();
6453 if ($cvalue =~ m/^([^:]+):/) {
6457 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6460 foreach my $id (keys %$data) {
6461 foreach my $item (@{$data->{$id}}) {
6462 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6463 push @$res, $item->{volid
} if defined($item->{volid
});
6470 my $complete_vmid_full = sub {
6473 my $idlist = vmstatus
();
6477 foreach my $id (keys %$idlist) {
6478 my $d = $idlist->{$id};
6479 if (defined($running)) {
6480 next if $d->{template
};
6481 next if $running && $d->{status
} ne 'running';
6482 next if !$running && $d->{status
} eq 'running';
6491 return &$complete_vmid_full();
6494 sub complete_vmid_stopped
{
6495 return &$complete_vmid_full(0);
6498 sub complete_vmid_running
{
6499 return &$complete_vmid_full(1);
6502 sub complete_storage
{
6504 my $cfg = PVE
::Storage
::config
();
6505 my $ids = $cfg->{ids
};
6508 foreach my $sid (keys %$ids) {
6509 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);