1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
36 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
38 # Note about locking: we use flock on the config file protect
39 # against concurent actions.
40 # Aditionaly, we have a 'lock' setting in the config file. This
41 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
42 # allowed when such lock is set. But you can ignore this kind of
43 # lock with the --skiplock flag.
45 cfs_register_file
('/qemu-server/',
49 PVE
::JSONSchema
::register_standard_option
('skiplock', {
50 description
=> "Ignore locks - only root is allowed to use this option.",
55 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
56 description
=> "Some command save/restore state from this location.",
62 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
63 description
=> "The name of the snapshot.",
64 type
=> 'string', format
=> 'pve-configid',
68 #no warnings 'redefine';
71 my ($controller, $vmid, $option, $value) = @_;
73 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
74 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
78 my $nodename = PVE
::INotify
::nodename
();
80 mkdir "/etc/pve/nodes/$nodename";
81 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
84 my $var_run_tmpdir = "/var/run/qemu-server";
85 mkdir $var_run_tmpdir;
87 my $lock_dir = "/var/lock/qemu-server";
90 my $pcisysfs = "/sys/bus/pci";
96 description
=> "Specifies whether a VM will be started during system bootup.",
102 description
=> "Automatic restart after crash (currently ignored).",
107 type
=> 'string', format
=> 'pve-hotplug-features',
108 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
109 default => 'network,disk,usb',
114 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
120 description
=> "Lock/unlock the VM.",
121 enum
=> [qw(migrate backup snapshot rollback)],
126 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
134 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
142 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
149 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
155 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
163 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
164 enum
=> PVE
::Tools
::kvmkeymaplist
(),
169 type
=> 'string', format
=> 'dns-name',
170 description
=> "Set a name for the VM. Only used on the configuration web interface.",
175 description
=> "scsi controller model",
176 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
182 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
187 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
188 description
=> <<EODESC,
189 Used to enable special optimization/features for specific
192 other => unspecified OS
193 wxp => Microsoft Windows XP
194 w2k => Microsoft Windows 2000
195 w2k3 => Microsoft Windows 2003
196 w2k8 => Microsoft Windows 2008
197 wvista => Microsoft Windows Vista
198 win7 => Microsoft Windows 7
199 win8 => Microsoft Windows 8/2012
200 l24 => Linux 2.4 Kernel
201 l26 => Linux 2.6/3.X Kernel
202 solaris => solaris/opensolaris/openindiania kernel
204 other|l24|l26|solaris ... no special behaviour
205 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
211 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
212 pattern
=> '[acdn]{1,4}',
217 type
=> 'string', format
=> 'pve-qm-bootdisk',
218 description
=> "Enable booting from specified disk.",
219 pattern
=> '(ide|sata|scsi|virtio)\d+',
224 description
=> "The number of CPUs. Please use option -sockets instead.",
231 description
=> "The number of CPU sockets.",
238 description
=> "The number of cores per socket.",
245 description
=> "Enable/disable Numa.",
251 description
=> "Number of hotplugged vcpus.",
258 description
=> "Enable/disable ACPI.",
264 description
=> "Enable/disable Qemu GuestAgent.",
270 description
=> "Enable/disable KVM hardware virtualization.",
276 description
=> "Enable/disable time drift fix.",
282 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
287 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
292 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
293 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
297 type
=> 'string', format
=> 'pve-qm-watchdog',
298 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
299 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
304 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
305 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
306 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
309 startup
=> get_standard_option
('pve-startup-order'),
313 description
=> "Enable/disable Template.",
319 description
=> <<EODESCR,
320 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
322 args: -no-reboot -no-hpet
329 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
334 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
338 migrate_downtime
=> {
341 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
347 type
=> 'string', format
=> 'pve-qm-drive',
348 typetext
=> 'volume',
349 description
=> "This is an alias for option -ide2",
353 description
=> "Emulated CPU type.",
355 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
358 parent
=> get_standard_option
('pve-snapshot-name', {
360 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
364 description
=> "Timestamp for snapshots.",
370 type
=> 'string', format
=> 'pve-volume-id',
371 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
374 description
=> "Specific the Qemu machine type.",
376 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
381 description
=> "Specify SMBIOS type 1 fields.",
382 type
=> 'string', format
=> 'pve-qm-smbios1',
383 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
390 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
395 # what about other qemu settings ?
397 #machine => 'string',
410 ##soundhw => 'string',
412 while (my ($k, $v) = each %$confdesc) {
413 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
416 my $MAX_IDE_DISKS = 4;
417 my $MAX_SCSI_DISKS = 14;
418 my $MAX_VIRTIO_DISKS = 16;
419 my $MAX_SATA_DISKS = 6;
420 my $MAX_USB_DEVICES = 5;
422 my $MAX_UNUSED_DISKS = 8;
423 my $MAX_HOSTPCI_DEVICES = 4;
424 my $MAX_SERIAL_PORTS = 4;
425 my $MAX_PARALLEL_PORTS = 3;
427 my $MAX_MEM = 4194304;
428 my $STATICMEM = 1024;
432 type
=> 'string', format
=> 'pve-qm-numanode',
433 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
434 description
=> "numa topology",
436 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
438 for (my $i = 0; $i < $MAX_NUMA; $i++) {
439 $confdesc->{"numa$i"} = $numadesc;
442 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
443 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
444 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
445 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
449 type
=> 'string', format
=> 'pve-qm-net',
450 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
451 description
=> <<EODESCR,
452 Specify network devices.
454 MODEL is one of: $nic_model_list_txt
456 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
457 automatically generated if not specified.
459 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
461 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
463 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
469 The DHCP server assign addresses to the guest starting from 10.0.2.15.
473 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
475 for (my $i = 0; $i < $MAX_NETS; $i++) {
476 $confdesc->{"net$i"} = $netdesc;
483 type
=> 'string', format
=> 'pve-qm-drive',
484 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,serial=serial][,model=model]',
485 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
487 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
491 type
=> 'string', format
=> 'pve-qm-drive',
492 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,queues=<nbqueues>] [,serial=serial]',
493 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
499 type
=> 'string', format
=> 'pve-qm-drive',
500 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,serial=serial]',
501 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
503 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
507 type
=> 'string', format
=> 'pve-qm-drive',
508 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,serial=serial]',
509 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
511 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
515 type
=> 'string', format
=> 'pve-qm-usb-device',
516 typetext
=> 'host=HOSTUSBDEVICE|spice',
517 description
=> <<EODESCR,
518 Configure an USB device (n is 0 to 4). This can be used to
519 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
521 'bus-port(.port)*' (decimal numbers) or
522 'vendor_id:product_id' (hexadeciaml numbers)
524 You can use the 'lsusb -t' command to list existing usb devices.
526 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
528 The value 'spice' can be used to add a usb redirection devices for spice.
532 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
536 type
=> 'string', format
=> 'pve-qm-hostpci',
537 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
538 description
=> <<EODESCR,
539 Map host pci devices. HOSTPCIDEVICE syntax is:
541 'bus:dev.func' (hexadecimal numbers)
543 You can us the 'lspci' command to list existing pci devices.
545 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
547 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
549 Experimental: user reported problems with this option.
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
557 pattern
=> '(/dev/.+|socket)',
558 description
=> <<EODESCR,
559 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
561 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
563 Experimental: user reported problems with this option.
570 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
571 description
=> <<EODESCR,
572 Map host parallel devices (n is 0 to 2).
574 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
576 Experimental: user reported problems with this option.
580 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
581 $confdesc->{"parallel$i"} = $paralleldesc;
584 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
585 $confdesc->{"serial$i"} = $serialdesc;
588 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
589 $confdesc->{"hostpci$i"} = $hostpcidesc;
592 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
593 $drivename_hash->{"ide$i"} = 1;
594 $confdesc->{"ide$i"} = $idedesc;
597 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
598 $drivename_hash->{"sata$i"} = 1;
599 $confdesc->{"sata$i"} = $satadesc;
602 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
603 $drivename_hash->{"scsi$i"} = 1;
604 $confdesc->{"scsi$i"} = $scsidesc ;
607 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
608 $drivename_hash->{"virtio$i"} = 1;
609 $confdesc->{"virtio$i"} = $virtiodesc;
612 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
613 $confdesc->{"usb$i"} = $usbdesc;
618 type
=> 'string', format
=> 'pve-volume-id',
619 description
=> "Reference to unused volumes.",
622 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
623 $confdesc->{"unused$i"} = $unuseddesc;
626 my $kvm_api_version = 0;
630 return $kvm_api_version if $kvm_api_version;
632 my $fh = IO
::File-
>new("</dev/kvm") ||
635 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
636 $kvm_api_version = $v;
641 return $kvm_api_version;
644 my $kvm_user_version;
646 sub kvm_user_version
{
648 return $kvm_user_version if $kvm_user_version;
650 $kvm_user_version = 'unknown';
652 my $tmp = `kvm -help 2>/dev/null`;
654 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
655 $kvm_user_version = $2;
658 return $kvm_user_version;
662 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
665 # order is important - used to autoselect boot disk
666 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
667 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
668 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
669 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
672 sub valid_drivename
{
675 return defined($drivename_hash->{$dev});
680 return defined($confdesc->{$key});
684 return $nic_model_list;
687 sub os_list_description
{
692 w2k
=> 'Windows 2000',
693 w2k3
=>, 'Windows 2003',
694 w2k8
=> 'Windows 2008',
695 wvista
=> 'Windows Vista',
697 win8
=> 'Windows 8/2012',
707 return $cdrom_path if $cdrom_path;
709 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
710 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
711 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
715 my ($storecfg, $vmid, $cdrom) = @_;
717 if ($cdrom eq 'cdrom') {
718 return get_cdrom_path
();
719 } elsif ($cdrom eq 'none') {
721 } elsif ($cdrom =~ m
|^/|) {
724 return PVE
::Storage
::path
($storecfg, $cdrom);
728 # try to convert old style file names to volume IDs
729 sub filename_to_volume_id
{
730 my ($vmid, $file, $media) = @_;
732 if (!($file eq 'none' || $file eq 'cdrom' ||
733 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
735 return undef if $file =~ m
|/|;
737 if ($media && $media eq 'cdrom') {
738 $file = "local:iso/$file";
740 $file = "local:$vmid/$file";
747 sub verify_media_type
{
748 my ($opt, $vtype, $media) = @_;
753 if ($media eq 'disk') {
755 } elsif ($media eq 'cdrom') {
758 die "internal error";
761 return if ($vtype eq $etype);
763 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
766 sub cleanup_drive_path
{
767 my ($opt, $storecfg, $drive) = @_;
769 # try to convert filesystem paths to volume IDs
771 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
772 ($drive->{file
} !~ m
|^/dev/.+|) &&
773 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
774 ($drive->{file
} !~ m/^\d+$/)) {
775 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
776 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
777 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
778 verify_media_type
($opt, $vtype, $drive->{media
});
779 $drive->{file
} = $volid;
782 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
785 sub create_conf_nolock
{
786 my ($vmid, $settings) = @_;
788 my $filename = config_file
($vmid);
790 die "configuration file '$filename' already exists\n" if -f
$filename;
792 my $defaults = load_defaults
();
794 $settings->{name
} = "vm$vmid" if !$settings->{name
};
795 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
798 foreach my $opt (keys %$settings) {
799 next if !$confdesc->{$opt};
801 my $value = $settings->{$opt};
804 $data .= "$opt: $value\n";
807 PVE
::Tools
::file_set_contents
($filename, $data);
810 sub parse_hotplug_features
{
815 return $res if $data eq '0';
817 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
819 foreach my $feature (PVE
::Tools
::split_list
($data)) {
820 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
823 warn "ignoring unknown hotplug feature '$feature'\n";
829 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
830 sub pve_verify_hotplug_features
{
831 my ($value, $noerr) = @_;
833 return $value if parse_hotplug_features
($value);
835 return undef if $noerr;
837 die "unable to parse hotplug option\n";
840 my $parse_size = sub {
843 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
844 my ($size, $unit) = ($1, $3);
847 $size = $size * 1024;
848 } elsif ($unit eq 'M') {
849 $size = $size * 1024 * 1024;
850 } elsif ($unit eq 'G') {
851 $size = $size * 1024 * 1024 * 1024;
857 my $format_size = sub {
862 my $kb = int($size/1024);
863 return $size if $kb*1024 != $size;
865 my $mb = int($kb/1024);
866 return "${kb}K" if $mb*1024 != $kb;
868 my $gb = int($mb/1024);
869 return "${mb}M" if $gb*1024 != $mb;
874 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
875 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
876 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
877 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
878 # [,serial=serial][,model=model]
881 my ($key, $data) = @_;
885 # $key may be undefined - used to verify JSON parameters
886 if (!defined($key)) {
887 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
889 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
890 $res->{interface
} = $1;
896 foreach my $p (split (/,/, $data)) {
897 next if $p =~ m/^\s*$/;
899 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues|serial|model)=(.+)$/) {
900 my ($k, $v) = ($1, $2);
902 $k = 'file' if $k eq 'volume';
904 return undef if defined $res->{$k};
906 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
907 return undef if !$v || $v !~ m/^\d+/;
909 $v = sprintf("%.3f", $v / (1024*1024));
913 if (!$res->{file
} && $p !~ m/=/) {
921 return undef if !$res->{file
};
923 return undef if $res->{cache
} &&
924 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
925 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
926 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
927 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
928 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
929 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
930 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
931 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
932 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
933 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
934 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
935 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
936 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
937 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
938 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
940 return undef if $res->{mbps_rd
} && $res->{mbps
};
941 return undef if $res->{mbps_wr
} && $res->{mbps
};
943 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
944 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
945 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
946 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
947 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{iops_rd
} && $res->{iops
};
951 return undef if $res->{iops_wr
} && $res->{iops
};
954 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
955 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
956 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
957 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
958 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
959 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
962 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
965 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
966 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
967 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
968 return undef if $res->{interface
} eq 'virtio';
971 # rerror does not work with scsi drives
972 if ($res->{rerror
}) {
973 return undef if $res->{interface
} eq 'scsi';
979 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
982 my ($vmid, $drive) = @_;
985 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
986 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
989 if ($drive->{size
}) {
990 $opts .= ",size=" . &$format_size($drive->{size
});
993 if (my $model = $drive->{model
}) {
994 $opts .= ",model=$model";
997 return "$drive->{file}$opts";
1001 my($fh, $noerr) = @_;
1004 my $SG_GET_VERSION_NUM = 0x2282;
1006 my $versionbuf = "\x00" x
8;
1007 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1009 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1012 my $version = unpack("I", $versionbuf);
1013 if ($version < 30000) {
1014 die "scsi generic interface too old\n" if !$noerr;
1018 my $buf = "\x00" x
36;
1019 my $sensebuf = "\x00" x
8;
1020 my $cmd = pack("C x3 C x1", 0x12, 36);
1022 # see /usr/include/scsi/sg.h
1023 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1025 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1026 length($sensebuf), 0, length($buf), $buf,
1027 $cmd, $sensebuf, 6000);
1029 $ret = ioctl($fh, $SG_IO, $packet);
1031 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1035 my @res = unpack($sg_io_hdr_t, $packet);
1036 if ($res[17] || $res[18]) {
1037 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1042 (my $byte0, my $byte1, $res->{vendor
},
1043 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1045 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1046 $res->{type
} = $byte0 & 31;
1054 my $fh = IO
::File-
>new("+<$path") || return undef;
1055 my $res = scsi_inquiry
($fh, 1);
1061 sub machine_type_is_q35
{
1064 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1067 sub print_tabletdevice_full
{
1070 my $q35 = machine_type_is_q35
($conf);
1072 # we use uhci for old VMs because tablet driver was buggy in older qemu
1073 my $usbbus = $q35 ?
"ehci" : "uhci";
1075 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1078 sub print_drivedevice_full
{
1079 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1084 if ($drive->{interface
} eq 'virtio') {
1085 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1086 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1087 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1088 } elsif ($drive->{interface
} eq 'scsi') {
1090 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1091 my $unit = $drive->{index} % $maxdev;
1092 my $devicetype = 'hd';
1094 if (drive_is_cdrom
($drive)) {
1097 if ($drive->{file
} =~ m
|^/|) {
1098 $path = $drive->{file
};
1100 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1103 if($path =~ m/^iscsi\:\/\
//){
1104 $devicetype = 'generic';
1106 if (my $info = path_is_scsi
($path)) {
1107 if ($info->{type
} == 0) {
1108 $devicetype = 'block';
1109 } elsif ($info->{type
} == 1) { # tape
1110 $devicetype = 'generic';
1116 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1117 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1122 } elsif ($drive->{interface
} eq 'ide'){
1124 my $controller = int($drive->{index} / $maxdev);
1125 my $unit = $drive->{index} % $maxdev;
1126 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1128 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1129 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1130 $device .= ",model=$model";
1132 } elsif ($drive->{interface
} eq 'sata'){
1133 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1134 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1135 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1136 } elsif ($drive->{interface
} eq 'usb') {
1138 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1140 die "unsupported interface type";
1143 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1148 sub get_initiator_name
{
1151 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1152 while (defined(my $line = <$fh>)) {
1153 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1162 sub print_drive_full
{
1163 my ($storecfg, $vmid, $drive) = @_;
1166 my $volid = $drive->{file
};
1169 if (drive_is_cdrom
($drive)) {
1170 $path = get_iso_path
($storecfg, $vmid, $volid);
1172 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1174 $path = PVE
::Storage
::path
($storecfg, $volid);
1175 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1176 $format = qemu_img_format
($scfg, $volname);
1183 foreach my $o (@qemu_drive_options) {
1184 next if $o eq 'bootindex';
1185 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1188 $opts .= ",format=$format" if $format && !$drive->{format
};
1190 foreach my $o (qw(bps bps_rd bps_wr)) {
1191 my $v = $drive->{"m$o"};
1192 $opts .= ",$o=" . int($v*1024*1024) if $v;
1195 my $cache_direct = 0;
1197 if (my $cache = $drive->{cache
}) {
1198 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1199 } elsif (!drive_is_cdrom
($drive)) {
1200 $opts .= ",cache=none";
1204 # aio native works only with O_DIRECT
1205 if (!$drive->{aio
}) {
1207 $opts .= ",aio=native";
1209 $opts .= ",aio=threads";
1213 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1214 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1216 my $pathinfo = $path ?
"file=$path," : '';
1218 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1221 sub print_netdevice_full
{
1222 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1224 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1226 my $device = $net->{model
};
1227 if ($net->{model
} eq 'virtio') {
1228 $device = 'virtio-net-pci';
1231 my $pciaddr = print_pci_addr
("$netid", $bridges);
1232 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1233 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1234 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1235 my $vectors = $net->{queues
} * 2 + 2;
1236 $tmpstr .= ",vectors=$vectors,mq=on";
1238 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1240 if ($use_old_bios_files) {
1242 if ($device eq 'virtio-net-pci') {
1243 $romfile = 'pxe-virtio.rom';
1244 } elsif ($device eq 'e1000') {
1245 $romfile = 'pxe-e1000.rom';
1246 } elsif ($device eq 'ne2k') {
1247 $romfile = 'pxe-ne2k_pci.rom';
1248 } elsif ($device eq 'pcnet') {
1249 $romfile = 'pxe-pcnet.rom';
1250 } elsif ($device eq 'rtl8139') {
1251 $romfile = 'pxe-rtl8139.rom';
1253 $tmpstr .= ",romfile=$romfile" if $romfile;
1259 sub print_netdev_full
{
1260 my ($vmid, $conf, $net, $netid) = @_;
1263 if ($netid =~ m/^net(\d+)$/) {
1267 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1269 my $ifname = "tap${vmid}i$i";
1271 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1272 die "interface name '$ifname' is too long (max 15 character)\n"
1273 if length($ifname) >= 16;
1275 my $vhostparam = '';
1276 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1278 my $vmname = $conf->{name
} || "vm$vmid";
1282 if ($net->{bridge
}) {
1283 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1285 $netdev = "type=user,id=$netid,hostname=$vmname";
1288 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1293 sub drive_is_cdrom
{
1296 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1305 foreach my $kvp (split(/,/, $data)) {
1307 if ($kvp =~ m/^memory=(\S+)$/) {
1308 $res->{memory
} = $1;
1309 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1310 $res->{policy
} = $1;
1311 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1312 $res->{cpus
}->{start
} = $1;
1313 $res->{cpus
}->{end
} = $3;
1314 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1315 $res->{hostnodes
}->{start
} = $1;
1316 $res->{hostnodes
}->{end
} = $3;
1328 return undef if !$value;
1331 my @list = split(/,/, $value);
1335 foreach my $kv (@list) {
1337 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1340 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1343 my $pcidevices = lspci
($2);
1344 $res->{pciid
} = $pcidevices->{$2};
1346 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1347 $res->{rombar
} = $1;
1348 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1349 $res->{'x-vga'} = $1;
1350 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1351 $res->{pcie
} = 1 if $1 == 1;
1353 warn "unknown hostpci setting '$kv'\n";
1357 return undef if !$found;
1362 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1368 foreach my $kvp (split(/,/, $data)) {
1370 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1372 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1373 $res->{model
} = $model;
1374 $res->{macaddr
} = $mac;
1375 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1376 $res->{bridge
} = $1;
1377 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1378 $res->{queues
} = $1;
1379 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1381 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1383 } elsif ($kvp =~ m/^firewall=([01])$/) {
1384 $res->{firewall
} = $1;
1385 } elsif ($kvp =~ m/^link_down=([01])$/) {
1386 $res->{link_down
} = $1;
1393 return undef if !$res->{model
};
1401 my $res = "$net->{model}";
1402 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1403 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1404 $res .= ",rate=$net->{rate}" if $net->{rate
};
1405 $res .= ",tag=$net->{tag}" if $net->{tag
};
1406 $res .= ",firewall=1" if $net->{firewall
};
1407 $res .= ",link_down=1" if $net->{link_down
};
1408 $res .= ",queues=$net->{queues}" if $net->{queues
};
1413 sub add_random_macs
{
1414 my ($settings) = @_;
1416 foreach my $opt (keys %$settings) {
1417 next if $opt !~ m/^net(\d+)$/;
1418 my $net = parse_net
($settings->{$opt});
1420 $settings->{$opt} = print_net
($net);
1424 sub add_unused_volume
{
1425 my ($config, $volid) = @_;
1428 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1429 my $test = "unused$ind";
1430 if (my $vid = $config->{$test}) {
1431 return if $vid eq $volid; # do not add duplicates
1437 die "To many unused volume - please delete them first.\n" if !$key;
1439 $config->{$key} = $volid;
1444 sub vm_is_volid_owner
{
1445 my ($storecfg, $vmid, $volid) = @_;
1447 if ($volid !~ m
|^/|) {
1449 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1450 if ($owner && ($owner == $vmid)) {
1458 sub split_flagged_list
{
1459 my $text = shift || '';
1460 $text =~ s/[,;]/ /g;
1462 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1465 sub join_flagged_list
{
1466 my ($how, $lst) = @_;
1467 join $how, map { $lst->{$_} . $_ } keys %$lst;
1470 sub vmconfig_delete_pending_option
{
1471 my ($conf, $key, $force) = @_;
1473 delete $conf->{pending
}->{$key};
1474 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1475 $pending_delete_hash->{$key} = $force ?
'!' : '';
1476 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1479 sub vmconfig_undelete_pending_option
{
1480 my ($conf, $key) = @_;
1482 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1483 delete $pending_delete_hash->{$key};
1485 if (%$pending_delete_hash) {
1486 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1488 delete $conf->{pending
}->{delete};
1492 sub vmconfig_register_unused_drive
{
1493 my ($storecfg, $vmid, $conf, $drive) = @_;
1495 if (!drive_is_cdrom
($drive)) {
1496 my $volid = $drive->{file
};
1497 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1498 add_unused_volume
($conf, $volid, $vmid);
1503 sub vmconfig_cleanup_pending
{
1506 # remove pending changes when nothing changed
1508 foreach my $opt (keys %{$conf->{pending
}}) {
1509 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1511 delete $conf->{pending
}->{$opt};
1515 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1516 my $pending_delete_hash = {};
1517 while (my ($opt, $force) = each %$current_delete_hash) {
1518 if (defined($conf->{$opt})) {
1519 $pending_delete_hash->{$opt} = $force;
1525 if (%$pending_delete_hash) {
1526 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1528 delete $conf->{pending
}->{delete};
1534 my $valid_smbios1_options = {
1535 manufacturer
=> '\S+',
1539 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1544 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1550 foreach my $kvp (split(/,/, $data)) {
1551 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1552 my ($k, $v) = split(/=/, $kvp);
1553 return undef if !defined($k) || !defined($v);
1554 return undef if !$valid_smbios1_options->{$k};
1555 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1566 foreach my $k (keys %$smbios1) {
1567 next if !defined($smbios1->{$k});
1568 next if !$valid_smbios1_options->{$k};
1569 $data .= ',' if $data;
1570 $data .= "$k=$smbios1->{$k}";
1575 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1576 sub verify_smbios1
{
1577 my ($value, $noerr) = @_;
1579 return $value if parse_smbios1
($value);
1581 return undef if $noerr;
1583 die "unable to parse smbios (type 1) options\n";
1586 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1587 sub verify_bootdisk
{
1588 my ($value, $noerr) = @_;
1590 return $value if valid_drivename
($value);
1592 return undef if $noerr;
1594 die "invalid boot disk '$value'\n";
1597 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1599 my ($value, $noerr) = @_;
1601 return $value if parse_numa
($value);
1603 return undef if $noerr;
1605 die "unable to parse numa options\n";
1608 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1610 my ($value, $noerr) = @_;
1612 return $value if parse_net
($value);
1614 return undef if $noerr;
1616 die "unable to parse network options\n";
1619 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1621 my ($value, $noerr) = @_;
1623 return $value if parse_drive
(undef, $value);
1625 return undef if $noerr;
1627 die "unable to parse drive options\n";
1630 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1631 sub verify_hostpci
{
1632 my ($value, $noerr) = @_;
1634 return $value if parse_hostpci
($value);
1636 return undef if $noerr;
1638 die "unable to parse pci id\n";
1641 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1642 sub verify_watchdog
{
1643 my ($value, $noerr) = @_;
1645 return $value if parse_watchdog
($value);
1647 return undef if $noerr;
1649 die "unable to parse watchdog options\n";
1652 sub parse_watchdog
{
1655 return undef if !$value;
1659 foreach my $p (split(/,/, $value)) {
1660 next if $p =~ m/^\s*$/;
1662 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1664 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1665 $res->{action
} = $2;
1674 sub parse_usb_device
{
1677 return undef if !$value;
1679 my @dl = split(/,/, $value);
1683 foreach my $v (@dl) {
1684 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1686 $res->{vendorid
} = $2;
1687 $res->{productid
} = $4;
1688 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1690 $res->{hostbus
} = $1;
1691 $res->{hostport
} = $2;
1692 } elsif ($v =~ m/^spice$/) {
1699 return undef if !$found;
1704 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1705 sub verify_usb_device
{
1706 my ($value, $noerr) = @_;
1708 return $value if parse_usb_device
($value);
1710 return undef if $noerr;
1712 die "unable to parse usb device\n";
1715 # add JSON properties for create and set function
1716 sub json_config_properties
{
1719 foreach my $opt (keys %$confdesc) {
1720 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1721 $prop->{$opt} = $confdesc->{$opt};
1728 my ($key, $value) = @_;
1730 die "unknown setting '$key'\n" if !$confdesc->{$key};
1732 my $type = $confdesc->{$key}->{type
};
1734 if (!defined($value)) {
1735 die "got undefined value\n";
1738 if ($value =~ m/[\n\r]/) {
1739 die "property contains a line feed\n";
1742 if ($type eq 'boolean') {
1743 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1744 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1745 die "type check ('boolean') failed - got '$value'\n";
1746 } elsif ($type eq 'integer') {
1747 return int($1) if $value =~ m/^(\d+)$/;
1748 die "type check ('integer') failed - got '$value'\n";
1749 } elsif ($type eq 'number') {
1750 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1751 die "type check ('number') failed - got '$value'\n";
1752 } elsif ($type eq 'string') {
1753 if (my $fmt = $confdesc->{$key}->{format
}) {
1754 if ($fmt eq 'pve-qm-drive') {
1755 # special case - we need to pass $key to parse_drive()
1756 my $drive = parse_drive
($key, $value);
1757 return $value if $drive;
1758 die "unable to parse drive options\n";
1760 PVE
::JSONSchema
::check_format
($fmt, $value);
1763 $value =~ s/^\"(.*)\"$/$1/;
1766 die "internal error"
1770 sub lock_config_full
{
1771 my ($vmid, $timeout, $code, @param) = @_;
1773 my $filename = config_file_lock
($vmid);
1775 my $res = lock_file
($filename, $timeout, $code, @param);
1782 sub lock_config_mode
{
1783 my ($vmid, $timeout, $shared, $code, @param) = @_;
1785 my $filename = config_file_lock
($vmid);
1787 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1795 my ($vmid, $code, @param) = @_;
1797 return lock_config_full
($vmid, 10, $code, @param);
1800 sub cfs_config_path
{
1801 my ($vmid, $node) = @_;
1803 $node = $nodename if !$node;
1804 return "nodes/$node/qemu-server/$vmid.conf";
1807 sub check_iommu_support
{
1808 #fixme : need to check IOMMU support
1809 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1817 my ($vmid, $node) = @_;
1819 my $cfspath = cfs_config_path
($vmid, $node);
1820 return "/etc/pve/$cfspath";
1823 sub config_file_lock
{
1826 return "$lock_dir/lock-$vmid.conf";
1832 my $conf = config_file
($vmid);
1833 utime undef, undef, $conf;
1837 my ($storecfg, $vmid, $keep_empty_config) = @_;
1839 my $conffile = config_file
($vmid);
1841 my $conf = load_config
($vmid);
1845 # only remove disks owned by this VM
1846 foreach_drive
($conf, sub {
1847 my ($ds, $drive) = @_;
1849 return if drive_is_cdrom
($drive);
1851 my $volid = $drive->{file
};
1853 return if !$volid || $volid =~ m
|^/|;
1855 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1856 return if !$path || !$owner || ($owner != $vmid);
1858 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1861 if ($keep_empty_config) {
1862 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1867 # also remove unused disk
1869 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1872 PVE
::Storage
::foreach_volid
($dl, sub {
1873 my ($volid, $sid, $volname, $d) = @_;
1874 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1884 my ($vmid, $node) = @_;
1886 my $cfspath = cfs_config_path
($vmid, $node);
1888 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1890 die "no such VM ('$vmid')\n" if !defined($conf);
1895 sub parse_vm_config
{
1896 my ($filename, $raw) = @_;
1898 return undef if !defined($raw);
1901 digest
=> Digest
::SHA
::sha1_hex
($raw),
1906 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1907 || die "got strange filename '$filename'";
1915 my @lines = split(/\n/, $raw);
1916 foreach my $line (@lines) {
1917 next if $line =~ m/^\s*$/;
1919 if ($line =~ m/^\[PENDING\]\s*$/i) {
1920 $section = 'pending';
1921 if (defined($descr)) {
1923 $conf->{description
} = $descr;
1926 $conf = $res->{$section} = {};
1929 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1931 if (defined($descr)) {
1933 $conf->{description
} = $descr;
1936 $conf = $res->{snapshots
}->{$section} = {};
1940 if ($line =~ m/^\#(.*)\s*$/) {
1941 $descr = '' if !defined($descr);
1942 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1946 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1947 $descr = '' if !defined($descr);
1948 $descr .= PVE
::Tools
::decode_text
($2);
1949 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1950 $conf->{snapstate
} = $1;
1951 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1954 $conf->{$key} = $value;
1955 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1957 if ($section eq 'pending') {
1958 $conf->{delete} = $value; # we parse this later
1960 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1962 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1965 eval { $value = check_type
($key, $value); };
1967 warn "vm $vmid - unable to parse value of '$key' - $@";
1969 my $fmt = $confdesc->{$key}->{format
};
1970 if ($fmt && $fmt eq 'pve-qm-drive') {
1971 my $v = parse_drive
($key, $value);
1972 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1973 $v->{file
} = $volid;
1974 $value = print_drive
($vmid, $v);
1976 warn "vm $vmid - unable to parse value of '$key'\n";
1981 if ($key eq 'cdrom') {
1982 $conf->{ide2
} = $value;
1984 $conf->{$key} = $value;
1990 if (defined($descr)) {
1992 $conf->{description
} = $descr;
1994 delete $res->{snapstate
}; # just to be sure
1999 sub write_vm_config
{
2000 my ($filename, $conf) = @_;
2002 delete $conf->{snapstate
}; # just to be sure
2004 if ($conf->{cdrom
}) {
2005 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2006 $conf->{ide2
} = $conf->{cdrom
};
2007 delete $conf->{cdrom
};
2010 # we do not use 'smp' any longer
2011 if ($conf->{sockets
}) {
2012 delete $conf->{smp
};
2013 } elsif ($conf->{smp
}) {
2014 $conf->{sockets
} = $conf->{smp
};
2015 delete $conf->{cores
};
2016 delete $conf->{smp
};
2019 my $used_volids = {};
2021 my $cleanup_config = sub {
2022 my ($cref, $pending, $snapname) = @_;
2024 foreach my $key (keys %$cref) {
2025 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2026 $key eq 'snapstate' || $key eq 'pending';
2027 my $value = $cref->{$key};
2028 if ($key eq 'delete') {
2029 die "propertry 'delete' is only allowed in [PENDING]\n"
2031 # fixme: check syntax?
2034 eval { $value = check_type
($key, $value); };
2035 die "unable to parse value of '$key' - $@" if $@;
2037 $cref->{$key} = $value;
2039 if (!$snapname && valid_drivename
($key)) {
2040 my $drive = parse_drive
($key, $value);
2041 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2046 &$cleanup_config($conf);
2048 &$cleanup_config($conf->{pending
}, 1);
2050 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2051 die "internal error" if $snapname eq 'pending';
2052 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2055 # remove 'unusedX' settings if we re-add a volume
2056 foreach my $key (keys %$conf) {
2057 my $value = $conf->{$key};
2058 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2059 delete $conf->{$key};
2063 my $generate_raw_config = sub {
2064 my ($conf, $pending) = @_;
2068 # add description as comment to top of file
2069 if (defined(my $descr = $conf->{description
})) {
2071 foreach my $cl (split(/\n/, $descr)) {
2072 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2075 $raw .= "#\n" if $pending;
2079 foreach my $key (sort keys %$conf) {
2080 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2081 $raw .= "$key: $conf->{$key}\n";
2086 my $raw = &$generate_raw_config($conf);
2088 if (scalar(keys %{$conf->{pending
}})){
2089 $raw .= "\n[PENDING]\n";
2090 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2093 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2094 $raw .= "\n[$snapname]\n";
2095 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2101 sub update_config_nolock
{
2102 my ($vmid, $conf, $skiplock) = @_;
2104 check_lock
($conf) if !$skiplock;
2106 my $cfspath = cfs_config_path
($vmid);
2108 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2112 my ($vmid, $conf, $skiplock) = @_;
2114 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2121 # we use static defaults from our JSON schema configuration
2122 foreach my $key (keys %$confdesc) {
2123 if (defined(my $default = $confdesc->{$key}->{default})) {
2124 $res->{$key} = $default;
2128 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2129 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2135 my $vmlist = PVE
::Cluster
::get_vmlist
();
2137 return $res if !$vmlist || !$vmlist->{ids
};
2138 my $ids = $vmlist->{ids
};
2140 foreach my $vmid (keys %$ids) {
2141 my $d = $ids->{$vmid};
2142 next if !$d->{node
} || $d->{node
} ne $nodename;
2143 next if !$d->{type
} || $d->{type
} ne 'qemu';
2144 $res->{$vmid}->{exists} = 1;
2149 # test if VM uses local resources (to prevent migration)
2150 sub check_local_resources
{
2151 my ($conf, $noerr) = @_;
2155 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2156 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2158 foreach my $k (keys %$conf) {
2159 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2160 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2163 die "VM uses local resources\n" if $loc_res && !$noerr;
2168 # check if used storages are available on all nodes (use by migrate)
2169 sub check_storage_availability
{
2170 my ($storecfg, $conf, $node) = @_;
2172 foreach_drive
($conf, sub {
2173 my ($ds, $drive) = @_;
2175 my $volid = $drive->{file
};
2178 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2181 # check if storage is available on both nodes
2182 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2183 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2187 # list nodes where all VM images are available (used by has_feature API)
2189 my ($conf, $storecfg) = @_;
2191 my $nodelist = PVE
::Cluster
::get_nodelist
();
2192 my $nodehash = { map { $_ => 1 } @$nodelist };
2193 my $nodename = PVE
::INotify
::nodename
();
2195 foreach_drive
($conf, sub {
2196 my ($ds, $drive) = @_;
2198 my $volid = $drive->{file
};
2201 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2203 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2204 if ($scfg->{disable
}) {
2206 } elsif (my $avail = $scfg->{nodes
}) {
2207 foreach my $node (keys %$nodehash) {
2208 delete $nodehash->{$node} if !$avail->{$node};
2210 } elsif (!$scfg->{shared
}) {
2211 foreach my $node (keys %$nodehash) {
2212 delete $nodehash->{$node} if $node ne $nodename
2224 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2228 my ($pidfile, $pid) = @_;
2230 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2234 return undef if !$line;
2235 my @param = split(/\0/, $line);
2237 my $cmd = $param[0];
2238 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2240 for (my $i = 0; $i < scalar (@param); $i++) {
2243 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2244 my $p = $param[$i+1];
2245 return 1 if $p && ($p eq $pidfile);
2254 my ($vmid, $nocheck, $node) = @_;
2256 my $filename = config_file
($vmid, $node);
2258 die "unable to find configuration file for VM $vmid - no such machine\n"
2259 if !$nocheck && ! -f
$filename;
2261 my $pidfile = pidfile_name
($vmid);
2263 if (my $fd = IO
::File-
>new("<$pidfile")) {
2268 my $mtime = $st->mtime;
2269 if ($mtime > time()) {
2270 warn "file '$filename' modified in future\n";
2273 if ($line =~ m/^(\d+)$/) {
2275 if (check_cmdline
($pidfile, $pid)) {
2276 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2288 my $vzlist = config_list
();
2290 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2292 while (defined(my $de = $fd->read)) {
2293 next if $de !~ m/^(\d+)\.pid$/;
2295 next if !defined($vzlist->{$vmid});
2296 if (my $pid = check_running
($vmid)) {
2297 $vzlist->{$vmid}->{pid
} = $pid;
2305 my ($storecfg, $conf) = @_;
2307 my $bootdisk = $conf->{bootdisk
};
2308 return undef if !$bootdisk;
2309 return undef if !valid_drivename
($bootdisk);
2311 return undef if !$conf->{$bootdisk};
2313 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2314 return undef if !defined($drive);
2316 return undef if drive_is_cdrom
($drive);
2318 my $volid = $drive->{file
};
2319 return undef if !$volid;
2321 return $drive->{size
};
2324 my $last_proc_pid_stat;
2326 # get VM status information
2327 # This must be fast and should not block ($full == false)
2328 # We only query KVM using QMP if $full == true (this can be slow)
2330 my ($opt_vmid, $full) = @_;
2334 my $storecfg = PVE
::Storage
::config
();
2336 my $list = vzlist
();
2337 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2339 my $cpucount = $cpuinfo->{cpus
} || 1;
2341 foreach my $vmid (keys %$list) {
2342 next if $opt_vmid && ($vmid ne $opt_vmid);
2344 my $cfspath = cfs_config_path
($vmid);
2345 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2348 $d->{pid
} = $list->{$vmid}->{pid
};
2350 # fixme: better status?
2351 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2353 my $size = disksize
($storecfg, $conf);
2354 if (defined($size)) {
2355 $d->{disk
} = 0; # no info available
2356 $d->{maxdisk
} = $size;
2362 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2363 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2364 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2366 $d->{name
} = $conf->{name
} || "VM $vmid";
2367 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2369 if ($conf->{balloon
}) {
2370 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2371 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2382 $d->{diskwrite
} = 0;
2384 $d->{template
} = is_template
($conf);
2389 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2390 foreach my $dev (keys %$netdev) {
2391 next if $dev !~ m/^tap([1-9]\d*)i/;
2393 my $d = $res->{$vmid};
2396 $d->{netout
} += $netdev->{$dev}->{receive
};
2397 $d->{netin
} += $netdev->{$dev}->{transmit
};
2400 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2401 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2406 my $ctime = gettimeofday
;
2408 foreach my $vmid (keys %$list) {
2410 my $d = $res->{$vmid};
2411 my $pid = $d->{pid
};
2414 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2415 next if !$pstat; # not running
2417 my $used = $pstat->{utime} + $pstat->{stime
};
2419 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2421 if ($pstat->{vsize
}) {
2422 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2425 my $old = $last_proc_pid_stat->{$pid};
2427 $last_proc_pid_stat->{$pid} = {
2435 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2437 if ($dtime > 1000) {
2438 my $dutime = $used - $old->{used
};
2440 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2441 $last_proc_pid_stat->{$pid} = {
2447 $d->{cpu
} = $old->{cpu
};
2451 return $res if !$full;
2453 my $qmpclient = PVE
::QMPClient-
>new();
2455 my $ballooncb = sub {
2456 my ($vmid, $resp) = @_;
2458 my $info = $resp->{'return'};
2459 return if !$info->{max_mem
};
2461 my $d = $res->{$vmid};
2463 # use memory assigned to VM
2464 $d->{maxmem
} = $info->{max_mem
};
2465 $d->{balloon
} = $info->{actual
};
2467 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2468 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2469 $d->{freemem
} = $info->{free_mem
};
2472 $d->{ballooninfo
} = $info;
2475 my $blockstatscb = sub {
2476 my ($vmid, $resp) = @_;
2477 my $data = $resp->{'return'} || [];
2478 my $totalrdbytes = 0;
2479 my $totalwrbytes = 0;
2481 for my $blockstat (@$data) {
2482 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2483 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2485 $blockstat->{device
} =~ s/drive-//;
2486 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2488 $res->{$vmid}->{diskread
} = $totalrdbytes;
2489 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2492 my $statuscb = sub {
2493 my ($vmid, $resp) = @_;
2495 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2496 # this fails if ballon driver is not loaded, so this must be
2497 # the last commnand (following command are aborted if this fails).
2498 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2500 my $status = 'unknown';
2501 if (!defined($status = $resp->{'return'}->{status
})) {
2502 warn "unable to get VM status\n";
2506 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2509 foreach my $vmid (keys %$list) {
2510 next if $opt_vmid && ($vmid ne $opt_vmid);
2511 next if !$res->{$vmid}->{pid
}; # not running
2512 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2515 $qmpclient->queue_execute(undef, 1);
2517 foreach my $vmid (keys %$list) {
2518 next if $opt_vmid && ($vmid ne $opt_vmid);
2519 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2526 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2529 my $current_size = 1024;
2530 my $dimm_size = 512;
2531 return if $current_size == $memory;
2533 for (my $j = 0; $j < 8; $j++) {
2534 for (my $i = 0; $i < 32; $i++) {
2535 my $name = "dimm${dimm_id}";
2537 my $numanode = $i % $sockets;
2538 $current_size += $dimm_size;
2539 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2540 return $current_size if $current_size >= $memory;
2546 sub foreach_reverse_dimm
{
2547 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2550 my $current_size = 4177920;
2551 my $dimm_size = 65536;
2552 return if $current_size == $memory;
2554 for (my $j = 0; $j < 8; $j++) {
2555 for (my $i = 0; $i < 32; $i++) {
2556 my $name = "dimm${dimm_id}";
2558 my $numanode = $i % $sockets;
2559 $current_size -= $dimm_size;
2560 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2561 return $current_size if $current_size <= $memory;
2568 my ($conf, $func) = @_;
2570 foreach my $ds (keys %$conf) {
2571 next if !valid_drivename
($ds);
2573 my $drive = parse_drive
($ds, $conf->{$ds});
2576 &$func($ds, $drive);
2581 my ($conf, $func) = @_;
2585 my $test_volid = sub {
2586 my ($volid, $is_cdrom) = @_;
2590 $volhash->{$volid} = $is_cdrom || 0;
2593 foreach_drive
($conf, sub {
2594 my ($ds, $drive) = @_;
2595 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2598 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2599 my $snap = $conf->{snapshots
}->{$snapname};
2600 &$test_volid($snap->{vmstate
}, 0);
2601 foreach_drive
($snap, sub {
2602 my ($ds, $drive) = @_;
2603 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2607 foreach my $volid (keys %$volhash) {
2608 &$func($volid, $volhash->{$volid});
2612 sub vga_conf_has_spice
{
2615 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2620 sub config_to_command
{
2621 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2624 my $globalFlags = [];
2625 my $machineFlags = [];
2631 my $kvmver = kvm_user_version
();
2632 my $vernum = 0; # unknown
2633 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2634 $vernum = $1*1000000+$2*1000;
2635 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2636 $vernum = $1*1000000+$2*1000+$3;
2639 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2641 my $have_ovz = -f
'/proc/vz/vestat';
2643 my $q35 = machine_type_is_q35
($conf);
2644 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2645 my $machine_type = $forcemachine || $conf->{machine
};
2647 my $cpuunits = defined($conf->{cpuunits
}) ?
2648 $conf->{cpuunits
} : $defaults->{cpuunits
};
2650 push @$cmd, '/usr/bin/systemd-run';
2651 push @$cmd, '--scope';
2652 push @$cmd, '--slice', "qemu";
2653 push @$cmd, '--unit', $vmid;
2654 push @$cmd, '-p', "CPUShares=$cpuunits";
2655 if ($conf->{cpulimit
}) {
2656 my $cpulimit = int($conf->{cpulimit
} * 100);
2657 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2660 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
2661 # load new efi bios files on migration. So this hack is required to allow
2662 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
2663 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
2664 my $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
2666 push @$cmd, '/usr/bin/kvm';
2668 push @$cmd, '-id', $vmid;
2672 my $qmpsocket = qmp_socket
($vmid);
2673 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2674 push @$cmd, '-mon', "chardev=qmp,mode=control";
2676 my $socket = vnc_socket
($vmid);
2677 push @$cmd, '-vnc', "unix:$socket,x509,password";
2679 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2681 push @$cmd, '-daemonize';
2683 if ($conf->{smbios1
}) {
2684 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2688 # the q35 chipset support native usb2, so we enable usb controller
2689 # by default for this machine type
2690 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2692 $pciaddr = print_pci_addr
("piix3", $bridges);
2693 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2696 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2697 next if !$conf->{"usb$i"};
2700 # include usb device config
2701 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2704 my $vga = $conf->{vga
};
2706 my $qxlnum = vga_conf_has_spice
($vga);
2707 $vga = 'qxl' if $qxlnum;
2710 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2711 $conf->{ostype
} eq 'win7' ||
2712 $conf->{ostype
} eq 'w2k8')) {
2719 # enable absolute mouse coordinates (needed by vnc)
2721 if (defined($conf->{tablet
})) {
2722 $tablet = $conf->{tablet
};
2724 $tablet = $defaults->{tablet
};
2725 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2726 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2729 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2732 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2733 my $d = parse_hostpci
($conf->{"hostpci$i"});
2736 my $pcie = $d->{pcie
};
2738 die "q35 machine model is not enabled" if !$q35;
2739 $pciaddr = print_pcie_addr
("hostpci$i");
2741 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2744 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2745 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2746 if ($xvga && $xvga ne '') {
2747 push @$cpuFlags, 'kvm=off';
2750 my $pcidevices = $d->{pciid
};
2751 my $multifunction = 1 if @$pcidevices > 1;
2754 foreach my $pcidevice (@$pcidevices) {
2756 my $id = "hostpci$i";
2757 $id .= ".$j" if $multifunction;
2758 my $addr = $pciaddr;
2759 $addr .= ".$j" if $multifunction;
2760 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2763 $devicestr .= "$rombar$xvga";
2764 $devicestr .= ",multifunction=on" if $multifunction;
2767 push @$devices, '-device', $devicestr;
2773 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2774 my $d = parse_usb_device
($conf->{"usb$i"});
2776 if ($d->{vendorid
} && $d->{productid
}) {
2777 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2778 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2779 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2780 } elsif ($d->{spice
}) {
2781 # usb redir support for spice
2782 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2783 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2788 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2789 if (my $path = $conf->{"serial$i"}) {
2790 if ($path eq 'socket') {
2791 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2792 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2793 push @$devices, '-device', "isa-serial,chardev=serial$i";
2795 die "no such serial device\n" if ! -c
$path;
2796 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2797 push @$devices, '-device', "isa-serial,chardev=serial$i";
2803 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2804 if (my $path = $conf->{"parallel$i"}) {
2805 die "no such parallel device\n" if ! -c
$path;
2806 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2807 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2808 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2812 my $vmname = $conf->{name
} || "vm$vmid";
2814 push @$cmd, '-name', $vmname;
2817 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2818 $sockets = $conf->{sockets
} if $conf->{sockets
};
2820 my $cores = $conf->{cores
} || 1;
2822 my $maxcpus = $sockets * $cores;
2824 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2826 my $allowed_vcpus = $cpuinfo->{cpus
};
2828 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2829 if ($allowed_vcpus < $maxcpus);
2831 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2833 push @$cmd, '-nodefaults';
2835 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2837 my $bootindex_hash = {};
2839 foreach my $o (split(//, $bootorder)) {
2840 $bootindex_hash->{$o} = $i*100;
2844 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2846 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2848 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2850 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2853 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2855 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2856 my $useLocaltime = $conf->{localtime};
2858 if (my $ost = $conf->{ostype
}) {
2859 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2861 if ($ost =~ m/^w/) { # windows
2862 $useLocaltime = 1 if !defined($conf->{localtime});
2864 # use time drift fix when acpi is enabled
2865 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2866 $tdf = 1 if !defined($conf->{tdf
});
2870 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2872 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2873 push @$cmd, '-no-hpet';
2874 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2875 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2876 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2877 push @$cpuFlags , 'hv_time' if !$nokvm;
2880 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2884 if ($ost eq 'win7' || $ost eq 'win8') {
2885 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2889 push @$rtcFlags, 'driftfix=slew' if $tdf;
2892 push @$machineFlags, 'accel=tcg';
2894 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2897 if ($machine_type) {
2898 push @$machineFlags, "type=${machine_type}";
2901 if ($conf->{startdate
}) {
2902 push @$rtcFlags, "base=$conf->{startdate}";
2903 } elsif ($useLocaltime) {
2904 push @$rtcFlags, 'base=localtime';
2907 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2908 $cpu = $conf->{cpu
} if $conf->{cpu
};
2910 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2912 push @$cpuFlags , '-x2apic'
2913 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2915 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2917 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2919 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2921 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2922 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2923 push @$cpuFlags , '-kvm_steal_time' if !$nokvm;
2926 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2928 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2930 push @$cmd, '-cpu', $cpu;
2932 my $memory = $conf->{memory
} || $defaults->{memory
};
2933 my $static_memory = 0;
2934 my $dimm_memory = 0;
2936 if ($hotplug_features->{memory
}) {
2937 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2938 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2939 $static_memory = $STATICMEM;
2940 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2941 $dimm_memory = $memory - $static_memory;
2942 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2946 $static_memory = $memory;
2947 push @$cmd, '-m', $static_memory;
2950 if ($conf->{numa
}) {
2952 my $numa_totalmemory = undef;
2953 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2954 next if !$conf->{"numa$i"};
2955 my $numa = parse_numa
($conf->{"numa$i"});
2958 die "missing numa node$i memory value\n" if !$numa->{memory
};
2959 my $numa_memory = $numa->{memory
};
2960 $numa_totalmemory += $numa_memory;
2961 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2964 my $cpus_start = $numa->{cpus
}->{start
};
2965 die "missing numa node$i cpus\n" if !defined($cpus_start);
2966 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2967 my $cpus = $cpus_start;
2968 if (defined($cpus_end)) {
2969 $cpus .= "-$cpus_end";
2970 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2974 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2975 if (defined($hostnodes_start)) {
2976 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2977 my $hostnodes = $hostnodes_start;
2978 if (defined($hostnodes_end)) {
2979 $hostnodes .= "-$hostnodes_end";
2980 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2983 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2984 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2985 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2989 my $policy = $numa->{policy
};
2990 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2991 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2994 push @$cmd, '-object', $numa_object;
2995 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2998 die "total memory for NUMA nodes must be equal to vm static memory\n"
2999 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3001 #if no custom tology, we split memory and cores across numa nodes
3002 if(!$numa_totalmemory) {
3004 my $numa_memory = ($static_memory / $sockets) . "M";
3006 for (my $i = 0; $i < $sockets; $i++) {
3008 my $cpustart = ($cores * $i);
3009 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3010 my $cpus = $cpustart;
3011 $cpus .= "-$cpuend" if $cpuend;
3013 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3014 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3019 if ($hotplug_features->{memory
}) {
3020 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3021 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3022 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3023 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3025 #if dimm_memory is not aligned to dimm map
3026 if($current_size > $memory) {
3027 $conf->{memory
} = $current_size;
3028 update_config_nolock
($vmid, $conf, 1);
3033 push @$cmd, '-S' if $conf->{freeze
};
3035 # set keyboard layout
3036 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3037 push @$cmd, '-k', $kb if $kb;
3040 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3041 #push @$cmd, '-soundhw', 'es1370';
3042 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3044 if($conf->{agent
}) {
3045 my $qgasocket = qmp_socket
($vmid, 1);
3046 my $pciaddr = print_pci_addr
("qga0", $bridges);
3047 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3048 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3049 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3056 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3057 for(my $i = 1; $i < $qxlnum; $i++){
3058 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3059 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3062 # assume other OS works like Linux
3063 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3064 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3068 my $pciaddr = print_pci_addr
("spice", $bridges);
3070 my $nodename = PVE
::INotify
::nodename
();
3071 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3072 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3074 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3076 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3077 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3078 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3081 # enable balloon by default, unless explicitly disabled
3082 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3083 $pciaddr = print_pci_addr
("balloon0", $bridges);
3084 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3087 if ($conf->{watchdog
}) {
3088 my $wdopts = parse_watchdog
($conf->{watchdog
});
3089 $pciaddr = print_pci_addr
("watchdog", $bridges);
3090 my $watchdog = $wdopts->{model
} || 'i6300esb';
3091 push @$devices, '-device', "$watchdog$pciaddr";
3092 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3096 my $scsicontroller = {};
3097 my $ahcicontroller = {};
3098 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3100 # Add iscsi initiator name if available
3101 if (my $initiator = get_initiator_name
()) {
3102 push @$devices, '-iscsi', "initiator-name=$initiator";
3105 foreach_drive
($conf, sub {
3106 my ($ds, $drive) = @_;
3108 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3109 push @$vollist, $drive->{file
};
3112 $use_virtio = 1 if $ds =~ m/^virtio/;
3114 if (drive_is_cdrom
($drive)) {
3115 if ($bootindex_hash->{d
}) {
3116 $drive->{bootindex
} = $bootindex_hash->{d
};
3117 $bootindex_hash->{d
} += 1;
3120 if ($bootindex_hash->{c
}) {
3121 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3122 $bootindex_hash->{c
} += 1;
3126 if($drive->{interface
} eq 'virtio'){
3127 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3130 if ($drive->{interface
} eq 'scsi') {
3132 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3134 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3135 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3138 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3139 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3140 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3144 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3145 $queues = ",num_queues=$drive->{queues}";
3148 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3149 $scsicontroller->{$controller}=1;
3152 if ($drive->{interface
} eq 'sata') {
3153 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3154 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3155 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3156 $ahcicontroller->{$controller}=1;
3159 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3160 push @$devices, '-drive',$drive_cmd;
3161 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3164 for (my $i = 0; $i < $MAX_NETS; $i++) {
3165 next if !$conf->{"net$i"};
3166 my $d = parse_net
($conf->{"net$i"});
3169 $use_virtio = 1 if $d->{model
} eq 'virtio';
3171 if ($bootindex_hash->{n
}) {
3172 $d->{bootindex
} = $bootindex_hash->{n
};
3173 $bootindex_hash->{n
} += 1;
3176 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3177 push @$devices, '-netdev', $netdevfull;
3179 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3180 push @$devices, '-device', $netdevicefull;
3185 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3190 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3192 while (my ($k, $v) = each %$bridges) {
3193 $pciaddr = print_pci_addr
("pci.$k");
3194 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3199 if ($conf->{args
}) {
3200 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3204 push @$cmd, @$devices;
3205 push @$cmd, '-rtc', join(',', @$rtcFlags)
3206 if scalar(@$rtcFlags);
3207 push @$cmd, '-machine', join(',', @$machineFlags)
3208 if scalar(@$machineFlags);
3209 push @$cmd, '-global', join(',', @$globalFlags)
3210 if scalar(@$globalFlags);
3212 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3217 return "${var_run_tmpdir}/$vmid.vnc";
3223 my $res = vm_mon_cmd
($vmid, 'query-spice');
3225 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3229 my ($vmid, $qga) = @_;
3230 my $sockettype = $qga ?
'qga' : 'qmp';
3231 return "${var_run_tmpdir}/$vmid.$sockettype";
3236 return "${var_run_tmpdir}/$vmid.pid";
3239 sub vm_devices_list
{
3242 my $res = vm_mon_cmd
($vmid, 'query-pci');
3244 foreach my $pcibus (@$res) {
3245 foreach my $device (@{$pcibus->{devices
}}) {
3246 next if !$device->{'qdev_id'};
3247 if ($device->{'pci_bridge'}) {
3248 $devices->{$device->{'qdev_id'}} = 1;
3249 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3250 next if !$bridge_device->{'qdev_id'};
3251 $devices->{$bridge_device->{'qdev_id'}} = 1;
3252 $devices->{$device->{'qdev_id'}}++;
3255 $devices->{$device->{'qdev_id'}} = 1;
3260 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3261 foreach my $block (@$resblock) {
3262 if($block->{device
} =~ m/^drive-(\S+)/){
3267 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3268 foreach my $mice (@$resmice) {
3269 if ($mice->{name
} eq 'QEMU HID Tablet') {
3270 $devices->{tablet
} = 1;
3279 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3281 my $q35 = machine_type_is_q35
($conf);
3283 my $devices_list = vm_devices_list
($vmid);
3284 return 1 if defined($devices_list->{$deviceid});
3286 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3288 if ($deviceid eq 'tablet') {
3290 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3292 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3294 qemu_iothread_add
($vmid, $deviceid, $device);
3296 qemu_driveadd
($storecfg, $vmid, $device);
3297 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3299 qemu_deviceadd
($vmid, $devicefull);
3300 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3302 eval { qemu_drivedel
($vmid, $deviceid); };
3307 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3310 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3311 my $pciaddr = print_pci_addr
($deviceid);
3312 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3314 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3316 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3317 qemu_iothread_add
($vmid, $deviceid, $device);
3318 $devicefull .= ",iothread=iothread-$deviceid";
3321 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3322 $devicefull .= ",num_queues=$device->{queues}";
3325 qemu_deviceadd
($vmid, $devicefull);
3326 qemu_deviceaddverify
($vmid, $deviceid);
3328 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3330 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3331 qemu_driveadd
($storecfg, $vmid, $device);
3333 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3334 eval { qemu_deviceadd
($vmid, $devicefull); };
3336 eval { qemu_drivedel
($vmid, $deviceid); };
3341 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3343 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3344 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3345 qemu_deviceadd
($vmid, $netdevicefull);
3346 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3348 eval { qemu_netdevdel
($vmid, $deviceid); };
3353 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3356 my $pciaddr = print_pci_addr
($deviceid);
3357 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3359 qemu_deviceadd
($vmid, $devicefull);
3360 qemu_deviceaddverify
($vmid, $deviceid);
3363 die "can't hotplug device '$deviceid'\n";
3369 # fixme: this should raise exceptions on error!
3370 sub vm_deviceunplug
{
3371 my ($vmid, $conf, $deviceid) = @_;
3373 my $devices_list = vm_devices_list
($vmid);
3374 return 1 if !defined($devices_list->{$deviceid});
3376 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3378 if ($deviceid eq 'tablet') {
3380 qemu_devicedel
($vmid, $deviceid);
3382 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3384 qemu_devicedel
($vmid, $deviceid);
3385 qemu_devicedelverify
($vmid, $deviceid);
3386 qemu_drivedel
($vmid, $deviceid);
3387 qemu_iothread_del
($conf, $vmid, $deviceid);
3389 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3391 qemu_devicedel
($vmid, $deviceid);
3392 qemu_devicedelverify
($vmid, $deviceid);
3393 qemu_iothread_del
($conf, $vmid, $deviceid);
3395 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3397 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3398 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3399 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3401 qemu_devicedel
($vmid, $deviceid);
3402 qemu_drivedel
($vmid, $deviceid);
3403 qemu_deletescsihw
($conf, $vmid, $deviceid);
3405 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3407 qemu_devicedel
($vmid, $deviceid);
3408 qemu_devicedelverify
($vmid, $deviceid);
3409 qemu_netdevdel
($vmid, $deviceid);
3412 die "can't unplug device '$deviceid'\n";
3418 sub qemu_deviceadd
{
3419 my ($vmid, $devicefull) = @_;
3421 $devicefull = "driver=".$devicefull;
3422 my %options = split(/[=,]/, $devicefull);
3424 vm_mon_cmd
($vmid, "device_add" , %options);
3427 sub qemu_devicedel
{
3428 my ($vmid, $deviceid) = @_;
3430 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3433 sub qemu_iothread_add
{
3434 my($vmid, $deviceid, $device) = @_;
3436 if ($device->{iothread
}) {
3437 my $iothreads = vm_iothreads_list
($vmid);
3438 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3442 sub qemu_iothread_del
{
3443 my($conf, $vmid, $deviceid) = @_;
3445 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3446 if ($device->{iothread
}) {
3447 my $iothreads = vm_iothreads_list
($vmid);
3448 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3452 sub qemu_objectadd
{
3453 my($vmid, $objectid, $qomtype) = @_;
3455 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3460 sub qemu_objectdel
{
3461 my($vmid, $objectid) = @_;
3463 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3469 my ($storecfg, $vmid, $device) = @_;
3471 my $drive = print_drive_full
($storecfg, $vmid, $device);
3472 $drive =~ s/\\/\\\\/g;
3473 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3475 # If the command succeeds qemu prints: "OK
"
3476 return 1 if $ret =~ m/OK/s;
3478 die "adding drive failed
: $ret\n";
3482 my($vmid, $deviceid) = @_;
3484 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3487 return 1 if $ret eq "";
3489 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3490 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3492 die "deleting drive
$deviceid failed
: $ret\n";
3495 sub qemu_deviceaddverify {
3496 my ($vmid, $deviceid) = @_;
3498 for (my $i = 0; $i <= 5; $i++) {
3499 my $devices_list = vm_devices_list($vmid);
3500 return 1 if defined($devices_list->{$deviceid});
3504 die "error on hotplug device
'$deviceid'\n";
3508 sub qemu_devicedelverify {
3509 my ($vmid, $deviceid) = @_;
3511 # need to verify that the device is correctly removed as device_del
3512 # is async and empty return is not reliable
3514 for (my $i = 0; $i <= 5; $i++) {
3515 my $devices_list = vm_devices_list($vmid);
3516 return 1 if !defined($devices_list->{$deviceid});
3520 die "error on hot-unplugging device
'$deviceid'\n";
3523 sub qemu_findorcreatescsihw {
3524 my ($storecfg, $conf, $vmid, $device) = @_;
3526 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3528 my $scsihwid="$controller_prefix$controller";
3529 my $devices_list = vm_devices_list($vmid);
3531 if(!defined($devices_list->{$scsihwid})) {
3532 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3538 sub qemu_deletescsihw {
3539 my ($conf, $vmid, $opt) = @_;
3541 my $device = parse_drive($opt, $conf->{$opt});
3543 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3544 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3548 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3550 my $devices_list = vm_devices_list($vmid);
3551 foreach my $opt (keys %{$devices_list}) {
3552 if (PVE::QemuServer::valid_drivename($opt)) {
3553 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3554 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3560 my $scsihwid="scsihw
$controller";
3562 vm_deviceunplug($vmid, $conf, $scsihwid);
3567 sub qemu_add_pci_bridge {
3568 my ($storecfg, $conf, $vmid, $device) = @_;
3574 print_pci_addr($device, $bridges);
3576 while (my ($k, $v) = each %$bridges) {
3579 return 1 if !defined($bridgeid) || $bridgeid < 1;
3581 my $bridge = "pci
.$bridgeid";
3582 my $devices_list = vm_devices_list($vmid);
3584 if (!defined($devices_list->{$bridge})) {
3585 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3591 sub qemu_set_link_status {
3592 my ($vmid, $device, $up) = @_;
3594 vm_mon_cmd($vmid, "set_link
", name => $device,
3595 up => $up ? JSON::true : JSON::false);
3598 sub qemu_netdevadd {
3599 my ($vmid, $conf, $device, $deviceid) = @_;
3601 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3602 my %options = split(/[=,]/, $netdev);
3604 vm_mon_cmd($vmid, "netdev_add
", %options);
3608 sub qemu_netdevdel {
3609 my ($vmid, $deviceid) = @_;
3611 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3614 sub qemu_cpu_hotplug {
3615 my ($vmid, $conf, $vcpus) = @_;
3618 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3619 $sockets = $conf->{sockets} if $conf->{sockets};
3620 my $cores = $conf->{cores} || 1;
3621 my $maxcpus = $sockets * $cores;
3623 $vcpus = $maxcpus if !$vcpus;
3625 die "you can
't add more vcpus than maxcpus\n"
3626 if $vcpus > $maxcpus;
3628 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3629 die "online cpu unplug is not yet possible\n"
3630 if $vcpus < $currentvcpus;
3632 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3633 die "vcpus in running vm is different than configuration\n"
3634 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3636 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3637 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3641 sub qemu_memory_hotplug {
3642 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3644 return $value if !check_running($vmid);
3646 my $memory = $conf->{memory} || $defaults->{memory};
3647 $value = $defaults->{memory} if !$value;
3648 return $value if $value == $memory;
3650 my $static_memory = $STATICMEM;
3651 my $dimm_memory = $memory - $static_memory;
3653 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3654 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3658 $sockets = $conf->{sockets} if $conf->{sockets};
3660 if($value > $memory) {
3662 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3663 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3665 return if $current_size <= $conf->{memory};
3667 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3669 eval { qemu_objectdel($vmid, "mem-
$name"); };
3673 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3675 eval { qemu_objectdel($vmid, "mem-
$name"); };
3678 #update conf after each succesful module hotplug
3679 $conf->{memory} = $current_size;
3680 update_config_nolock($vmid, $conf, 1);
3685 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3686 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3688 return if $current_size >= $conf->{memory};
3689 print "try to unplug memory dimm
$name\n";
3693 eval { qemu_devicedel($vmid, $name) };
3695 my $dimm_list = qemu_dimm_list($vmid);
3696 last if !$dimm_list->{$name};
3697 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3701 #update conf after each succesful module unplug
3702 $conf->{memory} = $current_size;
3704 eval { qemu_objectdel($vmid, "mem-
$name"); };
3705 update_config_nolock($vmid, $conf, 1);
3710 sub qemu_dimm_list {
3713 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3716 foreach my $dimm (@$dimmarray) {
3718 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3719 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3720 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3721 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3722 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3727 sub qemu_block_set_io_throttle {
3728 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3730 return if !check_running($vmid) ;
3732 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));
3736 # old code, only used to shutdown old VM after update
3738 my ($fh, $timeout) = @_;
3740 my $sel = new IO::Select;
3747 while (scalar (@ready = $sel->can_read($timeout))) {
3749 if ($count = $fh->sysread($buf, 8192)) {
3750 if ($buf =~ /^(.*)\(qemu\) $/s) {
3757 if (!defined($count)) {
3764 die "monitor
read timeout
\n" if !scalar(@ready);
3769 # old code, only used to shutdown old VM after update
3770 sub vm_monitor_command {
3771 my ($vmid, $cmdstr, $nocheck) = @_;
3776 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3778 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3780 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3781 die "unable to
connect to VM
$vmid socket - $!\n";
3785 # hack: migrate sometime blocks the monitor (when migrate_downtime
3787 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3788 $timeout = 60*60; # 1 hour
3792 my $data = __read_avail($sock, $timeout);
3794 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3795 die "got unexpected qemu monitor banner
\n";
3798 my $sel = new IO::Select;
3801 if (!scalar(my @ready = $sel->can_write($timeout))) {
3802 die "monitor
write error
- timeout
";
3805 my $fullcmd = "$cmdstr\r";
3807 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3810 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3811 die "monitor
write error
- $!";
3814 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3818 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3819 $timeout = 60*60; # 1 hour
3820 } elsif ($cmdstr =~ m/^(eject|change)/) {
3821 $timeout = 60; # note: cdrom mount command is slow
3823 if ($res = __read_avail($sock, $timeout)) {
3825 my @lines = split("\r?
\n", $res);
3827 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3829 $res = join("\n", @lines);
3837 syslog("err
", "VM
$vmid monitor command failed
- $err");
3844 sub qemu_block_resize {
3845 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3847 my $running = check_running($vmid);
3849 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3851 return if !$running;
3853 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3857 sub qemu_volume_snapshot {
3858 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3860 my $running = check_running($vmid);
3862 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3863 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3865 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3869 sub qemu_volume_snapshot_delete {
3870 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3872 my $running = check_running($vmid);
3874 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3876 return if !$running;
3878 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3881 sub set_migration_caps {
3887 "auto-converge
" => 1,
3889 "x-rdma-pin-all
" => 0,
3894 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3896 for my $supported_capability (@$supported_capabilities) {
3898 capability => $supported_capability->{capability},
3899 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3903 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3906 my $fast_plug_option = {
3915 # hotplug changes in [PENDING]
3916 # $selection hash can be used to only apply specified options, for
3917 # example: { cores => 1 } (only apply changed 'cores')
3918 # $errors ref is used to return error messages
3919 sub vmconfig_hotplug_pending {
3920 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3922 my $defaults = load_defaults();
3924 # commit values which do not have any impact on running VM first
3925 # Note: those option cannot raise errors, we we do not care about
3926 # $selection and always apply them.
3928 my $add_error = sub {
3929 my ($opt, $msg) = @_;
3930 $errors->{$opt} = "hotplug problem
- $msg";
3934 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3935 if ($fast_plug_option->{$opt}) {
3936 $conf->{$opt} = $conf->{pending}->{$opt};
3937 delete $conf->{pending}->{$opt};
3943 update_config_nolock($vmid, $conf, 1);
3944 $conf = load_config($vmid); # update/reload
3947 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3949 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3950 while (my ($opt, $force) = each %$pending_delete_hash) {
3951 next if $selection && !$selection->{$opt};
3953 if ($opt eq 'hotplug') {
3954 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3955 } elsif ($opt eq 'tablet') {
3956 die "skip
\n" if !$hotplug_features->{usb};
3957 if ($defaults->{tablet}) {
3958 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3960 vm_deviceunplug($vmid, $conf, $opt);
3962 } elsif ($opt eq 'vcpus') {
3963 die "skip
\n" if !$hotplug_features->{cpu};
3964 qemu_cpu_hotplug($vmid, $conf, undef);
3965 } elsif ($opt eq 'balloon') {
3966 # enable balloon device is not hotpluggable
3967 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3968 } elsif ($fast_plug_option->{$opt}) {
3970 } elsif ($opt =~ m/^net(\d+)$/) {
3971 die "skip
\n" if !$hotplug_features->{network};
3972 vm_deviceunplug($vmid, $conf, $opt);
3973 } elsif (valid_drivename($opt)) {
3974 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3975 vm_deviceunplug($vmid, $conf, $opt);
3976 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3977 } elsif ($opt =~ m/^memory$/) {
3978 die "skip
\n" if !$hotplug_features->{memory};
3979 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3980 } elsif ($opt eq 'cpuunits') {
3981 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3982 } elsif ($opt eq 'cpulimit') {
3983 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3989 &$add_error($opt, $err) if $err ne "skip
\n";
3991 # save new config if hotplug was successful
3992 delete $conf->{$opt};
3993 vmconfig_undelete_pending_option($conf, $opt);
3994 update_config_nolock($vmid, $conf, 1);
3995 $conf = load_config($vmid); # update/reload
3999 foreach my $opt (keys %{$conf->{pending}}) {
4000 next if $selection && !$selection->{$opt};
4001 my $value = $conf->{pending}->{$opt};
4003 if ($opt eq 'hotplug') {
4004 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4005 } elsif ($opt eq 'tablet') {
4006 die "skip
\n" if !$hotplug_features->{usb};
4008 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4009 } elsif ($value == 0) {
4010 vm_deviceunplug($vmid, $conf, $opt);
4012 } elsif ($opt eq 'vcpus') {
4013 die "skip
\n" if !$hotplug_features->{cpu};
4014 qemu_cpu_hotplug($vmid, $conf, $value);
4015 } elsif ($opt eq 'balloon') {
4016 # enable/disable balloning device is not hotpluggable
4017 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4018 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4019 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4021 # allow manual ballooning if shares is set to zero
4022 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4023 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4024 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4026 } elsif ($opt =~ m/^net(\d+)$/) {
4027 # some changes can be done without hotplug
4028 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4029 $vmid, $opt, $value);
4030 } elsif (valid_drivename($opt)) {
4031 # some changes can be done without hotplug
4032 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4033 $vmid, $opt, $value, 1);
4034 } elsif ($opt =~ m/^memory$/) { #dimms
4035 die "skip
\n" if !$hotplug_features->{memory};
4036 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4037 } elsif ($opt eq 'cpuunits') {
4038 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4039 } elsif ($opt eq 'cpulimit') {
4040 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4041 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4043 die "skip
\n"; # skip non-hot-pluggable options
4047 &$add_error($opt, $err) if $err ne "skip
\n";
4049 # save new config if hotplug was successful
4050 $conf->{$opt} = $value;
4051 delete $conf->{pending}->{$opt};
4052 update_config_nolock($vmid, $conf, 1);
4053 $conf = load_config($vmid); # update/reload
4058 sub try_deallocate_drive {
4059 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4061 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4062 my $volid = $drive->{file};
4063 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4064 my $sid = PVE::Storage::parse_volume_id($volid);
4065 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4067 # check if the disk is really unused
4068 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4069 my $path = PVE::Storage::path($storecfg, $volid);
4070 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4071 if $used_paths->{$path};
4072 PVE::Storage::vdisk_free($storecfg, $volid);
4075 # If vm is not owner of this disk remove from config
4083 sub vmconfig_delete_or_detach_drive {
4084 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4086 my $drive = parse_drive($opt, $conf->{$opt});
4088 my $rpcenv = PVE::RPCEnvironment::get();
4089 my $authuser = $rpcenv->get_user();
4092 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4093 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4095 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4099 sub vmconfig_apply_pending {
4100 my ($vmid, $conf, $storecfg) = @_;
4104 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4105 while (my ($opt, $force) = each %$pending_delete_hash) {
4106 die "internal error
" if $opt =~ m/^unused/;
4107 $conf = load_config($vmid); # update/reload
4108 if (!defined($conf->{$opt})) {
4109 vmconfig_undelete_pending_option($conf, $opt);
4110 update_config_nolock($vmid, $conf, 1);
4111 } elsif (valid_drivename($opt)) {
4112 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4113 vmconfig_undelete_pending_option($conf, $opt);
4114 delete $conf->{$opt};
4115 update_config_nolock($vmid, $conf, 1);
4117 vmconfig_undelete_pending_option($conf, $opt);
4118 delete $conf->{$opt};
4119 update_config_nolock($vmid, $conf, 1);
4123 $conf = load_config($vmid); # update/reload
4125 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4126 $conf = load_config($vmid); # update/reload
4128 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4129 # skip if nothing changed
4130 } elsif (valid_drivename($opt)) {
4131 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4132 if defined($conf->{$opt});
4133 $conf->{$opt} = $conf->{pending}->{$opt};
4135 $conf->{$opt} = $conf->{pending}->{$opt};
4138 delete $conf->{pending}->{$opt};
4139 update_config_nolock($vmid, $conf, 1);
4143 my $safe_num_ne = sub {
4146 return 0 if !defined($a) && !defined($b);
4147 return 1 if !defined($a);
4148 return 1 if !defined($b);
4153 my $safe_string_ne = sub {
4156 return 0 if !defined($a) && !defined($b);
4157 return 1 if !defined($a);
4158 return 1 if !defined($b);
4163 sub vmconfig_update_net {
4164 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4166 my $newnet = parse_net($value);
4168 if ($conf->{$opt}) {
4169 my $oldnet = parse_net($conf->{$opt});
4171 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4172 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4173 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4174 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4176 # for non online change, we try to hot-unplug
4177 die "skip
\n" if !$hotplug;
4178 vm_deviceunplug($vmid, $conf, $opt);
4181 die "internal error
" if $opt !~ m/net(\d+)/;
4182 my $iface = "tap
${vmid
}i
$1";
4184 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4185 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4188 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4189 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4190 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4191 PVE::Network::tap_unplug($iface);
4192 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4195 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4196 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4204 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4210 sub vmconfig_update_disk {
4211 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4213 # fixme: do we need force?
4215 my $drive = parse_drive($opt, $value);
4217 if ($conf->{$opt}) {
4219 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4221 my $media = $drive->{media} || 'disk';
4222 my $oldmedia = $old_drive->{media} || 'disk';
4223 die "unable to change media type
\n" if $media ne $oldmedia;
4225 if (!drive_is_cdrom($old_drive)) {
4227 if ($drive->{file} ne $old_drive->{file}) {
4229 die "skip
\n" if !$hotplug;
4231 # unplug and register as unused
4232 vm_deviceunplug($vmid, $conf, $opt);
4233 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4236 # update existing disk
4238 # skip non hotpluggable value
4239 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4240 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4241 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4242 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4247 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4248 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4249 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4250 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4251 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4252 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4253 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4254 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4255 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4256 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4257 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4258 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4260 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4261 ($drive->{mbps} || 0)*1024*1024,
4262 ($drive->{mbps_rd} || 0)*1024*1024,
4263 ($drive->{mbps_wr} || 0)*1024*1024,
4264 $drive->{iops} || 0,
4265 $drive->{iops_rd} || 0,
4266 $drive->{iops_wr} || 0,
4267 ($drive->{mbps_max} || 0)*1024*1024,
4268 ($drive->{mbps_rd_max} || 0)*1024*1024,
4269 ($drive->{mbps_wr_max} || 0)*1024*1024,
4270 $drive->{iops_max} || 0,
4271 $drive->{iops_rd_max} || 0,
4272 $drive->{iops_wr_max} || 0);
4281 if ($drive->{file} eq 'none') {
4282 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4284 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4285 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4286 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4294 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4296 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4300 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4301 $forcemachine, $spice_ticket) = @_;
4303 lock_config($vmid, sub {
4304 my $conf = load_config($vmid, $migratedfrom);
4306 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4308 check_lock($conf) if !$skiplock;
4310 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4312 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4313 vmconfig_apply_pending($vmid, $conf, $storecfg);
4314 $conf = load_config($vmid); # update/reload
4317 my $defaults = load_defaults();
4319 # set environment variable useful inside network script
4320 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4322 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4324 my $migrate_port = 0;
4327 if ($statefile eq 'tcp') {
4328 my $localip = "localhost
";
4329 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4330 my $nodename = PVE::INotify::nodename();
4331 if ($datacenterconf->{migration_unsecure}) {
4332 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4333 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4335 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4336 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4337 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4338 push @$cmd, '-incoming', $migrate_uri;
4341 push @$cmd, '-loadstate', $statefile;
4348 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4349 my $d = parse_hostpci($conf->{"hostpci
$i"});
4351 my $pcidevices = $d->{pciid};
4352 foreach my $pcidevice (@$pcidevices) {
4353 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4355 my $info = pci_device_info("0000:$pciid");
4356 die "IOMMU
not present
\n" if !check_iommu_support();
4357 die "no pci device info
for device
'$pciid'\n" if !$info;
4358 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4359 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4363 PVE::Storage::activate_volumes($storecfg, $vollist);
4365 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4368 die "start failed
: $err" if $err;
4370 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4372 if ($statefile && $statefile ne 'tcp') {
4373 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4377 if ($migratedfrom) {
4380 set_migration_caps($vmid);
4385 print "spice listens on port
$spice_port\n";
4386 if ($spice_ticket) {
4387 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4388 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4394 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4395 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4396 if $conf->{balloon};
4399 foreach my $opt (keys %$conf) {
4400 next if $opt !~ m/^net\d+$/;
4401 my $nicconf = parse_net($conf->{$opt});
4402 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4406 vm_mon_cmd_nocheck($vmid, 'qom-set',
4407 path => "machine
/peripheral/balloon0
",
4408 property => "guest-stats-polling-interval
",
4409 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4415 my ($vmid, $execute, %params) = @_;
4417 my $cmd = { execute => $execute, arguments => \%params };
4418 vm_qmp_command($vmid, $cmd);
4421 sub vm_mon_cmd_nocheck {
4422 my ($vmid, $execute, %params) = @_;
4424 my $cmd = { execute => $execute, arguments => \%params };
4425 vm_qmp_command($vmid, $cmd, 1);
4428 sub vm_qmp_command {
4429 my ($vmid, $cmd, $nocheck) = @_;
4434 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4435 $timeout = $cmd->{arguments}->{timeout};
4436 delete $cmd->{arguments}->{timeout};
4440 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4441 my $sname = qmp_socket($vmid);
4442 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4443 my $qmpclient = PVE::QMPClient->new();
4445 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4446 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4447 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4448 if scalar(%{$cmd->{arguments}});
4449 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4451 die "unable to open monitor socket\n";
4455 syslog("err", "VM $vmid qmp command failed - $err");
4462 sub vm_human_monitor_command {
4463 my ($vmid, $cmdline) = @_;
4468 execute => 'human-monitor-command
',
4469 arguments => { 'command-line
' => $cmdline},
4472 return vm_qmp_command($vmid, $cmd);
4475 sub vm_commandline {
4476 my ($storecfg, $vmid) = @_;
4478 my $conf = load_config($vmid);
4480 my $defaults = load_defaults();
4482 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4484 return join(' ', @$cmd);
4488 my ($vmid, $skiplock) = @_;
4490 lock_config($vmid, sub {
4492 my $conf = load_config($vmid);
4494 check_lock($conf) if !$skiplock;
4496 vm_mon_cmd($vmid, "system_reset");
4500 sub get_vm_volumes {
4504 foreach_volid($conf, sub {
4505 my ($volid, $is_cdrom) = @_;
4507 return if $volid =~ m|^/|;
4509 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4512 push @$vollist, $volid;
4518 sub vm_stop_cleanup {
4519 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4524 my $vollist = get_vm_volumes($conf);
4525 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4528 foreach my $ext (qw(mon qmp pid vnc qga)) {
4529 unlink "/var/run/qemu-server/${vmid}.$ext";
4532 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4534 warn $@ if $@; # avoid errors - just warn
4537 # Note: use $nockeck to skip tests if VM configuration file exists.
4538 # We need that when migration VMs to other nodes (files already moved)
4539 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4541 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4543 $force = 1 if !defined($force) && !$shutdown;
4546 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4547 kill 15, $pid if $pid;
4548 my $conf = load_config
($vmid, $migratedfrom);
4549 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4553 lock_config
($vmid, sub {
4555 my $pid = check_running
($vmid, $nocheck);
4560 $conf = load_config
($vmid);
4561 check_lock
($conf) if !$skiplock;
4562 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4563 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4564 $timeout = $opts->{down
} if $opts->{down
};
4568 $timeout = 60 if !defined($timeout);
4572 if (defined($conf) && $conf->{agent
}) {
4573 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4575 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4578 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4585 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4590 if ($count >= $timeout) {
4592 warn "VM still running - terminating now with SIGTERM\n";
4595 die "VM quit/powerdown failed - got timeout\n";
4598 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4603 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4606 die "VM quit/powerdown failed\n";
4614 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4619 if ($count >= $timeout) {
4620 warn "VM still running - terminating now with SIGKILL\n";
4625 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4630 my ($vmid, $skiplock) = @_;
4632 lock_config
($vmid, sub {
4634 my $conf = load_config
($vmid);
4636 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4638 vm_mon_cmd
($vmid, "stop");
4643 my ($vmid, $skiplock, $nocheck) = @_;
4645 lock_config
($vmid, sub {
4649 my $conf = load_config
($vmid);
4651 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4653 vm_mon_cmd
($vmid, "cont");
4656 vm_mon_cmd_nocheck
($vmid, "cont");
4662 my ($vmid, $skiplock, $key) = @_;
4664 lock_config
($vmid, sub {
4666 my $conf = load_config
($vmid);
4668 # there is no qmp command, so we use the human monitor command
4669 vm_human_monitor_command
($vmid, "sendkey $key");
4674 my ($storecfg, $vmid, $skiplock) = @_;
4676 lock_config
($vmid, sub {
4678 my $conf = load_config
($vmid);
4680 check_lock
($conf) if !$skiplock;
4682 if (!check_running
($vmid)) {
4683 destroy_vm
($storecfg, $vmid);
4685 die "VM $vmid is running - destroy failed\n";
4693 my ($filename, $buf) = @_;
4695 my $fh = IO
::File-
>new($filename, "w");
4696 return undef if !$fh;
4698 my $res = print $fh $buf;
4705 sub pci_device_info
{
4710 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4711 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4713 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4714 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4716 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4717 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4719 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4720 return undef if !defined($product) || $product !~ s/^0x//;
4725 product
=> $product,
4731 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4740 my $name = $dev->{name
};
4742 my $fn = "$pcisysfs/devices/$name/reset";
4744 return file_write
($fn, "1");
4747 sub pci_dev_bind_to_vfio
{
4750 my $name = $dev->{name
};
4752 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4754 if (!-d
$vfio_basedir) {
4755 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4757 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4759 my $testdir = "$vfio_basedir/$name";
4760 return 1 if -d
$testdir;
4762 my $data = "$dev->{vendor} $dev->{product}";
4763 return undef if !file_write
("$vfio_basedir/new_id", $data);
4765 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4766 if (!file_write
($fn, $name)) {
4767 return undef if -f
$fn;
4770 $fn = "$vfio_basedir/bind";
4771 if (! -d
$testdir) {
4772 return undef if !file_write
($fn, $name);
4778 sub pci_dev_group_bind_to_vfio
{
4781 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4783 if (!-d
$vfio_basedir) {
4784 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4786 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4788 # get IOMMU group devices
4789 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4790 my @devs = grep /^0000:/, readdir($D);
4793 foreach my $pciid (@devs) {
4794 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4796 # pci bridges, switches or root ports are not supported
4797 # they have a pci_bus subdirectory so skip them
4798 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4800 my $info = pci_device_info
($1);
4801 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4807 sub print_pci_addr
{
4808 my ($id, $bridges) = @_;
4812 piix3
=> { bus
=> 0, addr
=> 1 },
4813 #addr2 : first videocard
4814 balloon0
=> { bus
=> 0, addr
=> 3 },
4815 watchdog
=> { bus
=> 0, addr
=> 4 },
4816 scsihw0
=> { bus
=> 0, addr
=> 5 },
4817 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4818 scsihw1
=> { bus
=> 0, addr
=> 6 },
4819 ahci0
=> { bus
=> 0, addr
=> 7 },
4820 qga0
=> { bus
=> 0, addr
=> 8 },
4821 spice
=> { bus
=> 0, addr
=> 9 },
4822 virtio0
=> { bus
=> 0, addr
=> 10 },
4823 virtio1
=> { bus
=> 0, addr
=> 11 },
4824 virtio2
=> { bus
=> 0, addr
=> 12 },
4825 virtio3
=> { bus
=> 0, addr
=> 13 },
4826 virtio4
=> { bus
=> 0, addr
=> 14 },
4827 virtio5
=> { bus
=> 0, addr
=> 15 },
4828 hostpci0
=> { bus
=> 0, addr
=> 16 },
4829 hostpci1
=> { bus
=> 0, addr
=> 17 },
4830 net0
=> { bus
=> 0, addr
=> 18 },
4831 net1
=> { bus
=> 0, addr
=> 19 },
4832 net2
=> { bus
=> 0, addr
=> 20 },
4833 net3
=> { bus
=> 0, addr
=> 21 },
4834 net4
=> { bus
=> 0, addr
=> 22 },
4835 net5
=> { bus
=> 0, addr
=> 23 },
4836 vga1
=> { bus
=> 0, addr
=> 24 },
4837 vga2
=> { bus
=> 0, addr
=> 25 },
4838 vga3
=> { bus
=> 0, addr
=> 26 },
4839 hostpci2
=> { bus
=> 0, addr
=> 27 },
4840 hostpci3
=> { bus
=> 0, addr
=> 28 },
4841 #addr29 : usb-host (pve-usb.cfg)
4842 'pci.1' => { bus
=> 0, addr
=> 30 },
4843 'pci.2' => { bus
=> 0, addr
=> 31 },
4844 'net6' => { bus
=> 1, addr
=> 1 },
4845 'net7' => { bus
=> 1, addr
=> 2 },
4846 'net8' => { bus
=> 1, addr
=> 3 },
4847 'net9' => { bus
=> 1, addr
=> 4 },
4848 'net10' => { bus
=> 1, addr
=> 5 },
4849 'net11' => { bus
=> 1, addr
=> 6 },
4850 'net12' => { bus
=> 1, addr
=> 7 },
4851 'net13' => { bus
=> 1, addr
=> 8 },
4852 'net14' => { bus
=> 1, addr
=> 9 },
4853 'net15' => { bus
=> 1, addr
=> 10 },
4854 'net16' => { bus
=> 1, addr
=> 11 },
4855 'net17' => { bus
=> 1, addr
=> 12 },
4856 'net18' => { bus
=> 1, addr
=> 13 },
4857 'net19' => { bus
=> 1, addr
=> 14 },
4858 'net20' => { bus
=> 1, addr
=> 15 },
4859 'net21' => { bus
=> 1, addr
=> 16 },
4860 'net22' => { bus
=> 1, addr
=> 17 },
4861 'net23' => { bus
=> 1, addr
=> 18 },
4862 'net24' => { bus
=> 1, addr
=> 19 },
4863 'net25' => { bus
=> 1, addr
=> 20 },
4864 'net26' => { bus
=> 1, addr
=> 21 },
4865 'net27' => { bus
=> 1, addr
=> 22 },
4866 'net28' => { bus
=> 1, addr
=> 23 },
4867 'net29' => { bus
=> 1, addr
=> 24 },
4868 'net30' => { bus
=> 1, addr
=> 25 },
4869 'net31' => { bus
=> 1, addr
=> 26 },
4870 'virtio6' => { bus
=> 2, addr
=> 1 },
4871 'virtio7' => { bus
=> 2, addr
=> 2 },
4872 'virtio8' => { bus
=> 2, addr
=> 3 },
4873 'virtio9' => { bus
=> 2, addr
=> 4 },
4874 'virtio10' => { bus
=> 2, addr
=> 5 },
4875 'virtio11' => { bus
=> 2, addr
=> 6 },
4876 'virtio12' => { bus
=> 2, addr
=> 7 },
4877 'virtio13' => { bus
=> 2, addr
=> 8 },
4878 'virtio14' => { bus
=> 2, addr
=> 9 },
4879 'virtio15' => { bus
=> 2, addr
=> 10 },
4880 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4881 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4882 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4883 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4884 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4885 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4886 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4887 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4888 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4889 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4890 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4891 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4892 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4893 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4894 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4895 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4896 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4897 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4898 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4899 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4900 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4901 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4902 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4903 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4904 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4905 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4906 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4907 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4908 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4909 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4910 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4914 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4915 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4916 my $bus = $devices->{$id}->{bus
};
4917 $res = ",bus=pci.$bus,addr=$addr";
4918 $bridges->{$bus} = 1 if $bridges;
4924 sub print_pcie_addr
{
4929 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4930 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4931 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4932 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4935 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4936 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4937 my $bus = $devices->{$id}->{bus
};
4938 $res = ",bus=$bus,addr=$addr";
4944 # vzdump restore implementaion
4946 sub tar_archive_read_firstfile
{
4947 my $archive = shift;
4949 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4951 # try to detect archive type first
4952 my $pid = open (TMP
, "tar tf '$archive'|") ||
4953 die "unable to open file '$archive'\n";
4954 my $firstfile = <TMP
>;
4958 die "ERROR: archive contaions no data\n" if !$firstfile;
4964 sub tar_restore_cleanup
{
4965 my ($storecfg, $statfile) = @_;
4967 print STDERR
"starting cleanup\n";
4969 if (my $fd = IO
::File-
>new($statfile, "r")) {
4970 while (defined(my $line = <$fd>)) {
4971 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4974 if ($volid =~ m
|^/|) {
4975 unlink $volid || die 'unlink failed\n';
4977 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4979 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4981 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4983 print STDERR
"unable to parse line in statfile - $line";
4990 sub restore_archive
{
4991 my ($archive, $vmid, $user, $opts) = @_;
4993 my $format = $opts->{format
};
4996 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4997 $format = 'tar' if !$format;
4999 } elsif ($archive =~ m/\.tar$/) {
5000 $format = 'tar' if !$format;
5001 } elsif ($archive =~ m/.tar.lzo$/) {
5002 $format = 'tar' if !$format;
5004 } elsif ($archive =~ m/\.vma$/) {
5005 $format = 'vma' if !$format;
5006 } elsif ($archive =~ m/\.vma\.gz$/) {
5007 $format = 'vma' if !$format;
5009 } elsif ($archive =~ m/\.vma\.lzo$/) {
5010 $format = 'vma' if !$format;
5013 $format = 'vma' if !$format; # default
5016 # try to detect archive format
5017 if ($format eq 'tar') {
5018 return restore_tar_archive
($archive, $vmid, $user, $opts);
5020 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5024 sub restore_update_config_line
{
5025 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5027 return if $line =~ m/^\#qmdump\#/;
5028 return if $line =~ m/^\#vzdump\#/;
5029 return if $line =~ m/^lock:/;
5030 return if $line =~ m/^unused\d+:/;
5031 return if $line =~ m/^parent:/;
5032 return if $line =~ m/^template:/; # restored VM is never a template
5034 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5035 # try to convert old 1.X settings
5036 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5037 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5038 my ($model, $macaddr) = split(/\=/, $devconfig);
5039 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5042 bridge
=> "vmbr$ind",
5043 macaddr
=> $macaddr,
5045 my $netstr = print_net
($net);
5047 print $outfd "net$cookie->{netcount}: $netstr\n";
5048 $cookie->{netcount
}++;
5050 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5051 my ($id, $netstr) = ($1, $2);
5052 my $net = parse_net
($netstr);
5053 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5054 $netstr = print_net
($net);
5055 print $outfd "$id: $netstr\n";
5056 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5059 if ($line =~ m/backup=no/) {
5060 print $outfd "#$line";
5061 } elsif ($virtdev && $map->{$virtdev}) {
5062 my $di = parse_drive
($virtdev, $value);
5063 delete $di->{format
}; # format can change on restore
5064 $di->{file
} = $map->{$virtdev};
5065 $value = print_drive
($vmid, $di);
5066 print $outfd "$virtdev: $value\n";
5076 my ($cfg, $vmid) = @_;
5078 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5080 my $volid_hash = {};
5081 foreach my $storeid (keys %$info) {
5082 foreach my $item (@{$info->{$storeid}}) {
5083 next if !($item->{volid
} && $item->{size
});
5084 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5085 $volid_hash->{$item->{volid
}} = $item;
5092 sub get_used_paths
{
5093 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5097 my $scan_config = sub {
5098 my ($cref, $snapname) = @_;
5100 foreach my $key (keys %$cref) {
5101 my $value = $cref->{$key};
5102 if (valid_drivename
($key)) {
5103 next if $skip_drive && $key eq $skip_drive;
5104 my $drive = parse_drive
($key, $value);
5105 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5106 if ($drive->{file
} =~ m!^/!) {
5107 $used_path->{$drive->{file
}}++; # = 1;
5109 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5111 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5113 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5114 $used_path->{$path}++; # = 1;
5120 &$scan_config($conf);
5124 if ($scan_snapshots) {
5125 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5126 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5133 sub update_disksize
{
5134 my ($vmid, $conf, $volid_hash) = @_;
5140 # Note: it is allowed to define multiple storages with same path (alias), so
5141 # we need to check both 'volid' and real 'path' (two different volid can point
5142 # to the same path).
5147 foreach my $opt (keys %$conf) {
5148 if (valid_drivename
($opt)) {
5149 my $drive = parse_drive
($opt, $conf->{$opt});
5150 my $volid = $drive->{file
};
5153 $used->{$volid} = 1;
5154 if ($volid_hash->{$volid} &&
5155 (my $path = $volid_hash->{$volid}->{path
})) {
5156 $usedpath->{$path} = 1;
5159 next if drive_is_cdrom
($drive);
5160 next if !$volid_hash->{$volid};
5162 $drive->{size
} = $volid_hash->{$volid}->{size
};
5163 my $new = print_drive
($vmid, $drive);
5164 if ($new ne $conf->{$opt}) {
5166 $conf->{$opt} = $new;
5171 # remove 'unusedX' entry if volume is used
5172 foreach my $opt (keys %$conf) {
5173 next if $opt !~ m/^unused\d+$/;
5174 my $volid = $conf->{$opt};
5175 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5176 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5178 delete $conf->{$opt};
5182 foreach my $volid (sort keys %$volid_hash) {
5183 next if $volid =~ m/vm-$vmid-state-/;
5184 next if $used->{$volid};
5185 my $path = $volid_hash->{$volid}->{path
};
5186 next if !$path; # just to be sure
5187 next if $usedpath->{$path};
5189 add_unused_volume
($conf, $volid);
5190 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5197 my ($vmid, $nolock) = @_;
5199 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5201 my $volid_hash = scan_volids
($cfg, $vmid);
5203 my $updatefn = sub {
5206 my $conf = load_config
($vmid);
5211 foreach my $volid (keys %$volid_hash) {
5212 my $info = $volid_hash->{$volid};
5213 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5216 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5218 update_config_nolock
($vmid, $conf, 1) if $changes;
5221 if (defined($vmid)) {
5225 lock_config
($vmid, $updatefn, $vmid);
5228 my $vmlist = config_list
();
5229 foreach my $vmid (keys %$vmlist) {
5233 lock_config
($vmid, $updatefn, $vmid);
5239 sub restore_vma_archive
{
5240 my ($archive, $vmid, $user, $opts, $comp) = @_;
5242 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5243 my $readfrom = $archive;
5248 my $qarchive = PVE
::Tools
::shellquote
($archive);
5249 if ($comp eq 'gzip') {
5250 $uncomp = "zcat $qarchive|";
5251 } elsif ($comp eq 'lzop') {
5252 $uncomp = "lzop -d -c $qarchive|";
5254 die "unknown compression method '$comp'\n";
5259 my $tmpdir = "/var/tmp/vzdumptmp$$";
5262 # disable interrupts (always do cleanups)
5263 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5264 warn "got interrupt - ignored\n";
5267 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5268 POSIX
::mkfifo
($mapfifo, 0600);
5271 my $openfifo = sub {
5272 open($fifofh, '>', $mapfifo) || die $!;
5275 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5282 my $rpcenv = PVE
::RPCEnvironment
::get
();
5284 my $conffile = config_file
($vmid);
5285 my $tmpfn = "$conffile.$$.tmp";
5287 # Note: $oldconf is undef if VM does not exists
5288 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5290 my $print_devmap = sub {
5291 my $virtdev_hash = {};
5293 my $cfgfn = "$tmpdir/qemu-server.conf";
5295 # we can read the config - that is already extracted
5296 my $fh = IO
::File-
>new($cfgfn, "r") ||
5297 "unable to read qemu-server.conf - $!\n";
5299 while (defined(my $line = <$fh>)) {
5300 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5301 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5302 die "archive does not contain data for drive '$virtdev'\n"
5303 if !$devinfo->{$devname};
5304 if (defined($opts->{storage
})) {
5305 $storeid = $opts->{storage
} || 'local';
5306 } elsif (!$storeid) {
5309 $format = 'raw' if !$format;
5310 $devinfo->{$devname}->{devname
} = $devname;
5311 $devinfo->{$devname}->{virtdev
} = $virtdev;
5312 $devinfo->{$devname}->{format
} = $format;
5313 $devinfo->{$devname}->{storeid
} = $storeid;
5315 # check permission on storage
5316 my $pool = $opts->{pool
}; # todo: do we need that?
5317 if ($user ne 'root@pam') {
5318 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5321 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5325 foreach my $devname (keys %$devinfo) {
5326 die "found no device mapping information for device '$devname'\n"
5327 if !$devinfo->{$devname}->{virtdev
};
5330 my $cfg = cfs_read_file
('storage.cfg');
5332 # create empty/temp config
5334 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5335 foreach_drive
($oldconf, sub {
5336 my ($ds, $drive) = @_;
5338 return if drive_is_cdrom
($drive);
5340 my $volid = $drive->{file
};
5342 return if !$volid || $volid =~ m
|^/|;
5344 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5345 return if !$path || !$owner || ($owner != $vmid);
5347 # Note: only delete disk we want to restore
5348 # other volumes will become unused
5349 if ($virtdev_hash->{$ds}) {
5350 PVE
::Storage
::vdisk_free
($cfg, $volid);
5356 foreach my $virtdev (sort keys %$virtdev_hash) {
5357 my $d = $virtdev_hash->{$virtdev};
5358 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5359 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5361 # test if requested format is supported
5362 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5363 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5364 $d->{format
} = $defFormat if !$supported;
5366 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5367 $d->{format
}, undef, $alloc_size);
5368 print STDERR
"new volume ID is '$volid'\n";
5369 $d->{volid
} = $volid;
5370 my $path = PVE
::Storage
::path
($cfg, $volid);
5372 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5374 my $write_zeros = 1;
5375 # fixme: what other storages types initialize volumes with zero?
5376 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5377 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5381 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5383 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5384 $map->{$virtdev} = $volid;
5387 $fh->seek(0, 0) || die "seek failed - $!\n";
5389 my $outfd = new IO
::File
($tmpfn, "w") ||
5390 die "unable to write config for VM $vmid\n";
5392 my $cookie = { netcount
=> 0 };
5393 while (defined(my $line = <$fh>)) {
5394 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5403 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5404 die "interrupted by signal\n";
5406 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5408 $oldtimeout = alarm($timeout);
5415 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5416 my ($dev_id, $size, $devname) = ($1, $2, $3);
5417 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5418 } elsif ($line =~ m/^CTIME: /) {
5419 # we correctly received the vma config, so we can disable
5420 # the timeout now for disk allocation (set to 10 minutes, so
5421 # that we always timeout if something goes wrong)
5424 print $fifofh "done\n";
5425 my $tmp = $oldtimeout || 0;
5426 $oldtimeout = undef;
5432 print "restore vma archive: $cmd\n";
5433 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5437 alarm($oldtimeout) if $oldtimeout;
5440 foreach my $devname (keys %$devinfo) {
5441 my $volid = $devinfo->{$devname}->{volid
};
5442 push @$vollist, $volid if $volid;
5445 my $cfg = cfs_read_file
('storage.cfg');
5446 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5454 foreach my $devname (keys %$devinfo) {
5455 my $volid = $devinfo->{$devname}->{volid
};
5458 if ($volid =~ m
|^/|) {
5459 unlink $volid || die 'unlink failed\n';
5461 PVE
::Storage
::vdisk_free
($cfg, $volid);
5463 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5465 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5472 rename($tmpfn, $conffile) ||
5473 die "unable to commit configuration file '$conffile'\n";
5475 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5477 eval { rescan
($vmid, 1); };
5481 sub restore_tar_archive
{
5482 my ($archive, $vmid, $user, $opts) = @_;
5484 if ($archive ne '-') {
5485 my $firstfile = tar_archive_read_firstfile
($archive);
5486 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5487 if $firstfile ne 'qemu-server.conf';
5490 my $storecfg = cfs_read_file
('storage.cfg');
5492 # destroy existing data - keep empty config
5493 my $vmcfgfn = config_file
($vmid);
5494 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5496 my $tocmd = "/usr/lib/qemu-server/qmextract";
5498 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5499 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5500 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5501 $tocmd .= ' --info' if $opts->{info
};
5503 # tar option "xf" does not autodetect compression when read from STDIN,
5504 # so we pipe to zcat
5505 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5506 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5508 my $tmpdir = "/var/tmp/vzdumptmp$$";
5511 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5512 local $ENV{VZDUMP_VMID
} = $vmid;
5513 local $ENV{VZDUMP_USER
} = $user;
5515 my $conffile = config_file
($vmid);
5516 my $tmpfn = "$conffile.$$.tmp";
5518 # disable interrupts (always do cleanups)
5519 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5520 print STDERR
"got interrupt - ignored\n";
5525 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5526 die "interrupted by signal\n";
5529 if ($archive eq '-') {
5530 print "extracting archive from STDIN\n";
5531 run_command
($cmd, input
=> "<&STDIN");
5533 print "extracting archive '$archive'\n";
5537 return if $opts->{info
};
5541 my $statfile = "$tmpdir/qmrestore.stat";
5542 if (my $fd = IO
::File-
>new($statfile, "r")) {
5543 while (defined (my $line = <$fd>)) {
5544 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5545 $map->{$1} = $2 if $1;
5547 print STDERR
"unable to parse line in statfile - $line\n";
5553 my $confsrc = "$tmpdir/qemu-server.conf";
5555 my $srcfd = new IO
::File
($confsrc, "r") ||
5556 die "unable to open file '$confsrc'\n";
5558 my $outfd = new IO
::File
($tmpfn, "w") ||
5559 die "unable to write config for VM $vmid\n";
5561 my $cookie = { netcount
=> 0 };
5562 while (defined (my $line = <$srcfd>)) {
5563 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5575 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5582 rename $tmpfn, $conffile ||
5583 die "unable to commit configuration file '$conffile'\n";
5585 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5587 eval { rescan
($vmid, 1); };
5592 # Internal snapshots
5594 # NOTE: Snapshot create/delete involves several non-atomic
5595 # action, and can take a long time.
5596 # So we try to avoid locking the file and use 'lock' variable
5597 # inside the config file instead.
5599 my $snapshot_copy_config = sub {
5600 my ($source, $dest) = @_;
5602 foreach my $k (keys %$source) {
5603 next if $k eq 'snapshots';
5604 next if $k eq 'snapstate';
5605 next if $k eq 'snaptime';
5606 next if $k eq 'vmstate';
5607 next if $k eq 'lock';
5608 next if $k eq 'digest';
5609 next if $k eq 'description';
5610 next if $k =~ m/^unused\d+$/;
5612 $dest->{$k} = $source->{$k};
5616 my $snapshot_apply_config = sub {
5617 my ($conf, $snap) = @_;
5619 # copy snapshot list
5621 snapshots
=> $conf->{snapshots
},
5624 # keep description and list of unused disks
5625 foreach my $k (keys %$conf) {
5626 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5627 $newconf->{$k} = $conf->{$k};
5630 &$snapshot_copy_config($snap, $newconf);
5635 sub foreach_writable_storage
{
5636 my ($conf, $func) = @_;
5640 foreach my $ds (keys %$conf) {
5641 next if !valid_drivename
($ds);
5643 my $drive = parse_drive
($ds, $conf->{$ds});
5645 next if drive_is_cdrom
($drive);
5647 my $volid = $drive->{file
};
5649 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5650 $sidhash->{$sid} = $sid if $sid;
5653 foreach my $sid (sort keys %$sidhash) {
5658 my $alloc_vmstate_volid = sub {
5659 my ($storecfg, $vmid, $conf, $snapname) = @_;
5661 # Note: we try to be smart when selecting a $target storage
5665 # search shared storage first
5666 foreach_writable_storage
($conf, sub {
5668 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5669 return if !$scfg->{shared
};
5671 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5675 # now search local storage
5676 foreach_writable_storage
($conf, sub {
5678 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5679 return if $scfg->{shared
};
5681 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5685 $target = 'local' if !$target;
5687 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5688 # we abort live save after $conf->{memory}, so we need at max twice that space
5689 my $size = $conf->{memory
}*2 + $driver_state_size;
5691 my $name = "vm-$vmid-state-$snapname";
5692 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5693 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5694 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5699 my $snapshot_prepare = sub {
5700 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5704 my $updatefn = sub {
5706 my $conf = load_config
($vmid);
5708 die "you can't take a snapshot if it's a template\n"
5709 if is_template
($conf);
5713 $conf->{lock} = 'snapshot';
5715 die "snapshot name '$snapname' already used\n"
5716 if defined($conf->{snapshots
}->{$snapname});
5718 my $storecfg = PVE
::Storage
::config
();
5719 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5721 $snap = $conf->{snapshots
}->{$snapname} = {};
5723 if ($save_vmstate && check_running
($vmid)) {
5724 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5727 &$snapshot_copy_config($conf, $snap);
5729 $snap->{snapstate
} = "prepare";
5730 $snap->{snaptime
} = time();
5731 $snap->{description
} = $comment if $comment;
5733 # always overwrite machine if we save vmstate. This makes sure we
5734 # can restore it later using correct machine type
5735 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5737 update_config_nolock
($vmid, $conf, 1);
5740 lock_config
($vmid, $updatefn);
5745 my $snapshot_commit = sub {
5746 my ($vmid, $snapname) = @_;
5748 my $updatefn = sub {
5750 my $conf = load_config
($vmid);
5752 die "missing snapshot lock\n"
5753 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5755 my $has_machine_config = defined($conf->{machine
});
5757 my $snap = $conf->{snapshots
}->{$snapname};
5759 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5761 die "wrong snapshot state\n"
5762 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5764 delete $snap->{snapstate
};
5765 delete $conf->{lock};
5767 my $newconf = &$snapshot_apply_config($conf, $snap);
5769 delete $newconf->{machine
} if !$has_machine_config;
5771 $newconf->{parent
} = $snapname;
5773 update_config_nolock
($vmid, $newconf, 1);
5776 lock_config
($vmid, $updatefn);
5779 sub snapshot_rollback
{
5780 my ($vmid, $snapname) = @_;
5784 my $storecfg = PVE
::Storage
::config
();
5786 my $conf = load_config
($vmid);
5788 my $get_snapshot_config = sub {
5790 die "you can't rollback if vm is a template\n" if is_template
($conf);
5792 my $res = $conf->{snapshots
}->{$snapname};
5794 die "snapshot '$snapname' does not exist\n" if !defined($res);
5799 my $snap = &$get_snapshot_config();
5801 foreach_drive
($snap, sub {
5802 my ($ds, $drive) = @_;
5804 return if drive_is_cdrom
($drive);
5806 my $volid = $drive->{file
};
5808 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5811 my $updatefn = sub {
5813 $conf = load_config
($vmid);
5815 $snap = &$get_snapshot_config();
5817 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5818 if $snap->{snapstate
};
5822 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5825 die "unable to rollback vm $vmid: vm is running\n"
5826 if check_running
($vmid);
5829 $conf->{lock} = 'rollback';
5831 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5832 delete $conf->{lock};
5838 my $has_machine_config = defined($conf->{machine
});
5840 # copy snapshot config to current config
5841 $conf = &$snapshot_apply_config($conf, $snap);
5842 $conf->{parent
} = $snapname;
5844 # Note: old code did not store 'machine', so we try to be smart
5845 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5846 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5847 # we remove the 'machine' configuration if not explicitly specified
5848 # in the original config.
5849 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5852 update_config_nolock
($vmid, $conf, 1);
5854 if (!$prepare && $snap->{vmstate
}) {
5855 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5856 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5860 lock_config
($vmid, $updatefn);
5862 foreach_drive
($snap, sub {
5863 my ($ds, $drive) = @_;
5865 return if drive_is_cdrom
($drive);
5867 my $volid = $drive->{file
};
5868 my $device = "drive-$ds";
5870 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5874 lock_config
($vmid, $updatefn);
5877 my $savevm_wait = sub {
5881 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5882 if (!$stat->{status
}) {
5883 die "savevm not active\n";
5884 } elsif ($stat->{status
} eq 'active') {
5887 } elsif ($stat->{status
} eq 'completed') {
5890 die "query-savevm returned status '$stat->{status}'\n";
5895 sub do_snapshots_with_qemu
{
5896 my ($storecfg, $volid) = @_;
5898 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5900 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5901 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5905 if ($volid =~ m/\.(qcow2|qed)$/){
5912 sub snapshot_create
{
5913 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5915 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5917 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5919 my $config = load_config
($vmid);
5921 my $running = check_running
($vmid);
5923 my $freezefs = $running && $config->{agent
};
5924 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5929 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5930 warn "guest-fsfreeze-freeze problems - $@" if $@;
5934 # create internal snapshots of all drives
5936 my $storecfg = PVE
::Storage
::config
();
5939 if ($snap->{vmstate
}) {
5940 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5941 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5942 &$savevm_wait($vmid);
5944 vm_mon_cmd
($vmid, "savevm-start");
5948 foreach_drive
($snap, sub {
5949 my ($ds, $drive) = @_;
5951 return if drive_is_cdrom
($drive);
5953 my $volid = $drive->{file
};
5954 my $device = "drive-$ds";
5956 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5957 $drivehash->{$ds} = 1;
5963 eval { vm_mon_cmd
($vmid, "savevm-end") };
5967 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5968 warn "guest-fsfreeze-thaw problems - $@" if $@;
5971 # savevm-end is async, we need to wait
5973 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5974 if (!$stat->{bytes
}) {
5977 print "savevm not yet finished\n";
5985 warn "snapshot create failed: starting cleanup\n";
5986 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5991 &$snapshot_commit($vmid, $snapname);
5994 # Note: $drivehash is only set when called from snapshot_create.
5995 sub snapshot_delete
{
5996 my ($vmid, $snapname, $force, $drivehash) = @_;
6003 my $unlink_parent = sub {
6004 my ($confref, $new_parent) = @_;
6006 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6008 $confref->{parent
} = $new_parent;
6010 delete $confref->{parent
};
6015 my $updatefn = sub {
6016 my ($remove_drive) = @_;
6018 my $conf = load_config
($vmid);
6022 die "you can't delete a snapshot if vm is a template\n"
6023 if is_template
($conf);
6026 $snap = $conf->{snapshots
}->{$snapname};
6028 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6030 # remove parent refs
6032 &$unlink_parent($conf, $snap->{parent
});
6033 foreach my $sn (keys %{$conf->{snapshots
}}) {
6034 next if $sn eq $snapname;
6035 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6039 if ($remove_drive) {
6040 if ($remove_drive eq 'vmstate') {
6041 delete $snap->{$remove_drive};
6043 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6044 my $volid = $drive->{file
};
6045 delete $snap->{$remove_drive};
6046 add_unused_volume
($conf, $volid);
6051 $snap->{snapstate
} = 'delete';
6053 delete $conf->{snapshots
}->{$snapname};
6054 delete $conf->{lock} if $drivehash;
6055 foreach my $volid (@$unused) {
6056 add_unused_volume
($conf, $volid);
6060 update_config_nolock
($vmid, $conf, 1);
6063 lock_config
($vmid, $updatefn);
6065 # now remove vmstate file
6067 my $storecfg = PVE
::Storage
::config
();
6069 if ($snap->{vmstate
}) {
6070 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6072 die $err if !$force;
6075 # save changes (remove vmstate from snapshot)
6076 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6079 # now remove all internal snapshots
6080 foreach_drive
($snap, sub {
6081 my ($ds, $drive) = @_;
6083 return if drive_is_cdrom
($drive);
6085 my $volid = $drive->{file
};
6086 my $device = "drive-$ds";
6088 if (!$drivehash || $drivehash->{$ds}) {
6089 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6091 die $err if !$force;
6096 # save changes (remove drive fron snapshot)
6097 lock_config
($vmid, $updatefn, $ds) if !$force;
6098 push @$unused, $volid;
6101 # now cleanup config
6103 lock_config
($vmid, $updatefn);
6107 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6110 foreach_drive
($conf, sub {
6111 my ($ds, $drive) = @_;
6113 return if drive_is_cdrom
($drive);
6114 my $volid = $drive->{file
};
6115 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6118 return $err ?
0 : 1;
6121 sub template_create
{
6122 my ($vmid, $conf, $disk) = @_;
6124 my $storecfg = PVE
::Storage
::config
();
6126 foreach_drive
($conf, sub {
6127 my ($ds, $drive) = @_;
6129 return if drive_is_cdrom
($drive);
6130 return if $disk && $ds ne $disk;
6132 my $volid = $drive->{file
};
6133 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6135 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6136 $drive->{file
} = $voliddst;
6137 $conf->{$ds} = print_drive
($vmid, $drive);
6138 update_config_nolock
($vmid, $conf, 1);
6145 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6148 sub qemu_img_convert
{
6149 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6151 my $storecfg = PVE
::Storage
::config
();
6152 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6153 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6155 if ($src_storeid && $dst_storeid) {
6156 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6157 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6159 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6160 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6162 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6163 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6166 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6167 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6168 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6172 if($line =~ m/\((\S+)\/100\
%\)/){
6174 my $transferred = int($size * $percent / 100);
6175 my $remaining = $size - $transferred;
6177 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6182 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6184 die "copy failed: $err" if $err;
6188 sub qemu_img_format
{
6189 my ($scfg, $volname) = @_;
6191 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6198 sub qemu_drive_mirror
{
6199 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6201 my $storecfg = PVE
::Storage
::config
();
6202 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6204 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6206 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6208 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6210 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6211 $opts->{format
} = $format if $format;
6213 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6216 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6218 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6219 my $stat = @$stats[0];
6220 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6221 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6223 my $busy = $stat->{busy
};
6224 my $ready = $stat->{ready
};
6226 if (my $total = $stat->{len
}) {
6227 my $transferred = $stat->{offset
} || 0;
6228 my $remaining = $total - $transferred;
6229 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6231 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6235 if ($stat->{ready
} eq 'true') {
6237 last if $vmiddst != $vmid;
6239 # try to switch the disk if source and destination are on the same guest
6240 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6242 die $@ if $@ !~ m/cannot be completed/;
6251 my $cancel_job = sub {
6252 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6254 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6255 my $stat = @$stats[0];
6262 eval { &$cancel_job(); };
6263 die "mirroring error: $err";
6266 if ($vmiddst != $vmid) {
6267 # if we clone a disk for a new target vm, we don't switch the disk
6268 &$cancel_job(); # so we call block-job-cancel
6273 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6274 $newvmid, $storage, $format, $full, $newvollist) = @_;
6279 print "create linked clone of drive $drivename ($drive->{file})\n";
6280 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6281 push @$newvollist, $newvolid;
6283 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6284 $storeid = $storage if $storage;
6286 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6288 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6289 $format = qemu_img_format
($scfg, $volname);
6292 # test if requested format is supported - else use default
6293 my $supported = grep { $_ eq $format } @$validFormats;
6294 $format = $defFormat if !$supported;
6296 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6298 print "create full clone of drive $drivename ($drive->{file})\n";
6299 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6300 push @$newvollist, $newvolid;
6302 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6304 if (!$running || $snapname) {
6305 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6307 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6311 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6314 $disk->{format
} = undef;
6315 $disk->{file
} = $newvolid;
6316 $disk->{size
} = $size;
6321 # this only works if VM is running
6322 sub get_current_qemu_machine
{
6325 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6326 my $res = vm_qmp_command
($vmid, $cmd);
6328 my ($current, $default);
6329 foreach my $e (@$res) {
6330 $default = $e->{name
} if $e->{'is-default'};
6331 $current = $e->{name
} if $e->{'is-current'};
6334 # fallback to the default machine if current is not supported by qemu
6335 return $current || $default || 'pc';
6338 sub qemu_machine_feature_enabled
{
6339 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6344 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6346 $current_major = $3;
6347 $current_minor = $4;
6349 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6351 $current_major = $1;
6352 $current_minor = $2;
6355 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6364 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6365 my (undef, $id, $function) = @_;
6366 my $res = { id
=> $id, function
=> $function};
6367 push @{$devices->{$id}}, $res;
6373 sub vm_iothreads_list
{
6376 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6379 foreach my $iothread (@$res) {
6380 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6387 my ($conf, $drive) = @_;
6391 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6393 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6399 my $controller = int($drive->{index} / $maxdev);
6400 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6402 return ($maxdev, $controller, $controller_prefix);
6405 # bash completion helper
6407 sub complete_backup_archives
{
6408 my ($cmdname, $pname, $cvalue) = @_;
6410 my $cfg = PVE
::Storage
::config
();
6414 if ($cvalue =~ m/^([^:]+):/) {
6418 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6421 foreach my $id (keys %$data) {
6422 foreach my $item (@{$data->{$id}}) {
6423 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6424 push @$res, $item->{volid
} if defined($item->{volid
});
6431 my $complete_vmid_full = sub {
6434 my $idlist = vmstatus
();
6438 foreach my $id (keys %$idlist) {
6439 my $d = $idlist->{$id};
6440 if (defined($running)) {
6441 next if $d->{template
};
6442 next if $running && $d->{status
} ne 'running';
6443 next if !$running && $d->{status
} eq 'running';
6452 return &$complete_vmid_full();
6455 sub complete_vmid_stopped
{
6456 return &$complete_vmid_full(0);
6459 sub complete_vmid_running
{
6460 return &$complete_vmid_full(1);
6463 sub complete_storage
{
6465 my $cfg = PVE
::Storage
::config
();
6466 my $ids = $cfg->{ids
};
6469 foreach my $sid (keys %$ids) {
6470 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);