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);
33 use File
::Copy
qw(copy);
35 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
37 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
39 # Note about locking: we use flock on the config file protect
40 # against concurent actions.
41 # Aditionaly, we have a 'lock' setting in the config file. This
42 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
43 # allowed when such lock is set. But you can ignore this kind of
44 # lock with the --skiplock flag.
46 cfs_register_file
('/qemu-server/',
50 PVE
::JSONSchema
::register_standard_option
('skiplock', {
51 description
=> "Ignore locks - only root is allowed to use this option.",
56 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
57 description
=> "Some command save/restore state from this location.",
63 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
64 description
=> "The name of the snapshot.",
65 type
=> 'string', format
=> 'pve-configid',
69 #no warnings 'redefine';
72 my ($controller, $vmid, $option, $value) = @_;
74 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
75 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
79 my $nodename = PVE
::INotify
::nodename
();
81 mkdir "/etc/pve/nodes/$nodename";
82 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
85 my $var_run_tmpdir = "/var/run/qemu-server";
86 mkdir $var_run_tmpdir;
88 my $lock_dir = "/var/lock/qemu-server";
91 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Specifies whether a VM will be started during system bootup.",
103 description
=> "Automatic restart after crash (currently ignored).",
108 type
=> 'string', format
=> 'pve-hotplug-features',
109 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'.",
110 default => 'network,disk,usb',
115 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
121 description
=> "Lock/unlock the VM.",
122 enum
=> [qw(migrate backup snapshot rollback)],
127 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.",
135 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.",
143 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
150 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
156 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",
164 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
165 enum
=> PVE
::Tools
::kvmkeymaplist
(),
170 type
=> 'string', format
=> 'dns-name',
171 description
=> "Set a name for the VM. Only used on the configuration web interface.",
176 description
=> "scsi controller model",
177 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
183 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
188 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
189 description
=> <<EODESC,
190 Used to enable special optimization/features for specific
193 other => unspecified OS
194 wxp => Microsoft Windows XP
195 w2k => Microsoft Windows 2000
196 w2k3 => Microsoft Windows 2003
197 w2k8 => Microsoft Windows 2008
198 wvista => Microsoft Windows Vista
199 win7 => Microsoft Windows 7
200 win8 => Microsoft Windows 8/2012
201 l24 => Linux 2.4 Kernel
202 l26 => Linux 2.6/3.X Kernel
203 solaris => solaris/opensolaris/openindiania kernel
205 other|l24|l26|solaris ... no special behaviour
206 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
212 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
213 pattern
=> '[acdn]{1,4}',
218 type
=> 'string', format
=> 'pve-qm-bootdisk',
219 description
=> "Enable booting from specified disk.",
220 pattern
=> '(ide|sata|scsi|virtio)\d+',
225 description
=> "The number of CPUs. Please use option -sockets instead.",
232 description
=> "The number of CPU sockets.",
239 description
=> "The number of cores per socket.",
246 description
=> "Enable/disable Numa.",
252 description
=> "Number of hotplugged vcpus.",
259 description
=> "Enable/disable ACPI.",
265 description
=> "Enable/disable Qemu GuestAgent.",
271 description
=> "Enable/disable KVM hardware virtualization.",
277 description
=> "Enable/disable time drift fix.",
283 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
288 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
293 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.",
294 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
298 type
=> 'string', format
=> 'pve-qm-watchdog',
299 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
300 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)",
305 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
306 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'.",
307 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
310 startup
=> get_standard_option
('pve-startup-order'),
314 description
=> "Enable/disable Template.",
320 description
=> <<EODESCR,
321 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
323 args: -no-reboot -no-hpet
330 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).",
335 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
339 migrate_downtime
=> {
342 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
348 type
=> 'string', format
=> 'pve-qm-drive',
349 typetext
=> 'volume',
350 description
=> "This is an alias for option -ide2",
354 description
=> "Emulated CPU type.",
356 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) ],
359 parent
=> get_standard_option
('pve-snapshot-name', {
361 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
365 description
=> "Timestamp for snapshots.",
371 type
=> 'string', format
=> 'pve-volume-id',
372 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
375 description
=> "Specific the Qemu machine type.",
377 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
382 description
=> "Specify SMBIOS type 1 fields.",
383 type
=> 'string', format
=> 'pve-qm-smbios1',
384 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
391 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
397 description
=> "Enable ovmf uefi roms.",
402 # what about other qemu settings ?
404 #machine => 'string',
417 ##soundhw => 'string',
419 while (my ($k, $v) = each %$confdesc) {
420 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
423 my $MAX_IDE_DISKS = 4;
424 my $MAX_SCSI_DISKS = 14;
425 my $MAX_VIRTIO_DISKS = 16;
426 my $MAX_SATA_DISKS = 6;
427 my $MAX_USB_DEVICES = 5;
429 my $MAX_UNUSED_DISKS = 8;
430 my $MAX_HOSTPCI_DEVICES = 4;
431 my $MAX_SERIAL_PORTS = 4;
432 my $MAX_PARALLEL_PORTS = 3;
434 my $MAX_MEM = 4194304;
435 my $STATICMEM = 1024;
439 type
=> 'string', format
=> 'pve-qm-numanode',
440 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
441 description
=> "numa topology",
443 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
445 for (my $i = 0; $i < $MAX_NUMA; $i++) {
446 $confdesc->{"numa$i"} = $numadesc;
449 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
450 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
451 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
452 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
456 type
=> 'string', format
=> 'pve-qm-net',
457 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
458 description
=> <<EODESCR,
459 Specify network devices.
461 MODEL is one of: $nic_model_list_txt
463 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
464 automatically generated if not specified.
466 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
468 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'.
470 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
476 The DHCP server assign addresses to the guest starting from 10.0.2.15.
480 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
482 for (my $i = 0; $i < $MAX_NETS; $i++) {
483 $confdesc->{"net$i"} = $netdesc;
490 type
=> 'string', format
=> 'pve-qm-drive',
491 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]',
492 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
494 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
498 type
=> 'string', format
=> 'pve-qm-drive',
499 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]',
500 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
502 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
506 type
=> 'string', format
=> 'pve-qm-drive',
507 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]',
508 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
510 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
514 type
=> 'string', format
=> 'pve-qm-drive',
515 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]',
516 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
522 type
=> 'string', format
=> 'pve-qm-usb-device',
523 typetext
=> 'host=HOSTUSBDEVICE|spice',
524 description
=> <<EODESCR,
525 Configure an USB device (n is 0 to 4). This can be used to
526 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
528 'bus-port(.port)*' (decimal numbers) or
529 'vendor_id:product_id' (hexadeciaml numbers)
531 You can use the 'lsusb -t' command to list existing usb devices.
533 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
535 The value 'spice' can be used to add a usb redirection devices for spice.
539 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
543 type
=> 'string', format
=> 'pve-qm-hostpci',
544 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
545 description
=> <<EODESCR,
546 Map host pci devices. HOSTPCIDEVICE syntax is:
548 'bus:dev.func' (hexadecimal numbers)
550 You can us the 'lspci' command to list existing pci devices.
552 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
554 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
556 Experimental: user reported problems with this option.
559 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
564 pattern
=> '(/dev/.+|socket)',
565 description
=> <<EODESCR,
566 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).
568 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
570 Experimental: user reported problems with this option.
577 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
578 description
=> <<EODESCR,
579 Map host parallel devices (n is 0 to 2).
581 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
583 Experimental: user reported problems with this option.
587 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
588 $confdesc->{"parallel$i"} = $paralleldesc;
591 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
592 $confdesc->{"serial$i"} = $serialdesc;
595 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
596 $confdesc->{"hostpci$i"} = $hostpcidesc;
599 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
600 $drivename_hash->{"ide$i"} = 1;
601 $confdesc->{"ide$i"} = $idedesc;
604 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
605 $drivename_hash->{"sata$i"} = 1;
606 $confdesc->{"sata$i"} = $satadesc;
609 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
610 $drivename_hash->{"scsi$i"} = 1;
611 $confdesc->{"scsi$i"} = $scsidesc ;
614 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
615 $drivename_hash->{"virtio$i"} = 1;
616 $confdesc->{"virtio$i"} = $virtiodesc;
619 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
620 $confdesc->{"usb$i"} = $usbdesc;
625 type
=> 'string', format
=> 'pve-volume-id',
626 description
=> "Reference to unused volumes.",
629 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
630 $confdesc->{"unused$i"} = $unuseddesc;
633 my $kvm_api_version = 0;
637 return $kvm_api_version if $kvm_api_version;
639 my $fh = IO
::File-
>new("</dev/kvm") ||
642 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
643 $kvm_api_version = $v;
648 return $kvm_api_version;
651 my $kvm_user_version;
653 sub kvm_user_version
{
655 return $kvm_user_version if $kvm_user_version;
657 $kvm_user_version = 'unknown';
659 my $tmp = `kvm -help 2>/dev/null`;
661 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
662 $kvm_user_version = $2;
665 return $kvm_user_version;
669 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
672 # order is important - used to autoselect boot disk
673 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
674 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
675 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
676 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
679 sub valid_drivename
{
682 return defined($drivename_hash->{$dev});
687 return defined($confdesc->{$key});
691 return $nic_model_list;
694 sub os_list_description
{
699 w2k
=> 'Windows 2000',
700 w2k3
=>, 'Windows 2003',
701 w2k8
=> 'Windows 2008',
702 wvista
=> 'Windows Vista',
704 win8
=> 'Windows 8/2012',
714 return $cdrom_path if $cdrom_path;
716 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
717 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
718 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
722 my ($storecfg, $vmid, $cdrom) = @_;
724 if ($cdrom eq 'cdrom') {
725 return get_cdrom_path
();
726 } elsif ($cdrom eq 'none') {
728 } elsif ($cdrom =~ m
|^/|) {
731 return PVE
::Storage
::path
($storecfg, $cdrom);
735 # try to convert old style file names to volume IDs
736 sub filename_to_volume_id
{
737 my ($vmid, $file, $media) = @_;
739 if (!($file eq 'none' || $file eq 'cdrom' ||
740 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
742 return undef if $file =~ m
|/|;
744 if ($media && $media eq 'cdrom') {
745 $file = "local:iso/$file";
747 $file = "local:$vmid/$file";
754 sub verify_media_type
{
755 my ($opt, $vtype, $media) = @_;
760 if ($media eq 'disk') {
762 } elsif ($media eq 'cdrom') {
765 die "internal error";
768 return if ($vtype eq $etype);
770 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
773 sub cleanup_drive_path
{
774 my ($opt, $storecfg, $drive) = @_;
776 # try to convert filesystem paths to volume IDs
778 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
779 ($drive->{file
} !~ m
|^/dev/.+|) &&
780 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
781 ($drive->{file
} !~ m/^\d+$/)) {
782 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
783 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
784 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
785 verify_media_type
($opt, $vtype, $drive->{media
});
786 $drive->{file
} = $volid;
789 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
792 sub create_conf_nolock
{
793 my ($vmid, $settings) = @_;
795 my $filename = config_file
($vmid);
797 die "configuration file '$filename' already exists\n" if -f
$filename;
799 my $defaults = load_defaults
();
801 $settings->{name
} = "vm$vmid" if !$settings->{name
};
802 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
805 foreach my $opt (keys %$settings) {
806 next if !$confdesc->{$opt};
808 my $value = $settings->{$opt};
811 $data .= "$opt: $value\n";
814 PVE
::Tools
::file_set_contents
($filename, $data);
817 sub parse_hotplug_features
{
822 return $res if $data eq '0';
824 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
826 foreach my $feature (PVE
::Tools
::split_list
($data)) {
827 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
830 warn "ignoring unknown hotplug feature '$feature'\n";
836 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
837 sub pve_verify_hotplug_features
{
838 my ($value, $noerr) = @_;
840 return $value if parse_hotplug_features
($value);
842 return undef if $noerr;
844 die "unable to parse hotplug option\n";
847 my $parse_size = sub {
850 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
851 my ($size, $unit) = ($1, $3);
854 $size = $size * 1024;
855 } elsif ($unit eq 'M') {
856 $size = $size * 1024 * 1024;
857 } elsif ($unit eq 'G') {
858 $size = $size * 1024 * 1024 * 1024;
864 my $format_size = sub {
869 my $kb = int($size/1024);
870 return $size if $kb*1024 != $size;
872 my $mb = int($kb/1024);
873 return "${kb}K" if $mb*1024 != $kb;
875 my $gb = int($mb/1024);
876 return "${mb}M" if $gb*1024 != $mb;
881 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
882 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
883 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
884 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
885 # [,serial=serial][,model=model]
888 my ($key, $data) = @_;
892 # $key may be undefined - used to verify JSON parameters
893 if (!defined($key)) {
894 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
896 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
897 $res->{interface
} = $1;
903 foreach my $p (split (/,/, $data)) {
904 next if $p =~ m/^\s*$/;
906 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)=(.+)$/) {
907 my ($k, $v) = ($1, $2);
909 $k = 'file' if $k eq 'volume';
911 return undef if defined $res->{$k};
913 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
914 return undef if !$v || $v !~ m/^\d+/;
916 $v = sprintf("%.3f", $v / (1024*1024));
920 if (!$res->{file
} && $p !~ m/=/) {
928 return undef if !$res->{file
};
930 return undef if $res->{cache
} &&
931 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
932 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
933 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
934 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
935 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
936 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
937 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
938 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
939 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
940 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
941 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
942 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
943 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
944 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
945 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
947 return undef if $res->{mbps_rd
} && $res->{mbps
};
948 return undef if $res->{mbps_wr
} && $res->{mbps
};
950 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
951 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
953 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
955 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
957 return undef if $res->{iops_rd
} && $res->{iops
};
958 return undef if $res->{iops_wr
} && $res->{iops
};
961 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
962 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
963 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
964 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
965 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
966 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
969 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
972 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
973 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
974 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
975 return undef if $res->{interface
} eq 'virtio';
978 # rerror does not work with scsi drives
979 if ($res->{rerror
}) {
980 return undef if $res->{interface
} eq 'scsi';
986 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);
989 my ($vmid, $drive) = @_;
992 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
993 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
996 if ($drive->{size
}) {
997 $opts .= ",size=" . &$format_size($drive->{size
});
1000 if (my $model = $drive->{model
}) {
1001 $opts .= ",model=$model";
1004 return "$drive->{file}$opts";
1008 my($fh, $noerr) = @_;
1011 my $SG_GET_VERSION_NUM = 0x2282;
1013 my $versionbuf = "\x00" x
8;
1014 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1016 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1019 my $version = unpack("I", $versionbuf);
1020 if ($version < 30000) {
1021 die "scsi generic interface too old\n" if !$noerr;
1025 my $buf = "\x00" x
36;
1026 my $sensebuf = "\x00" x
8;
1027 my $cmd = pack("C x3 C x1", 0x12, 36);
1029 # see /usr/include/scsi/sg.h
1030 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";
1032 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1033 length($sensebuf), 0, length($buf), $buf,
1034 $cmd, $sensebuf, 6000);
1036 $ret = ioctl($fh, $SG_IO, $packet);
1038 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1042 my @res = unpack($sg_io_hdr_t, $packet);
1043 if ($res[17] || $res[18]) {
1044 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1049 (my $byte0, my $byte1, $res->{vendor
},
1050 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1052 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1053 $res->{type
} = $byte0 & 31;
1061 my $fh = IO
::File-
>new("+<$path") || return undef;
1062 my $res = scsi_inquiry
($fh, 1);
1068 sub machine_type_is_q35
{
1071 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1074 sub print_tabletdevice_full
{
1077 my $q35 = machine_type_is_q35
($conf);
1079 # we use uhci for old VMs because tablet driver was buggy in older qemu
1080 my $usbbus = $q35 ?
"ehci" : "uhci";
1082 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1085 sub print_drivedevice_full
{
1086 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1091 if ($drive->{interface
} eq 'virtio') {
1092 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1093 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1094 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1095 } elsif ($drive->{interface
} eq 'scsi') {
1097 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1098 my $unit = $drive->{index} % $maxdev;
1099 my $devicetype = 'hd';
1101 if (drive_is_cdrom
($drive)) {
1104 if ($drive->{file
} =~ m
|^/|) {
1105 $path = $drive->{file
};
1107 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1110 if($path =~ m/^iscsi\:\/\
//){
1111 $devicetype = 'generic';
1113 if (my $info = path_is_scsi
($path)) {
1114 if ($info->{type
} == 0) {
1115 $devicetype = 'block';
1116 } elsif ($info->{type
} == 1) { # tape
1117 $devicetype = 'generic';
1123 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1124 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1126 $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}";
1129 } elsif ($drive->{interface
} eq 'ide'){
1131 my $controller = int($drive->{index} / $maxdev);
1132 my $unit = $drive->{index} % $maxdev;
1133 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1135 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1136 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1137 $device .= ",model=$model";
1139 } elsif ($drive->{interface
} eq 'sata'){
1140 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1141 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1142 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1143 } elsif ($drive->{interface
} eq 'usb') {
1145 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1147 die "unsupported interface type";
1150 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1155 sub get_initiator_name
{
1158 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1159 while (defined(my $line = <$fh>)) {
1160 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1169 sub print_drive_full
{
1170 my ($storecfg, $vmid, $drive) = @_;
1173 my $volid = $drive->{file
};
1176 if (drive_is_cdrom
($drive)) {
1177 $path = get_iso_path
($storecfg, $vmid, $volid);
1179 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1181 $path = PVE
::Storage
::path
($storecfg, $volid);
1182 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1183 $format = qemu_img_format
($scfg, $volname);
1190 foreach my $o (@qemu_drive_options) {
1191 next if $o eq 'bootindex';
1192 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1195 $opts .= ",format=$format" if $format && !$drive->{format
};
1197 foreach my $o (qw(bps bps_rd bps_wr)) {
1198 my $v = $drive->{"m$o"};
1199 $opts .= ",$o=" . int($v*1024*1024) if $v;
1202 my $cache_direct = 0;
1204 if (my $cache = $drive->{cache
}) {
1205 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1206 } elsif (!drive_is_cdrom
($drive)) {
1207 $opts .= ",cache=none";
1211 # aio native works only with O_DIRECT
1212 if (!$drive->{aio
}) {
1214 $opts .= ",aio=native";
1216 $opts .= ",aio=threads";
1220 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1221 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1223 my $pathinfo = $path ?
"file=$path," : '';
1225 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1228 sub print_netdevice_full
{
1229 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1231 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1233 my $device = $net->{model
};
1234 if ($net->{model
} eq 'virtio') {
1235 $device = 'virtio-net-pci';
1238 my $pciaddr = print_pci_addr
("$netid", $bridges);
1239 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1240 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1241 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1242 my $vectors = $net->{queues
} * 2 + 2;
1243 $tmpstr .= ",vectors=$vectors,mq=on";
1245 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1247 if ($use_old_bios_files) {
1249 if ($device eq 'virtio-net-pci') {
1250 $romfile = 'pxe-virtio.rom';
1251 } elsif ($device eq 'e1000') {
1252 $romfile = 'pxe-e1000.rom';
1253 } elsif ($device eq 'ne2k') {
1254 $romfile = 'pxe-ne2k_pci.rom';
1255 } elsif ($device eq 'pcnet') {
1256 $romfile = 'pxe-pcnet.rom';
1257 } elsif ($device eq 'rtl8139') {
1258 $romfile = 'pxe-rtl8139.rom';
1260 $tmpstr .= ",romfile=$romfile" if $romfile;
1266 sub print_netdev_full
{
1267 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1270 if ($netid =~ m/^net(\d+)$/) {
1274 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1276 my $ifname = "tap${vmid}i$i";
1278 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1279 die "interface name '$ifname' is too long (max 15 character)\n"
1280 if length($ifname) >= 16;
1282 my $vhostparam = '';
1283 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1285 my $vmname = $conf->{name
} || "vm$vmid";
1288 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1290 if ($net->{bridge
}) {
1291 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1293 $netdev = "type=user,id=$netid,hostname=$vmname";
1296 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1301 sub drive_is_cdrom
{
1304 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1313 foreach my $kvp (split(/,/, $data)) {
1315 if ($kvp =~ m/^memory=(\S+)$/) {
1316 $res->{memory
} = $1;
1317 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1318 $res->{policy
} = $1;
1319 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1320 $res->{cpus
}->{start
} = $1;
1321 $res->{cpus
}->{end
} = $3;
1322 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1323 $res->{hostnodes
}->{start
} = $1;
1324 $res->{hostnodes
}->{end
} = $3;
1336 return undef if !$value;
1339 my @list = split(/,/, $value);
1343 foreach my $kv (@list) {
1345 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1348 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1351 my $pcidevices = lspci
($2);
1352 $res->{pciid
} = $pcidevices->{$2};
1354 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1355 $res->{rombar
} = $1;
1356 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1357 $res->{'x-vga'} = $1;
1358 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1359 $res->{pcie
} = 1 if $1 == 1;
1361 warn "unknown hostpci setting '$kv'\n";
1365 return undef if !$found;
1370 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1376 foreach my $kvp (split(/,/, $data)) {
1378 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) {
1380 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1381 $res->{model
} = $model;
1382 $res->{macaddr
} = $mac;
1383 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1384 $res->{bridge
} = $1;
1385 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1386 $res->{queues
} = $1;
1387 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1389 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1391 } elsif ($kvp =~ m/^firewall=([01])$/) {
1392 $res->{firewall
} = $1;
1393 } elsif ($kvp =~ m/^link_down=([01])$/) {
1394 $res->{link_down
} = $1;
1401 return undef if !$res->{model
};
1409 my $res = "$net->{model}";
1410 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1411 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1412 $res .= ",rate=$net->{rate}" if $net->{rate
};
1413 $res .= ",tag=$net->{tag}" if $net->{tag
};
1414 $res .= ",firewall=1" if $net->{firewall
};
1415 $res .= ",link_down=1" if $net->{link_down
};
1416 $res .= ",queues=$net->{queues}" if $net->{queues
};
1421 sub add_random_macs
{
1422 my ($settings) = @_;
1424 foreach my $opt (keys %$settings) {
1425 next if $opt !~ m/^net(\d+)$/;
1426 my $net = parse_net
($settings->{$opt});
1428 $settings->{$opt} = print_net
($net);
1432 sub add_unused_volume
{
1433 my ($config, $volid) = @_;
1436 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1437 my $test = "unused$ind";
1438 if (my $vid = $config->{$test}) {
1439 return if $vid eq $volid; # do not add duplicates
1445 die "To many unused volume - please delete them first.\n" if !$key;
1447 $config->{$key} = $volid;
1452 sub vm_is_volid_owner
{
1453 my ($storecfg, $vmid, $volid) = @_;
1455 if ($volid !~ m
|^/|) {
1457 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1458 if ($owner && ($owner == $vmid)) {
1466 sub split_flagged_list
{
1467 my $text = shift || '';
1468 $text =~ s/[,;]/ /g;
1470 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1473 sub join_flagged_list
{
1474 my ($how, $lst) = @_;
1475 join $how, map { $lst->{$_} . $_ } keys %$lst;
1478 sub vmconfig_delete_pending_option
{
1479 my ($conf, $key, $force) = @_;
1481 delete $conf->{pending
}->{$key};
1482 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1483 $pending_delete_hash->{$key} = $force ?
'!' : '';
1484 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1487 sub vmconfig_undelete_pending_option
{
1488 my ($conf, $key) = @_;
1490 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1491 delete $pending_delete_hash->{$key};
1493 if (%$pending_delete_hash) {
1494 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1496 delete $conf->{pending
}->{delete};
1500 sub vmconfig_register_unused_drive
{
1501 my ($storecfg, $vmid, $conf, $drive) = @_;
1503 if (!drive_is_cdrom
($drive)) {
1504 my $volid = $drive->{file
};
1505 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1506 add_unused_volume
($conf, $volid, $vmid);
1511 sub vmconfig_cleanup_pending
{
1514 # remove pending changes when nothing changed
1516 foreach my $opt (keys %{$conf->{pending
}}) {
1517 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1519 delete $conf->{pending
}->{$opt};
1523 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1524 my $pending_delete_hash = {};
1525 while (my ($opt, $force) = each %$current_delete_hash) {
1526 if (defined($conf->{$opt})) {
1527 $pending_delete_hash->{$opt} = $force;
1533 if (%$pending_delete_hash) {
1534 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1536 delete $conf->{pending
}->{delete};
1542 my $valid_smbios1_options = {
1543 manufacturer
=> '\S+',
1547 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1552 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1558 foreach my $kvp (split(/,/, $data)) {
1559 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1560 my ($k, $v) = split(/=/, $kvp);
1561 return undef if !defined($k) || !defined($v);
1562 return undef if !$valid_smbios1_options->{$k};
1563 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1574 foreach my $k (keys %$smbios1) {
1575 next if !defined($smbios1->{$k});
1576 next if !$valid_smbios1_options->{$k};
1577 $data .= ',' if $data;
1578 $data .= "$k=$smbios1->{$k}";
1583 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1584 sub verify_smbios1
{
1585 my ($value, $noerr) = @_;
1587 return $value if parse_smbios1
($value);
1589 return undef if $noerr;
1591 die "unable to parse smbios (type 1) options\n";
1594 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1595 sub verify_bootdisk
{
1596 my ($value, $noerr) = @_;
1598 return $value if valid_drivename
($value);
1600 return undef if $noerr;
1602 die "invalid boot disk '$value'\n";
1605 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1607 my ($value, $noerr) = @_;
1609 return $value if parse_numa
($value);
1611 return undef if $noerr;
1613 die "unable to parse numa options\n";
1616 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1618 my ($value, $noerr) = @_;
1620 return $value if parse_net
($value);
1622 return undef if $noerr;
1624 die "unable to parse network options\n";
1627 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1629 my ($value, $noerr) = @_;
1631 return $value if parse_drive
(undef, $value);
1633 return undef if $noerr;
1635 die "unable to parse drive options\n";
1638 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1639 sub verify_hostpci
{
1640 my ($value, $noerr) = @_;
1642 return $value if parse_hostpci
($value);
1644 return undef if $noerr;
1646 die "unable to parse pci id\n";
1649 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1650 sub verify_watchdog
{
1651 my ($value, $noerr) = @_;
1653 return $value if parse_watchdog
($value);
1655 return undef if $noerr;
1657 die "unable to parse watchdog options\n";
1660 sub parse_watchdog
{
1663 return undef if !$value;
1667 foreach my $p (split(/,/, $value)) {
1668 next if $p =~ m/^\s*$/;
1670 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1672 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1673 $res->{action
} = $2;
1682 sub parse_usb_device
{
1685 return undef if !$value;
1687 my @dl = split(/,/, $value);
1691 foreach my $v (@dl) {
1692 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1694 $res->{vendorid
} = $2;
1695 $res->{productid
} = $4;
1696 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1698 $res->{hostbus
} = $1;
1699 $res->{hostport
} = $2;
1700 } elsif ($v =~ m/^spice$/) {
1707 return undef if !$found;
1712 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1713 sub verify_usb_device
{
1714 my ($value, $noerr) = @_;
1716 return $value if parse_usb_device
($value);
1718 return undef if $noerr;
1720 die "unable to parse usb device\n";
1723 # add JSON properties for create and set function
1724 sub json_config_properties
{
1727 foreach my $opt (keys %$confdesc) {
1728 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1729 $prop->{$opt} = $confdesc->{$opt};
1736 my ($key, $value) = @_;
1738 die "unknown setting '$key'\n" if !$confdesc->{$key};
1740 my $type = $confdesc->{$key}->{type
};
1742 if (!defined($value)) {
1743 die "got undefined value\n";
1746 if ($value =~ m/[\n\r]/) {
1747 die "property contains a line feed\n";
1750 if ($type eq 'boolean') {
1751 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1752 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1753 die "type check ('boolean') failed - got '$value'\n";
1754 } elsif ($type eq 'integer') {
1755 return int($1) if $value =~ m/^(\d+)$/;
1756 die "type check ('integer') failed - got '$value'\n";
1757 } elsif ($type eq 'number') {
1758 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1759 die "type check ('number') failed - got '$value'\n";
1760 } elsif ($type eq 'string') {
1761 if (my $fmt = $confdesc->{$key}->{format
}) {
1762 if ($fmt eq 'pve-qm-drive') {
1763 # special case - we need to pass $key to parse_drive()
1764 my $drive = parse_drive
($key, $value);
1765 return $value if $drive;
1766 die "unable to parse drive options\n";
1768 PVE
::JSONSchema
::check_format
($fmt, $value);
1771 $value =~ s/^\"(.*)\"$/$1/;
1774 die "internal error"
1778 sub lock_config_full
{
1779 my ($vmid, $timeout, $code, @param) = @_;
1781 my $filename = config_file_lock
($vmid);
1783 my $res = lock_file
($filename, $timeout, $code, @param);
1790 sub lock_config_mode
{
1791 my ($vmid, $timeout, $shared, $code, @param) = @_;
1793 my $filename = config_file_lock
($vmid);
1795 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1803 my ($vmid, $code, @param) = @_;
1805 return lock_config_full
($vmid, 10, $code, @param);
1808 sub cfs_config_path
{
1809 my ($vmid, $node) = @_;
1811 $node = $nodename if !$node;
1812 return "nodes/$node/qemu-server/$vmid.conf";
1815 sub check_iommu_support
{
1816 #fixme : need to check IOMMU support
1817 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1825 my ($vmid, $node) = @_;
1827 my $cfspath = cfs_config_path
($vmid, $node);
1828 return "/etc/pve/$cfspath";
1831 sub config_file_lock
{
1834 return "$lock_dir/lock-$vmid.conf";
1840 my $conf = config_file
($vmid);
1841 utime undef, undef, $conf;
1845 my ($storecfg, $vmid, $keep_empty_config) = @_;
1847 my $conffile = config_file
($vmid);
1849 my $conf = load_config
($vmid);
1853 # only remove disks owned by this VM
1854 foreach_drive
($conf, sub {
1855 my ($ds, $drive) = @_;
1857 return if drive_is_cdrom
($drive);
1859 my $volid = $drive->{file
};
1861 return if !$volid || $volid =~ m
|^/|;
1863 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1864 return if !$path || !$owner || ($owner != $vmid);
1866 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1869 if ($keep_empty_config) {
1870 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1875 # also remove unused disk
1877 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1880 PVE
::Storage
::foreach_volid
($dl, sub {
1881 my ($volid, $sid, $volname, $d) = @_;
1882 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1892 my ($vmid, $node) = @_;
1894 my $cfspath = cfs_config_path
($vmid, $node);
1896 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1898 die "no such VM ('$vmid')\n" if !defined($conf);
1903 sub parse_vm_config
{
1904 my ($filename, $raw) = @_;
1906 return undef if !defined($raw);
1909 digest
=> Digest
::SHA
::sha1_hex
($raw),
1914 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1915 || die "got strange filename '$filename'";
1923 my @lines = split(/\n/, $raw);
1924 foreach my $line (@lines) {
1925 next if $line =~ m/^\s*$/;
1927 if ($line =~ m/^\[PENDING\]\s*$/i) {
1928 $section = 'pending';
1929 if (defined($descr)) {
1931 $conf->{description
} = $descr;
1934 $conf = $res->{$section} = {};
1937 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1939 if (defined($descr)) {
1941 $conf->{description
} = $descr;
1944 $conf = $res->{snapshots
}->{$section} = {};
1948 if ($line =~ m/^\#(.*)\s*$/) {
1949 $descr = '' if !defined($descr);
1950 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1954 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1955 $descr = '' if !defined($descr);
1956 $descr .= PVE
::Tools
::decode_text
($2);
1957 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1958 $conf->{snapstate
} = $1;
1959 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1962 $conf->{$key} = $value;
1963 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1965 if ($section eq 'pending') {
1966 $conf->{delete} = $value; # we parse this later
1968 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1970 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1973 eval { $value = check_type
($key, $value); };
1975 warn "vm $vmid - unable to parse value of '$key' - $@";
1977 my $fmt = $confdesc->{$key}->{format
};
1978 if ($fmt && $fmt eq 'pve-qm-drive') {
1979 my $v = parse_drive
($key, $value);
1980 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1981 $v->{file
} = $volid;
1982 $value = print_drive
($vmid, $v);
1984 warn "vm $vmid - unable to parse value of '$key'\n";
1989 if ($key eq 'cdrom') {
1990 $conf->{ide2
} = $value;
1992 $conf->{$key} = $value;
1998 if (defined($descr)) {
2000 $conf->{description
} = $descr;
2002 delete $res->{snapstate
}; # just to be sure
2007 sub write_vm_config
{
2008 my ($filename, $conf) = @_;
2010 delete $conf->{snapstate
}; # just to be sure
2012 if ($conf->{cdrom
}) {
2013 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2014 $conf->{ide2
} = $conf->{cdrom
};
2015 delete $conf->{cdrom
};
2018 # we do not use 'smp' any longer
2019 if ($conf->{sockets
}) {
2020 delete $conf->{smp
};
2021 } elsif ($conf->{smp
}) {
2022 $conf->{sockets
} = $conf->{smp
};
2023 delete $conf->{cores
};
2024 delete $conf->{smp
};
2027 my $used_volids = {};
2029 my $cleanup_config = sub {
2030 my ($cref, $pending, $snapname) = @_;
2032 foreach my $key (keys %$cref) {
2033 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2034 $key eq 'snapstate' || $key eq 'pending';
2035 my $value = $cref->{$key};
2036 if ($key eq 'delete') {
2037 die "propertry 'delete' is only allowed in [PENDING]\n"
2039 # fixme: check syntax?
2042 eval { $value = check_type
($key, $value); };
2043 die "unable to parse value of '$key' - $@" if $@;
2045 $cref->{$key} = $value;
2047 if (!$snapname && valid_drivename
($key)) {
2048 my $drive = parse_drive
($key, $value);
2049 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2054 &$cleanup_config($conf);
2056 &$cleanup_config($conf->{pending
}, 1);
2058 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2059 die "internal error" if $snapname eq 'pending';
2060 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2063 # remove 'unusedX' settings if we re-add a volume
2064 foreach my $key (keys %$conf) {
2065 my $value = $conf->{$key};
2066 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2067 delete $conf->{$key};
2071 my $generate_raw_config = sub {
2072 my ($conf, $pending) = @_;
2076 # add description as comment to top of file
2077 if (defined(my $descr = $conf->{description
})) {
2079 foreach my $cl (split(/\n/, $descr)) {
2080 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2083 $raw .= "#\n" if $pending;
2087 foreach my $key (sort keys %$conf) {
2088 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2089 $raw .= "$key: $conf->{$key}\n";
2094 my $raw = &$generate_raw_config($conf);
2096 if (scalar(keys %{$conf->{pending
}})){
2097 $raw .= "\n[PENDING]\n";
2098 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2101 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2102 $raw .= "\n[$snapname]\n";
2103 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2109 sub update_config_nolock
{
2110 my ($vmid, $conf, $skiplock) = @_;
2112 check_lock
($conf) if !$skiplock;
2114 my $cfspath = cfs_config_path
($vmid);
2116 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2120 my ($vmid, $conf, $skiplock) = @_;
2122 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2129 # we use static defaults from our JSON schema configuration
2130 foreach my $key (keys %$confdesc) {
2131 if (defined(my $default = $confdesc->{$key}->{default})) {
2132 $res->{$key} = $default;
2136 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2137 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2143 my $vmlist = PVE
::Cluster
::get_vmlist
();
2145 return $res if !$vmlist || !$vmlist->{ids
};
2146 my $ids = $vmlist->{ids
};
2148 foreach my $vmid (keys %$ids) {
2149 my $d = $ids->{$vmid};
2150 next if !$d->{node
} || $d->{node
} ne $nodename;
2151 next if !$d->{type
} || $d->{type
} ne 'qemu';
2152 $res->{$vmid}->{exists} = 1;
2157 # test if VM uses local resources (to prevent migration)
2158 sub check_local_resources
{
2159 my ($conf, $noerr) = @_;
2163 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2164 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2166 foreach my $k (keys %$conf) {
2167 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2168 # sockets are safe: they will recreated be on the target side post-migrate
2169 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2170 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2173 die "VM uses local resources\n" if $loc_res && !$noerr;
2178 # check if used storages are available on all nodes (use by migrate)
2179 sub check_storage_availability
{
2180 my ($storecfg, $conf, $node) = @_;
2182 foreach_drive
($conf, sub {
2183 my ($ds, $drive) = @_;
2185 my $volid = $drive->{file
};
2188 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2191 # check if storage is available on both nodes
2192 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2193 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2197 # list nodes where all VM images are available (used by has_feature API)
2199 my ($conf, $storecfg) = @_;
2201 my $nodelist = PVE
::Cluster
::get_nodelist
();
2202 my $nodehash = { map { $_ => 1 } @$nodelist };
2203 my $nodename = PVE
::INotify
::nodename
();
2205 foreach_drive
($conf, sub {
2206 my ($ds, $drive) = @_;
2208 my $volid = $drive->{file
};
2211 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2213 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2214 if ($scfg->{disable
}) {
2216 } elsif (my $avail = $scfg->{nodes
}) {
2217 foreach my $node (keys %$nodehash) {
2218 delete $nodehash->{$node} if !$avail->{$node};
2220 } elsif (!$scfg->{shared
}) {
2221 foreach my $node (keys %$nodehash) {
2222 delete $nodehash->{$node} if $node ne $nodename
2234 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2238 my ($pidfile, $pid) = @_;
2240 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2244 return undef if !$line;
2245 my @param = split(/\0/, $line);
2247 my $cmd = $param[0];
2248 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2250 for (my $i = 0; $i < scalar (@param); $i++) {
2253 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2254 my $p = $param[$i+1];
2255 return 1 if $p && ($p eq $pidfile);
2264 my ($vmid, $nocheck, $node) = @_;
2266 my $filename = config_file
($vmid, $node);
2268 die "unable to find configuration file for VM $vmid - no such machine\n"
2269 if !$nocheck && ! -f
$filename;
2271 my $pidfile = pidfile_name
($vmid);
2273 if (my $fd = IO
::File-
>new("<$pidfile")) {
2278 my $mtime = $st->mtime;
2279 if ($mtime > time()) {
2280 warn "file '$filename' modified in future\n";
2283 if ($line =~ m/^(\d+)$/) {
2285 if (check_cmdline
($pidfile, $pid)) {
2286 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2298 my $vzlist = config_list
();
2300 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2302 while (defined(my $de = $fd->read)) {
2303 next if $de !~ m/^(\d+)\.pid$/;
2305 next if !defined($vzlist->{$vmid});
2306 if (my $pid = check_running
($vmid)) {
2307 $vzlist->{$vmid}->{pid
} = $pid;
2315 my ($storecfg, $conf) = @_;
2317 my $bootdisk = $conf->{bootdisk
};
2318 return undef if !$bootdisk;
2319 return undef if !valid_drivename
($bootdisk);
2321 return undef if !$conf->{$bootdisk};
2323 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2324 return undef if !defined($drive);
2326 return undef if drive_is_cdrom
($drive);
2328 my $volid = $drive->{file
};
2329 return undef if !$volid;
2331 return $drive->{size
};
2334 my $last_proc_pid_stat;
2336 # get VM status information
2337 # This must be fast and should not block ($full == false)
2338 # We only query KVM using QMP if $full == true (this can be slow)
2340 my ($opt_vmid, $full) = @_;
2344 my $storecfg = PVE
::Storage
::config
();
2346 my $list = vzlist
();
2347 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2349 my $cpucount = $cpuinfo->{cpus
} || 1;
2351 foreach my $vmid (keys %$list) {
2352 next if $opt_vmid && ($vmid ne $opt_vmid);
2354 my $cfspath = cfs_config_path
($vmid);
2355 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2358 $d->{pid
} = $list->{$vmid}->{pid
};
2360 # fixme: better status?
2361 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2363 my $size = disksize
($storecfg, $conf);
2364 if (defined($size)) {
2365 $d->{disk
} = 0; # no info available
2366 $d->{maxdisk
} = $size;
2372 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2373 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2374 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2376 $d->{name
} = $conf->{name
} || "VM $vmid";
2377 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2379 if ($conf->{balloon
}) {
2380 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2381 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2392 $d->{diskwrite
} = 0;
2394 $d->{template
} = is_template
($conf);
2399 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2400 foreach my $dev (keys %$netdev) {
2401 next if $dev !~ m/^tap([1-9]\d*)i/;
2403 my $d = $res->{$vmid};
2406 $d->{netout
} += $netdev->{$dev}->{receive
};
2407 $d->{netin
} += $netdev->{$dev}->{transmit
};
2410 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2411 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2416 my $ctime = gettimeofday
;
2418 foreach my $vmid (keys %$list) {
2420 my $d = $res->{$vmid};
2421 my $pid = $d->{pid
};
2424 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2425 next if !$pstat; # not running
2427 my $used = $pstat->{utime} + $pstat->{stime
};
2429 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2431 if ($pstat->{vsize
}) {
2432 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2435 my $old = $last_proc_pid_stat->{$pid};
2437 $last_proc_pid_stat->{$pid} = {
2445 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2447 if ($dtime > 1000) {
2448 my $dutime = $used - $old->{used
};
2450 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2451 $last_proc_pid_stat->{$pid} = {
2457 $d->{cpu
} = $old->{cpu
};
2461 return $res if !$full;
2463 my $qmpclient = PVE
::QMPClient-
>new();
2465 my $ballooncb = sub {
2466 my ($vmid, $resp) = @_;
2468 my $info = $resp->{'return'};
2469 return if !$info->{max_mem
};
2471 my $d = $res->{$vmid};
2473 # use memory assigned to VM
2474 $d->{maxmem
} = $info->{max_mem
};
2475 $d->{balloon
} = $info->{actual
};
2477 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2478 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2479 $d->{freemem
} = $info->{free_mem
};
2482 $d->{ballooninfo
} = $info;
2485 my $blockstatscb = sub {
2486 my ($vmid, $resp) = @_;
2487 my $data = $resp->{'return'} || [];
2488 my $totalrdbytes = 0;
2489 my $totalwrbytes = 0;
2491 for my $blockstat (@$data) {
2492 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2493 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2495 $blockstat->{device
} =~ s/drive-//;
2496 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2498 $res->{$vmid}->{diskread
} = $totalrdbytes;
2499 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2502 my $statuscb = sub {
2503 my ($vmid, $resp) = @_;
2505 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2506 # this fails if ballon driver is not loaded, so this must be
2507 # the last commnand (following command are aborted if this fails).
2508 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2510 my $status = 'unknown';
2511 if (!defined($status = $resp->{'return'}->{status
})) {
2512 warn "unable to get VM status\n";
2516 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2519 foreach my $vmid (keys %$list) {
2520 next if $opt_vmid && ($vmid ne $opt_vmid);
2521 next if !$res->{$vmid}->{pid
}; # not running
2522 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2525 $qmpclient->queue_execute(undef, 1);
2527 foreach my $vmid (keys %$list) {
2528 next if $opt_vmid && ($vmid ne $opt_vmid);
2529 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2536 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2539 my $current_size = 1024;
2540 my $dimm_size = 512;
2541 return if $current_size == $memory;
2543 for (my $j = 0; $j < 8; $j++) {
2544 for (my $i = 0; $i < 32; $i++) {
2545 my $name = "dimm${dimm_id}";
2547 my $numanode = $i % $sockets;
2548 $current_size += $dimm_size;
2549 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2550 return $current_size if $current_size >= $memory;
2556 sub foreach_reverse_dimm
{
2557 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2560 my $current_size = 4177920;
2561 my $dimm_size = 65536;
2562 return if $current_size == $memory;
2564 for (my $j = 0; $j < 8; $j++) {
2565 for (my $i = 0; $i < 32; $i++) {
2566 my $name = "dimm${dimm_id}";
2568 my $numanode = $i % $sockets;
2569 $current_size -= $dimm_size;
2570 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2571 return $current_size if $current_size <= $memory;
2578 my ($conf, $func) = @_;
2580 foreach my $ds (keys %$conf) {
2581 next if !valid_drivename
($ds);
2583 my $drive = parse_drive
($ds, $conf->{$ds});
2586 &$func($ds, $drive);
2591 my ($conf, $func) = @_;
2595 my $test_volid = sub {
2596 my ($volid, $is_cdrom) = @_;
2600 $volhash->{$volid} = $is_cdrom || 0;
2603 foreach_drive
($conf, sub {
2604 my ($ds, $drive) = @_;
2605 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2608 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2609 my $snap = $conf->{snapshots
}->{$snapname};
2610 &$test_volid($snap->{vmstate
}, 0);
2611 foreach_drive
($snap, sub {
2612 my ($ds, $drive) = @_;
2613 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2617 foreach my $volid (keys %$volhash) {
2618 &$func($volid, $volhash->{$volid});
2622 sub vga_conf_has_spice
{
2625 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2630 sub config_to_command
{
2631 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2634 my $globalFlags = [];
2635 my $machineFlags = [];
2641 my $kvmver = kvm_user_version
();
2642 my $vernum = 0; # unknown
2643 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2644 $vernum = $1*1000000+$2*1000;
2645 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2646 $vernum = $1*1000000+$2*1000+$3;
2649 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2651 my $have_ovz = -f
'/proc/vz/vestat';
2653 my $q35 = machine_type_is_q35
($conf);
2654 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2655 my $machine_type = $forcemachine || $conf->{machine
};
2656 my $use_old_bios_files = undef;
2657 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2659 my $cpuunits = defined($conf->{cpuunits
}) ?
2660 $conf->{cpuunits
} : $defaults->{cpuunits
};
2662 push @$cmd, '/usr/bin/systemd-run';
2663 push @$cmd, '--scope';
2664 push @$cmd, '--slice', "qemu";
2665 push @$cmd, '--unit', $vmid;
2666 # set KillMode=none, so that systemd don't kill those scopes
2667 # at shutdown (pve-manager service should stop the VMs instead)
2668 push @$cmd, '-p', "KillMode=none";
2669 push @$cmd, '-p', "CPUShares=$cpuunits";
2670 if ($conf->{cpulimit
}) {
2671 my $cpulimit = int($conf->{cpulimit
} * 100);
2672 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2675 push @$cmd, '/usr/bin/kvm';
2677 push @$cmd, '-id', $vmid;
2681 my $qmpsocket = qmp_socket
($vmid);
2682 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2683 push @$cmd, '-mon', "chardev=qmp,mode=control";
2685 my $socket = vnc_socket
($vmid);
2686 push @$cmd, '-vnc', "unix:$socket,x509,password";
2688 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2690 push @$cmd, '-daemonize';
2692 if ($conf->{smbios1
}) {
2693 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2696 if ($conf->{ovmf
}) {
2697 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2698 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2699 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2700 copy
$ovmfvar_src,$ovmfvar_dst if !(-e
$ovmfvar_dst);
2701 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2702 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2706 # the q35 chipset support native usb2, so we enable usb controller
2707 # by default for this machine type
2708 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2710 $pciaddr = print_pci_addr
("piix3", $bridges);
2711 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2714 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2715 next if !$conf->{"usb$i"};
2718 # include usb device config
2719 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2722 my $vga = $conf->{vga
};
2724 my $qxlnum = vga_conf_has_spice
($vga);
2725 $vga = 'qxl' if $qxlnum;
2728 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2729 $conf->{ostype
} eq 'win7' ||
2730 $conf->{ostype
} eq 'w2k8')) {
2737 # enable absolute mouse coordinates (needed by vnc)
2739 if (defined($conf->{tablet
})) {
2740 $tablet = $conf->{tablet
};
2742 $tablet = $defaults->{tablet
};
2743 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2744 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2747 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2750 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2751 my $d = parse_hostpci
($conf->{"hostpci$i"});
2754 my $pcie = $d->{pcie
};
2756 die "q35 machine model is not enabled" if !$q35;
2757 $pciaddr = print_pcie_addr
("hostpci$i");
2759 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2762 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2763 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2764 if ($xvga && $xvga ne '') {
2765 push @$cpuFlags, 'kvm=off';
2768 my $pcidevices = $d->{pciid
};
2769 my $multifunction = 1 if @$pcidevices > 1;
2772 foreach my $pcidevice (@$pcidevices) {
2774 my $id = "hostpci$i";
2775 $id .= ".$j" if $multifunction;
2776 my $addr = $pciaddr;
2777 $addr .= ".$j" if $multifunction;
2778 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2781 $devicestr .= "$rombar$xvga";
2782 $devicestr .= ",multifunction=on" if $multifunction;
2785 push @$devices, '-device', $devicestr;
2791 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2792 my $d = parse_usb_device
($conf->{"usb$i"});
2794 if ($d->{vendorid
} && $d->{productid
}) {
2795 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2796 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2797 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2798 } elsif ($d->{spice
}) {
2799 # usb redir support for spice
2800 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2801 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2806 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2807 if (my $path = $conf->{"serial$i"}) {
2808 if ($path eq 'socket') {
2809 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2810 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2811 push @$devices, '-device', "isa-serial,chardev=serial$i";
2813 die "no such serial device\n" if ! -c
$path;
2814 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2815 push @$devices, '-device', "isa-serial,chardev=serial$i";
2821 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2822 if (my $path = $conf->{"parallel$i"}) {
2823 die "no such parallel device\n" if ! -c
$path;
2824 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2825 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2826 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2830 my $vmname = $conf->{name
} || "vm$vmid";
2832 push @$cmd, '-name', $vmname;
2835 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2836 $sockets = $conf->{sockets
} if $conf->{sockets
};
2838 my $cores = $conf->{cores
} || 1;
2840 my $maxcpus = $sockets * $cores;
2842 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2844 my $allowed_vcpus = $cpuinfo->{cpus
};
2846 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2847 if ($allowed_vcpus < $maxcpus);
2849 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2851 push @$cmd, '-nodefaults';
2853 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2855 my $bootindex_hash = {};
2857 foreach my $o (split(//, $bootorder)) {
2858 $bootindex_hash->{$o} = $i*100;
2862 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2864 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2866 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2868 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2871 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2873 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2874 my $useLocaltime = $conf->{localtime};
2876 if (my $ost = $conf->{ostype
}) {
2877 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2879 if ($ost =~ m/^w/) { # windows
2880 $useLocaltime = 1 if !defined($conf->{localtime});
2882 # use time drift fix when acpi is enabled
2883 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2884 $tdf = 1 if !defined($conf->{tdf
});
2888 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2890 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2891 push @$cmd, '-no-hpet';
2892 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2893 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2894 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2895 push @$cpuFlags , 'hv_time' if !$nokvm;
2898 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2902 if ($ost eq 'win7' || $ost eq 'win8') {
2903 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2907 push @$rtcFlags, 'driftfix=slew' if $tdf;
2910 push @$machineFlags, 'accel=tcg';
2912 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2915 if ($machine_type) {
2916 push @$machineFlags, "type=${machine_type}";
2919 if ($conf->{startdate
}) {
2920 push @$rtcFlags, "base=$conf->{startdate}";
2921 } elsif ($useLocaltime) {
2922 push @$rtcFlags, 'base=localtime';
2925 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2926 $cpu = $conf->{cpu
} if $conf->{cpu
};
2928 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2930 push @$cpuFlags , '-x2apic'
2931 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2933 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2935 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2937 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2939 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2940 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2943 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2945 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2947 push @$cmd, '-cpu', $cpu;
2949 my $memory = $conf->{memory
} || $defaults->{memory
};
2950 my $static_memory = 0;
2951 my $dimm_memory = 0;
2953 if ($hotplug_features->{memory
}) {
2954 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2955 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2956 $static_memory = $STATICMEM;
2957 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2958 $dimm_memory = $memory - $static_memory;
2959 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2963 $static_memory = $memory;
2964 push @$cmd, '-m', $static_memory;
2967 if ($conf->{numa
}) {
2969 my $numa_totalmemory = undef;
2970 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2971 next if !$conf->{"numa$i"};
2972 my $numa = parse_numa
($conf->{"numa$i"});
2975 die "missing numa node$i memory value\n" if !$numa->{memory
};
2976 my $numa_memory = $numa->{memory
};
2977 $numa_totalmemory += $numa_memory;
2978 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2981 my $cpus_start = $numa->{cpus
}->{start
};
2982 die "missing numa node$i cpus\n" if !defined($cpus_start);
2983 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2984 my $cpus = $cpus_start;
2985 if (defined($cpus_end)) {
2986 $cpus .= "-$cpus_end";
2987 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2991 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2992 if (defined($hostnodes_start)) {
2993 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2994 my $hostnodes = $hostnodes_start;
2995 if (defined($hostnodes_end)) {
2996 $hostnodes .= "-$hostnodes_end";
2997 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3000 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3001 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3002 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3006 my $policy = $numa->{policy
};
3007 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3008 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3011 push @$cmd, '-object', $numa_object;
3012 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3015 die "total memory for NUMA nodes must be equal to vm static memory\n"
3016 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3018 #if no custom tology, we split memory and cores across numa nodes
3019 if(!$numa_totalmemory) {
3021 my $numa_memory = ($static_memory / $sockets) . "M";
3023 for (my $i = 0; $i < $sockets; $i++) {
3025 my $cpustart = ($cores * $i);
3026 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3027 my $cpus = $cpustart;
3028 $cpus .= "-$cpuend" if $cpuend;
3030 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3031 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3036 if ($hotplug_features->{memory
}) {
3037 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3038 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3039 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3040 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3042 #if dimm_memory is not aligned to dimm map
3043 if($current_size > $memory) {
3044 $conf->{memory
} = $current_size;
3045 update_config_nolock
($vmid, $conf, 1);
3050 push @$cmd, '-S' if $conf->{freeze
};
3052 # set keyboard layout
3053 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3054 push @$cmd, '-k', $kb if $kb;
3057 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3058 #push @$cmd, '-soundhw', 'es1370';
3059 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3061 if($conf->{agent
}) {
3062 my $qgasocket = qmp_socket
($vmid, 1);
3063 my $pciaddr = print_pci_addr
("qga0", $bridges);
3064 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3065 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3066 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3073 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3074 for(my $i = 1; $i < $qxlnum; $i++){
3075 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3076 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3079 # assume other OS works like Linux
3080 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3081 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3085 my $pciaddr = print_pci_addr
("spice", $bridges);
3087 my $nodename = PVE
::INotify
::nodename
();
3088 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3089 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3091 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3093 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3094 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3095 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3098 # enable balloon by default, unless explicitly disabled
3099 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3100 $pciaddr = print_pci_addr
("balloon0", $bridges);
3101 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3104 if ($conf->{watchdog
}) {
3105 my $wdopts = parse_watchdog
($conf->{watchdog
});
3106 $pciaddr = print_pci_addr
("watchdog", $bridges);
3107 my $watchdog = $wdopts->{model
} || 'i6300esb';
3108 push @$devices, '-device', "$watchdog$pciaddr";
3109 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3113 my $scsicontroller = {};
3114 my $ahcicontroller = {};
3115 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3117 # Add iscsi initiator name if available
3118 if (my $initiator = get_initiator_name
()) {
3119 push @$devices, '-iscsi', "initiator-name=$initiator";
3122 foreach_drive
($conf, sub {
3123 my ($ds, $drive) = @_;
3125 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3126 push @$vollist, $drive->{file
};
3129 $use_virtio = 1 if $ds =~ m/^virtio/;
3131 if (drive_is_cdrom
($drive)) {
3132 if ($bootindex_hash->{d
}) {
3133 $drive->{bootindex
} = $bootindex_hash->{d
};
3134 $bootindex_hash->{d
} += 1;
3137 if ($bootindex_hash->{c
}) {
3138 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3139 $bootindex_hash->{c
} += 1;
3143 if($drive->{interface
} eq 'virtio'){
3144 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3147 if ($drive->{interface
} eq 'scsi') {
3149 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3151 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3152 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3155 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3156 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3157 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3161 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3162 $queues = ",num_queues=$drive->{queues}";
3165 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3166 $scsicontroller->{$controller}=1;
3169 if ($drive->{interface
} eq 'sata') {
3170 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3171 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3172 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3173 $ahcicontroller->{$controller}=1;
3176 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3177 push @$devices, '-drive',$drive_cmd;
3178 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3181 for (my $i = 0; $i < $MAX_NETS; $i++) {
3182 next if !$conf->{"net$i"};
3183 my $d = parse_net
($conf->{"net$i"});
3186 $use_virtio = 1 if $d->{model
} eq 'virtio';
3188 if ($bootindex_hash->{n
}) {
3189 $d->{bootindex
} = $bootindex_hash->{n
};
3190 $bootindex_hash->{n
} += 1;
3193 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3194 push @$devices, '-netdev', $netdevfull;
3196 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3197 push @$devices, '-device', $netdevicefull;
3202 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3207 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3209 while (my ($k, $v) = each %$bridges) {
3210 $pciaddr = print_pci_addr
("pci.$k");
3211 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3216 if ($conf->{args
}) {
3217 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3221 push @$cmd, @$devices;
3222 push @$cmd, '-rtc', join(',', @$rtcFlags)
3223 if scalar(@$rtcFlags);
3224 push @$cmd, '-machine', join(',', @$machineFlags)
3225 if scalar(@$machineFlags);
3226 push @$cmd, '-global', join(',', @$globalFlags)
3227 if scalar(@$globalFlags);
3229 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3234 return "${var_run_tmpdir}/$vmid.vnc";
3240 my $res = vm_mon_cmd
($vmid, 'query-spice');
3242 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3246 my ($vmid, $qga) = @_;
3247 my $sockettype = $qga ?
'qga' : 'qmp';
3248 return "${var_run_tmpdir}/$vmid.$sockettype";
3253 return "${var_run_tmpdir}/$vmid.pid";
3256 sub vm_devices_list
{
3259 my $res = vm_mon_cmd
($vmid, 'query-pci');
3261 foreach my $pcibus (@$res) {
3262 foreach my $device (@{$pcibus->{devices
}}) {
3263 next if !$device->{'qdev_id'};
3264 if ($device->{'pci_bridge'}) {
3265 $devices->{$device->{'qdev_id'}} = 1;
3266 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3267 next if !$bridge_device->{'qdev_id'};
3268 $devices->{$bridge_device->{'qdev_id'}} = 1;
3269 $devices->{$device->{'qdev_id'}}++;
3272 $devices->{$device->{'qdev_id'}} = 1;
3277 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3278 foreach my $block (@$resblock) {
3279 if($block->{device
} =~ m/^drive-(\S+)/){
3284 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3285 foreach my $mice (@$resmice) {
3286 if ($mice->{name
} eq 'QEMU HID Tablet') {
3287 $devices->{tablet
} = 1;
3296 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3298 my $q35 = machine_type_is_q35
($conf);
3300 my $devices_list = vm_devices_list
($vmid);
3301 return 1 if defined($devices_list->{$deviceid});
3303 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3305 if ($deviceid eq 'tablet') {
3307 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3309 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3311 qemu_iothread_add
($vmid, $deviceid, $device);
3313 qemu_driveadd
($storecfg, $vmid, $device);
3314 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3316 qemu_deviceadd
($vmid, $devicefull);
3317 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3319 eval { qemu_drivedel
($vmid, $deviceid); };
3324 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3327 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3328 my $pciaddr = print_pci_addr
($deviceid);
3329 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3331 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3333 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3334 qemu_iothread_add
($vmid, $deviceid, $device);
3335 $devicefull .= ",iothread=iothread-$deviceid";
3338 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3339 $devicefull .= ",num_queues=$device->{queues}";
3342 qemu_deviceadd
($vmid, $devicefull);
3343 qemu_deviceaddverify
($vmid, $deviceid);
3345 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3347 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3348 qemu_driveadd
($storecfg, $vmid, $device);
3350 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3351 eval { qemu_deviceadd
($vmid, $devicefull); };
3353 eval { qemu_drivedel
($vmid, $deviceid); };
3358 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3360 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3362 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3363 my $use_old_bios_files = undef;
3364 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3366 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3367 qemu_deviceadd
($vmid, $netdevicefull);
3368 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3370 eval { qemu_netdevdel
($vmid, $deviceid); };
3375 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3378 my $pciaddr = print_pci_addr
($deviceid);
3379 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3381 qemu_deviceadd
($vmid, $devicefull);
3382 qemu_deviceaddverify
($vmid, $deviceid);
3385 die "can't hotplug device '$deviceid'\n";
3391 # fixme: this should raise exceptions on error!
3392 sub vm_deviceunplug
{
3393 my ($vmid, $conf, $deviceid) = @_;
3395 my $devices_list = vm_devices_list
($vmid);
3396 return 1 if !defined($devices_list->{$deviceid});
3398 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3400 if ($deviceid eq 'tablet') {
3402 qemu_devicedel
($vmid, $deviceid);
3404 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3406 qemu_devicedel
($vmid, $deviceid);
3407 qemu_devicedelverify
($vmid, $deviceid);
3408 qemu_drivedel
($vmid, $deviceid);
3409 qemu_iothread_del
($conf, $vmid, $deviceid);
3411 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3413 qemu_devicedel
($vmid, $deviceid);
3414 qemu_devicedelverify
($vmid, $deviceid);
3415 qemu_iothread_del
($conf, $vmid, $deviceid);
3417 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3419 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3420 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3421 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3423 qemu_devicedel
($vmid, $deviceid);
3424 qemu_drivedel
($vmid, $deviceid);
3425 qemu_deletescsihw
($conf, $vmid, $deviceid);
3427 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3429 qemu_devicedel
($vmid, $deviceid);
3430 qemu_devicedelverify
($vmid, $deviceid);
3431 qemu_netdevdel
($vmid, $deviceid);
3434 die "can't unplug device '$deviceid'\n";
3440 sub qemu_deviceadd
{
3441 my ($vmid, $devicefull) = @_;
3443 $devicefull = "driver=".$devicefull;
3444 my %options = split(/[=,]/, $devicefull);
3446 vm_mon_cmd
($vmid, "device_add" , %options);
3449 sub qemu_devicedel
{
3450 my ($vmid, $deviceid) = @_;
3452 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3455 sub qemu_iothread_add
{
3456 my($vmid, $deviceid, $device) = @_;
3458 if ($device->{iothread
}) {
3459 my $iothreads = vm_iothreads_list
($vmid);
3460 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3464 sub qemu_iothread_del
{
3465 my($conf, $vmid, $deviceid) = @_;
3467 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3468 if ($device->{iothread
}) {
3469 my $iothreads = vm_iothreads_list
($vmid);
3470 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3474 sub qemu_objectadd
{
3475 my($vmid, $objectid, $qomtype) = @_;
3477 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3482 sub qemu_objectdel
{
3483 my($vmid, $objectid) = @_;
3485 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3491 my ($storecfg, $vmid, $device) = @_;
3493 my $drive = print_drive_full
($storecfg, $vmid, $device);
3494 $drive =~ s/\\/\\\\/g;
3495 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3497 # If the command succeeds qemu prints: "OK
"
3498 return 1 if $ret =~ m/OK/s;
3500 die "adding drive failed
: $ret\n";
3504 my($vmid, $deviceid) = @_;
3506 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3509 return 1 if $ret eq "";
3511 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3512 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3514 die "deleting drive
$deviceid failed
: $ret\n";
3517 sub qemu_deviceaddverify {
3518 my ($vmid, $deviceid) = @_;
3520 for (my $i = 0; $i <= 5; $i++) {
3521 my $devices_list = vm_devices_list($vmid);
3522 return 1 if defined($devices_list->{$deviceid});
3526 die "error on hotplug device
'$deviceid'\n";
3530 sub qemu_devicedelverify {
3531 my ($vmid, $deviceid) = @_;
3533 # need to verify that the device is correctly removed as device_del
3534 # is async and empty return is not reliable
3536 for (my $i = 0; $i <= 5; $i++) {
3537 my $devices_list = vm_devices_list($vmid);
3538 return 1 if !defined($devices_list->{$deviceid});
3542 die "error on hot-unplugging device
'$deviceid'\n";
3545 sub qemu_findorcreatescsihw {
3546 my ($storecfg, $conf, $vmid, $device) = @_;
3548 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3550 my $scsihwid="$controller_prefix$controller";
3551 my $devices_list = vm_devices_list($vmid);
3553 if(!defined($devices_list->{$scsihwid})) {
3554 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3560 sub qemu_deletescsihw {
3561 my ($conf, $vmid, $opt) = @_;
3563 my $device = parse_drive($opt, $conf->{$opt});
3565 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3566 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3570 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3572 my $devices_list = vm_devices_list($vmid);
3573 foreach my $opt (keys %{$devices_list}) {
3574 if (PVE::QemuServer::valid_drivename($opt)) {
3575 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3576 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3582 my $scsihwid="scsihw
$controller";
3584 vm_deviceunplug($vmid, $conf, $scsihwid);
3589 sub qemu_add_pci_bridge {
3590 my ($storecfg, $conf, $vmid, $device) = @_;
3596 print_pci_addr($device, $bridges);
3598 while (my ($k, $v) = each %$bridges) {
3601 return 1 if !defined($bridgeid) || $bridgeid < 1;
3603 my $bridge = "pci
.$bridgeid";
3604 my $devices_list = vm_devices_list($vmid);
3606 if (!defined($devices_list->{$bridge})) {
3607 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3613 sub qemu_set_link_status {
3614 my ($vmid, $device, $up) = @_;
3616 vm_mon_cmd($vmid, "set_link
", name => $device,
3617 up => $up ? JSON::true : JSON::false);
3620 sub qemu_netdevadd {
3621 my ($vmid, $conf, $device, $deviceid) = @_;
3623 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3624 my %options = split(/[=,]/, $netdev);
3626 vm_mon_cmd($vmid, "netdev_add
", %options);
3630 sub qemu_netdevdel {
3631 my ($vmid, $deviceid) = @_;
3633 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3636 sub qemu_cpu_hotplug {
3637 my ($vmid, $conf, $vcpus) = @_;
3640 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3641 $sockets = $conf->{sockets} if $conf->{sockets};
3642 my $cores = $conf->{cores} || 1;
3643 my $maxcpus = $sockets * $cores;
3645 $vcpus = $maxcpus if !$vcpus;
3647 die "you can
't add more vcpus than maxcpus\n"
3648 if $vcpus > $maxcpus;
3650 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3651 die "online cpu unplug is not yet possible\n"
3652 if $vcpus < $currentvcpus;
3654 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3655 die "vcpus in running vm is different than configuration\n"
3656 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3658 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3659 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3663 sub qemu_memory_hotplug {
3664 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3666 return $value if !check_running($vmid);
3668 my $memory = $conf->{memory} || $defaults->{memory};
3669 $value = $defaults->{memory} if !$value;
3670 return $value if $value == $memory;
3672 my $static_memory = $STATICMEM;
3673 my $dimm_memory = $memory - $static_memory;
3675 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3676 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3680 $sockets = $conf->{sockets} if $conf->{sockets};
3682 if($value > $memory) {
3684 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3685 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3687 return if $current_size <= $conf->{memory};
3689 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3691 eval { qemu_objectdel($vmid, "mem-
$name"); };
3695 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3697 eval { qemu_objectdel($vmid, "mem-
$name"); };
3700 #update conf after each succesful module hotplug
3701 $conf->{memory} = $current_size;
3702 update_config_nolock($vmid, $conf, 1);
3707 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3708 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3710 return if $current_size >= $conf->{memory};
3711 print "try to unplug memory dimm
$name\n";
3715 eval { qemu_devicedel($vmid, $name) };
3717 my $dimm_list = qemu_dimm_list($vmid);
3718 last if !$dimm_list->{$name};
3719 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3723 #update conf after each succesful module unplug
3724 $conf->{memory} = $current_size;
3726 eval { qemu_objectdel($vmid, "mem-
$name"); };
3727 update_config_nolock($vmid, $conf, 1);
3732 sub qemu_dimm_list {
3735 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3738 foreach my $dimm (@$dimmarray) {
3740 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3741 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3742 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3743 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3744 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3749 sub qemu_block_set_io_throttle {
3750 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3752 return if !check_running($vmid) ;
3754 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));
3758 # old code, only used to shutdown old VM after update
3760 my ($fh, $timeout) = @_;
3762 my $sel = new IO::Select;
3769 while (scalar (@ready = $sel->can_read($timeout))) {
3771 if ($count = $fh->sysread($buf, 8192)) {
3772 if ($buf =~ /^(.*)\(qemu\) $/s) {
3779 if (!defined($count)) {
3786 die "monitor
read timeout
\n" if !scalar(@ready);
3791 # old code, only used to shutdown old VM after update
3792 sub vm_monitor_command {
3793 my ($vmid, $cmdstr, $nocheck) = @_;
3798 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3800 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3802 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3803 die "unable to
connect to VM
$vmid socket - $!\n";
3807 # hack: migrate sometime blocks the monitor (when migrate_downtime
3809 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3810 $timeout = 60*60; # 1 hour
3814 my $data = __read_avail($sock, $timeout);
3816 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3817 die "got unexpected qemu monitor banner
\n";
3820 my $sel = new IO::Select;
3823 if (!scalar(my @ready = $sel->can_write($timeout))) {
3824 die "monitor
write error
- timeout
";
3827 my $fullcmd = "$cmdstr\r";
3829 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3832 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3833 die "monitor
write error
- $!";
3836 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3840 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3841 $timeout = 60*60; # 1 hour
3842 } elsif ($cmdstr =~ m/^(eject|change)/) {
3843 $timeout = 60; # note: cdrom mount command is slow
3845 if ($res = __read_avail($sock, $timeout)) {
3847 my @lines = split("\r?
\n", $res);
3849 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3851 $res = join("\n", @lines);
3859 syslog("err
", "VM
$vmid monitor command failed
- $err");
3866 sub qemu_block_resize {
3867 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3869 my $running = check_running($vmid);
3871 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3873 return if !$running;
3875 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3879 sub qemu_volume_snapshot {
3880 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3882 my $running = check_running($vmid);
3884 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3885 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3887 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3891 sub qemu_volume_snapshot_delete {
3892 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3894 my $running = check_running($vmid);
3896 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3898 return if !$running;
3900 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3903 sub set_migration_caps {
3909 "auto-converge
" => 1,
3911 "x-rdma-pin-all
" => 0,
3916 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3918 for my $supported_capability (@$supported_capabilities) {
3920 capability => $supported_capability->{capability},
3921 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3925 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3928 my $fast_plug_option = {
3937 # hotplug changes in [PENDING]
3938 # $selection hash can be used to only apply specified options, for
3939 # example: { cores => 1 } (only apply changed 'cores')
3940 # $errors ref is used to return error messages
3941 sub vmconfig_hotplug_pending {
3942 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3944 my $defaults = load_defaults();
3946 # commit values which do not have any impact on running VM first
3947 # Note: those option cannot raise errors, we we do not care about
3948 # $selection and always apply them.
3950 my $add_error = sub {
3951 my ($opt, $msg) = @_;
3952 $errors->{$opt} = "hotplug problem
- $msg";
3956 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3957 if ($fast_plug_option->{$opt}) {
3958 $conf->{$opt} = $conf->{pending}->{$opt};
3959 delete $conf->{pending}->{$opt};
3965 update_config_nolock($vmid, $conf, 1);
3966 $conf = load_config($vmid); # update/reload
3969 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3971 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3972 while (my ($opt, $force) = each %$pending_delete_hash) {
3973 next if $selection && !$selection->{$opt};
3975 if ($opt eq 'hotplug') {
3976 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3977 } elsif ($opt eq 'tablet') {
3978 die "skip
\n" if !$hotplug_features->{usb};
3979 if ($defaults->{tablet}) {
3980 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3982 vm_deviceunplug($vmid, $conf, $opt);
3984 } elsif ($opt eq 'vcpus') {
3985 die "skip
\n" if !$hotplug_features->{cpu};
3986 qemu_cpu_hotplug($vmid, $conf, undef);
3987 } elsif ($opt eq 'balloon') {
3988 # enable balloon device is not hotpluggable
3989 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3990 } elsif ($fast_plug_option->{$opt}) {
3992 } elsif ($opt =~ m/^net(\d+)$/) {
3993 die "skip
\n" if !$hotplug_features->{network};
3994 vm_deviceunplug($vmid, $conf, $opt);
3995 } elsif (valid_drivename($opt)) {
3996 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3997 vm_deviceunplug($vmid, $conf, $opt);
3998 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3999 } elsif ($opt =~ m/^memory$/) {
4000 die "skip
\n" if !$hotplug_features->{memory};
4001 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4002 } elsif ($opt eq 'cpuunits') {
4003 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4004 } elsif ($opt eq 'cpulimit') {
4005 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4011 &$add_error($opt, $err) if $err ne "skip
\n";
4013 # save new config if hotplug was successful
4014 delete $conf->{$opt};
4015 vmconfig_undelete_pending_option($conf, $opt);
4016 update_config_nolock($vmid, $conf, 1);
4017 $conf = load_config($vmid); # update/reload
4021 foreach my $opt (keys %{$conf->{pending}}) {
4022 next if $selection && !$selection->{$opt};
4023 my $value = $conf->{pending}->{$opt};
4025 if ($opt eq 'hotplug') {
4026 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4027 } elsif ($opt eq 'tablet') {
4028 die "skip
\n" if !$hotplug_features->{usb};
4030 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4031 } elsif ($value == 0) {
4032 vm_deviceunplug($vmid, $conf, $opt);
4034 } elsif ($opt eq 'vcpus') {
4035 die "skip
\n" if !$hotplug_features->{cpu};
4036 qemu_cpu_hotplug($vmid, $conf, $value);
4037 } elsif ($opt eq 'balloon') {
4038 # enable/disable balloning device is not hotpluggable
4039 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4040 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4041 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4043 # allow manual ballooning if shares is set to zero
4044 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4045 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4046 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4048 } elsif ($opt =~ m/^net(\d+)$/) {
4049 # some changes can be done without hotplug
4050 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4051 $vmid, $opt, $value);
4052 } elsif (valid_drivename($opt)) {
4053 # some changes can be done without hotplug
4054 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4055 $vmid, $opt, $value, 1);
4056 } elsif ($opt =~ m/^memory$/) { #dimms
4057 die "skip
\n" if !$hotplug_features->{memory};
4058 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4059 } elsif ($opt eq 'cpuunits') {
4060 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4061 } elsif ($opt eq 'cpulimit') {
4062 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4063 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4065 die "skip
\n"; # skip non-hot-pluggable options
4069 &$add_error($opt, $err) if $err ne "skip
\n";
4071 # save new config if hotplug was successful
4072 $conf->{$opt} = $value;
4073 delete $conf->{pending}->{$opt};
4074 update_config_nolock($vmid, $conf, 1);
4075 $conf = load_config($vmid); # update/reload
4080 sub try_deallocate_drive {
4081 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4083 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4084 my $volid = $drive->{file};
4085 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4086 my $sid = PVE::Storage::parse_volume_id($volid);
4087 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4089 # check if the disk is really unused
4090 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4091 my $path = PVE::Storage::path($storecfg, $volid);
4092 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4093 if $used_paths->{$path};
4094 PVE::Storage::vdisk_free($storecfg, $volid);
4097 # If vm is not owner of this disk remove from config
4105 sub vmconfig_delete_or_detach_drive {
4106 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4108 my $drive = parse_drive($opt, $conf->{$opt});
4110 my $rpcenv = PVE::RPCEnvironment::get();
4111 my $authuser = $rpcenv->get_user();
4114 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4115 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4117 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4121 sub vmconfig_apply_pending {
4122 my ($vmid, $conf, $storecfg) = @_;
4126 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4127 while (my ($opt, $force) = each %$pending_delete_hash) {
4128 die "internal error
" if $opt =~ m/^unused/;
4129 $conf = load_config($vmid); # update/reload
4130 if (!defined($conf->{$opt})) {
4131 vmconfig_undelete_pending_option($conf, $opt);
4132 update_config_nolock($vmid, $conf, 1);
4133 } elsif (valid_drivename($opt)) {
4134 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4135 vmconfig_undelete_pending_option($conf, $opt);
4136 delete $conf->{$opt};
4137 update_config_nolock($vmid, $conf, 1);
4139 vmconfig_undelete_pending_option($conf, $opt);
4140 delete $conf->{$opt};
4141 update_config_nolock($vmid, $conf, 1);
4145 $conf = load_config($vmid); # update/reload
4147 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4148 $conf = load_config($vmid); # update/reload
4150 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4151 # skip if nothing changed
4152 } elsif (valid_drivename($opt)) {
4153 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4154 if defined($conf->{$opt});
4155 $conf->{$opt} = $conf->{pending}->{$opt};
4157 $conf->{$opt} = $conf->{pending}->{$opt};
4160 delete $conf->{pending}->{$opt};
4161 update_config_nolock($vmid, $conf, 1);
4165 my $safe_num_ne = sub {
4168 return 0 if !defined($a) && !defined($b);
4169 return 1 if !defined($a);
4170 return 1 if !defined($b);
4175 my $safe_string_ne = sub {
4178 return 0 if !defined($a) && !defined($b);
4179 return 1 if !defined($a);
4180 return 1 if !defined($b);
4185 sub vmconfig_update_net {
4186 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4188 my $newnet = parse_net($value);
4190 if ($conf->{$opt}) {
4191 my $oldnet = parse_net($conf->{$opt});
4193 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4194 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4195 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4196 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4198 # for non online change, we try to hot-unplug
4199 die "skip
\n" if !$hotplug;
4200 vm_deviceunplug($vmid, $conf, $opt);
4203 die "internal error
" if $opt !~ m/net(\d+)/;
4204 my $iface = "tap
${vmid
}i
$1";
4206 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4207 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4210 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4211 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4212 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4213 PVE::Network::tap_unplug($iface);
4214 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4217 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4218 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4226 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4232 sub vmconfig_update_disk {
4233 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4235 # fixme: do we need force?
4237 my $drive = parse_drive($opt, $value);
4239 if ($conf->{$opt}) {
4241 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4243 my $media = $drive->{media} || 'disk';
4244 my $oldmedia = $old_drive->{media} || 'disk';
4245 die "unable to change media type
\n" if $media ne $oldmedia;
4247 if (!drive_is_cdrom($old_drive)) {
4249 if ($drive->{file} ne $old_drive->{file}) {
4251 die "skip
\n" if !$hotplug;
4253 # unplug and register as unused
4254 vm_deviceunplug($vmid, $conf, $opt);
4255 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4258 # update existing disk
4260 # skip non hotpluggable value
4261 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4262 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4263 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4264 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4269 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4270 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4271 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4272 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4273 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4274 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4275 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4276 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4277 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4278 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4279 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4280 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4282 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4283 ($drive->{mbps} || 0)*1024*1024,
4284 ($drive->{mbps_rd} || 0)*1024*1024,
4285 ($drive->{mbps_wr} || 0)*1024*1024,
4286 $drive->{iops} || 0,
4287 $drive->{iops_rd} || 0,
4288 $drive->{iops_wr} || 0,
4289 ($drive->{mbps_max} || 0)*1024*1024,
4290 ($drive->{mbps_rd_max} || 0)*1024*1024,
4291 ($drive->{mbps_wr_max} || 0)*1024*1024,
4292 $drive->{iops_max} || 0,
4293 $drive->{iops_rd_max} || 0,
4294 $drive->{iops_wr_max} || 0);
4303 if ($drive->{file} eq 'none') {
4304 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4306 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4307 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4308 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4316 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4318 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
4319 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4323 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4324 $forcemachine, $spice_ticket) = @_;
4326 lock_config($vmid, sub {
4327 my $conf = load_config($vmid, $migratedfrom);
4329 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4331 check_lock($conf) if !$skiplock;
4333 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4335 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4336 vmconfig_apply_pending($vmid, $conf, $storecfg);
4337 $conf = load_config($vmid); # update/reload
4340 my $defaults = load_defaults();
4342 # set environment variable useful inside network script
4343 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4345 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4347 my $migrate_port = 0;
4350 if ($statefile eq 'tcp') {
4351 my $localip = "localhost
";
4352 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4353 my $nodename = PVE::INotify::nodename();
4354 if ($datacenterconf->{migration_unsecure}) {
4355 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4356 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4358 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4359 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4360 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4361 push @$cmd, '-incoming', $migrate_uri;
4364 push @$cmd, '-loadstate', $statefile;
4371 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4372 my $d = parse_hostpci($conf->{"hostpci
$i"});
4374 my $pcidevices = $d->{pciid};
4375 foreach my $pcidevice (@$pcidevices) {
4376 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4378 my $info = pci_device_info("0000:$pciid");
4379 die "IOMMU
not present
\n" if !check_iommu_support();
4380 die "no pci device info
for device
'$pciid'\n" if !$info;
4381 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4382 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4386 PVE::Storage::activate_volumes($storecfg, $vollist);
4388 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4391 die "start failed
: $err" if $err;
4393 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4395 if ($statefile && $statefile ne 'tcp') {
4396 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4400 if ($migratedfrom) {
4403 set_migration_caps($vmid);
4408 print "spice listens on port
$spice_port\n";
4409 if ($spice_ticket) {
4410 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4411 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4417 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4418 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4419 if $conf->{balloon};
4422 foreach my $opt (keys %$conf) {
4423 next if $opt !~ m/^net\d+$/;
4424 my $nicconf = parse_net($conf->{$opt});
4425 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4429 vm_mon_cmd_nocheck($vmid, 'qom-set',
4430 path => "machine
/peripheral/balloon0
",
4431 property => "guest-stats-polling-interval
",
4432 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4438 my ($vmid, $execute, %params) = @_;
4440 my $cmd = { execute => $execute, arguments => \%params };
4441 vm_qmp_command($vmid, $cmd);
4444 sub vm_mon_cmd_nocheck {
4445 my ($vmid, $execute, %params) = @_;
4447 my $cmd = { execute => $execute, arguments => \%params };
4448 vm_qmp_command($vmid, $cmd, 1);
4451 sub vm_qmp_command {
4452 my ($vmid, $cmd, $nocheck) = @_;
4457 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4458 $timeout = $cmd->{arguments}->{timeout};
4459 delete $cmd->{arguments}->{timeout};
4463 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4464 my $sname = qmp_socket($vmid);
4465 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4466 my $qmpclient = PVE::QMPClient->new();
4468 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4469 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4470 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4471 if scalar(%{$cmd->{arguments}});
4472 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4474 die "unable to open monitor socket\n";
4478 syslog("err", "VM $vmid qmp command failed - $err");
4485 sub vm_human_monitor_command {
4486 my ($vmid, $cmdline) = @_;
4491 execute => 'human-monitor-command
',
4492 arguments => { 'command-line
' => $cmdline},
4495 return vm_qmp_command($vmid, $cmd);
4498 sub vm_commandline {
4499 my ($storecfg, $vmid) = @_;
4501 my $conf = load_config($vmid);
4503 my $defaults = load_defaults();
4505 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4507 return join(' ', @$cmd);
4511 my ($vmid, $skiplock) = @_;
4513 lock_config($vmid, sub {
4515 my $conf = load_config($vmid);
4517 check_lock($conf) if !$skiplock;
4519 vm_mon_cmd($vmid, "system_reset");
4523 sub get_vm_volumes {
4527 foreach_volid($conf, sub {
4528 my ($volid, $is_cdrom) = @_;
4530 return if $volid =~ m|^/|;
4532 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4535 push @$vollist, $volid;
4541 sub vm_stop_cleanup {
4542 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4547 my $vollist = get_vm_volumes($conf);
4548 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4551 foreach my $ext (qw(mon qmp pid vnc qga)) {
4552 unlink "/var/run/qemu-server/${vmid}.$ext";
4555 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4557 warn $@ if $@; # avoid errors - just warn
4560 # Note: use $nockeck to skip tests if VM configuration file exists.
4561 # We need that when migration VMs to other nodes (files already moved)
4562 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4564 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4566 $force = 1 if !defined($force) && !$shutdown;
4569 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4570 kill 15, $pid if $pid;
4571 my $conf = load_config
($vmid, $migratedfrom);
4572 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4576 lock_config
($vmid, sub {
4578 my $pid = check_running
($vmid, $nocheck);
4583 $conf = load_config
($vmid);
4584 check_lock
($conf) if !$skiplock;
4585 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4586 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4587 $timeout = $opts->{down
} if $opts->{down
};
4591 $timeout = 60 if !defined($timeout);
4595 if (defined($conf) && $conf->{agent
}) {
4596 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4598 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4601 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4608 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4613 if ($count >= $timeout) {
4615 warn "VM still running - terminating now with SIGTERM\n";
4618 die "VM quit/powerdown failed - got timeout\n";
4621 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4626 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4629 die "VM quit/powerdown failed\n";
4637 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4642 if ($count >= $timeout) {
4643 warn "VM still running - terminating now with SIGKILL\n";
4648 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4653 my ($vmid, $skiplock) = @_;
4655 lock_config
($vmid, sub {
4657 my $conf = load_config
($vmid);
4659 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4661 vm_mon_cmd
($vmid, "stop");
4666 my ($vmid, $skiplock, $nocheck) = @_;
4668 lock_config
($vmid, sub {
4672 my $conf = load_config
($vmid);
4674 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4676 vm_mon_cmd
($vmid, "cont");
4679 vm_mon_cmd_nocheck
($vmid, "cont");
4685 my ($vmid, $skiplock, $key) = @_;
4687 lock_config
($vmid, sub {
4689 my $conf = load_config
($vmid);
4691 # there is no qmp command, so we use the human monitor command
4692 vm_human_monitor_command
($vmid, "sendkey $key");
4697 my ($storecfg, $vmid, $skiplock) = @_;
4699 lock_config
($vmid, sub {
4701 my $conf = load_config
($vmid);
4703 check_lock
($conf) if !$skiplock;
4705 if (!check_running
($vmid)) {
4706 destroy_vm
($storecfg, $vmid);
4708 die "VM $vmid is running - destroy failed\n";
4716 my ($filename, $buf) = @_;
4718 my $fh = IO
::File-
>new($filename, "w");
4719 return undef if !$fh;
4721 my $res = print $fh $buf;
4728 sub pci_device_info
{
4733 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4734 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4736 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4737 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4739 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4740 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4742 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4743 return undef if !defined($product) || $product !~ s/^0x//;
4748 product
=> $product,
4754 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4763 my $name = $dev->{name
};
4765 my $fn = "$pcisysfs/devices/$name/reset";
4767 return file_write
($fn, "1");
4770 sub pci_dev_bind_to_vfio
{
4773 my $name = $dev->{name
};
4775 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4777 if (!-d
$vfio_basedir) {
4778 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4780 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4782 my $testdir = "$vfio_basedir/$name";
4783 return 1 if -d
$testdir;
4785 my $data = "$dev->{vendor} $dev->{product}";
4786 return undef if !file_write
("$vfio_basedir/new_id", $data);
4788 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4789 if (!file_write
($fn, $name)) {
4790 return undef if -f
$fn;
4793 $fn = "$vfio_basedir/bind";
4794 if (! -d
$testdir) {
4795 return undef if !file_write
($fn, $name);
4801 sub pci_dev_group_bind_to_vfio
{
4804 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4806 if (!-d
$vfio_basedir) {
4807 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4809 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4811 # get IOMMU group devices
4812 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4813 my @devs = grep /^0000:/, readdir($D);
4816 foreach my $pciid (@devs) {
4817 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4819 # pci bridges, switches or root ports are not supported
4820 # they have a pci_bus subdirectory so skip them
4821 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4823 my $info = pci_device_info
($1);
4824 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4830 sub print_pci_addr
{
4831 my ($id, $bridges) = @_;
4835 piix3
=> { bus
=> 0, addr
=> 1 },
4836 #addr2 : first videocard
4837 balloon0
=> { bus
=> 0, addr
=> 3 },
4838 watchdog
=> { bus
=> 0, addr
=> 4 },
4839 scsihw0
=> { bus
=> 0, addr
=> 5 },
4840 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4841 scsihw1
=> { bus
=> 0, addr
=> 6 },
4842 ahci0
=> { bus
=> 0, addr
=> 7 },
4843 qga0
=> { bus
=> 0, addr
=> 8 },
4844 spice
=> { bus
=> 0, addr
=> 9 },
4845 virtio0
=> { bus
=> 0, addr
=> 10 },
4846 virtio1
=> { bus
=> 0, addr
=> 11 },
4847 virtio2
=> { bus
=> 0, addr
=> 12 },
4848 virtio3
=> { bus
=> 0, addr
=> 13 },
4849 virtio4
=> { bus
=> 0, addr
=> 14 },
4850 virtio5
=> { bus
=> 0, addr
=> 15 },
4851 hostpci0
=> { bus
=> 0, addr
=> 16 },
4852 hostpci1
=> { bus
=> 0, addr
=> 17 },
4853 net0
=> { bus
=> 0, addr
=> 18 },
4854 net1
=> { bus
=> 0, addr
=> 19 },
4855 net2
=> { bus
=> 0, addr
=> 20 },
4856 net3
=> { bus
=> 0, addr
=> 21 },
4857 net4
=> { bus
=> 0, addr
=> 22 },
4858 net5
=> { bus
=> 0, addr
=> 23 },
4859 vga1
=> { bus
=> 0, addr
=> 24 },
4860 vga2
=> { bus
=> 0, addr
=> 25 },
4861 vga3
=> { bus
=> 0, addr
=> 26 },
4862 hostpci2
=> { bus
=> 0, addr
=> 27 },
4863 hostpci3
=> { bus
=> 0, addr
=> 28 },
4864 #addr29 : usb-host (pve-usb.cfg)
4865 'pci.1' => { bus
=> 0, addr
=> 30 },
4866 'pci.2' => { bus
=> 0, addr
=> 31 },
4867 'net6' => { bus
=> 1, addr
=> 1 },
4868 'net7' => { bus
=> 1, addr
=> 2 },
4869 'net8' => { bus
=> 1, addr
=> 3 },
4870 'net9' => { bus
=> 1, addr
=> 4 },
4871 'net10' => { bus
=> 1, addr
=> 5 },
4872 'net11' => { bus
=> 1, addr
=> 6 },
4873 'net12' => { bus
=> 1, addr
=> 7 },
4874 'net13' => { bus
=> 1, addr
=> 8 },
4875 'net14' => { bus
=> 1, addr
=> 9 },
4876 'net15' => { bus
=> 1, addr
=> 10 },
4877 'net16' => { bus
=> 1, addr
=> 11 },
4878 'net17' => { bus
=> 1, addr
=> 12 },
4879 'net18' => { bus
=> 1, addr
=> 13 },
4880 'net19' => { bus
=> 1, addr
=> 14 },
4881 'net20' => { bus
=> 1, addr
=> 15 },
4882 'net21' => { bus
=> 1, addr
=> 16 },
4883 'net22' => { bus
=> 1, addr
=> 17 },
4884 'net23' => { bus
=> 1, addr
=> 18 },
4885 'net24' => { bus
=> 1, addr
=> 19 },
4886 'net25' => { bus
=> 1, addr
=> 20 },
4887 'net26' => { bus
=> 1, addr
=> 21 },
4888 'net27' => { bus
=> 1, addr
=> 22 },
4889 'net28' => { bus
=> 1, addr
=> 23 },
4890 'net29' => { bus
=> 1, addr
=> 24 },
4891 'net30' => { bus
=> 1, addr
=> 25 },
4892 'net31' => { bus
=> 1, addr
=> 26 },
4893 'virtio6' => { bus
=> 2, addr
=> 1 },
4894 'virtio7' => { bus
=> 2, addr
=> 2 },
4895 'virtio8' => { bus
=> 2, addr
=> 3 },
4896 'virtio9' => { bus
=> 2, addr
=> 4 },
4897 'virtio10' => { bus
=> 2, addr
=> 5 },
4898 'virtio11' => { bus
=> 2, addr
=> 6 },
4899 'virtio12' => { bus
=> 2, addr
=> 7 },
4900 'virtio13' => { bus
=> 2, addr
=> 8 },
4901 'virtio14' => { bus
=> 2, addr
=> 9 },
4902 'virtio15' => { bus
=> 2, addr
=> 10 },
4903 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4904 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4905 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4906 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4907 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4908 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4909 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4910 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4911 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4912 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4913 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4914 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4915 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4916 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4917 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4918 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4919 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4920 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4921 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4922 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4923 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4924 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4925 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4926 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4927 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4928 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4929 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4930 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4931 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4932 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4933 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4937 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4938 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4939 my $bus = $devices->{$id}->{bus
};
4940 $res = ",bus=pci.$bus,addr=$addr";
4941 $bridges->{$bus} = 1 if $bridges;
4947 sub print_pcie_addr
{
4952 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4953 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4954 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4955 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4958 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4959 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4960 my $bus = $devices->{$id}->{bus
};
4961 $res = ",bus=$bus,addr=$addr";
4967 # vzdump restore implementaion
4969 sub tar_archive_read_firstfile
{
4970 my $archive = shift;
4972 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4974 # try to detect archive type first
4975 my $pid = open (TMP
, "tar tf '$archive'|") ||
4976 die "unable to open file '$archive'\n";
4977 my $firstfile = <TMP
>;
4981 die "ERROR: archive contaions no data\n" if !$firstfile;
4987 sub tar_restore_cleanup
{
4988 my ($storecfg, $statfile) = @_;
4990 print STDERR
"starting cleanup\n";
4992 if (my $fd = IO
::File-
>new($statfile, "r")) {
4993 while (defined(my $line = <$fd>)) {
4994 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4997 if ($volid =~ m
|^/|) {
4998 unlink $volid || die 'unlink failed\n';
5000 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5002 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5004 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5006 print STDERR
"unable to parse line in statfile - $line";
5013 sub restore_archive
{
5014 my ($archive, $vmid, $user, $opts) = @_;
5016 my $format = $opts->{format
};
5019 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5020 $format = 'tar' if !$format;
5022 } elsif ($archive =~ m/\.tar$/) {
5023 $format = 'tar' if !$format;
5024 } elsif ($archive =~ m/.tar.lzo$/) {
5025 $format = 'tar' if !$format;
5027 } elsif ($archive =~ m/\.vma$/) {
5028 $format = 'vma' if !$format;
5029 } elsif ($archive =~ m/\.vma\.gz$/) {
5030 $format = 'vma' if !$format;
5032 } elsif ($archive =~ m/\.vma\.lzo$/) {
5033 $format = 'vma' if !$format;
5036 $format = 'vma' if !$format; # default
5039 # try to detect archive format
5040 if ($format eq 'tar') {
5041 return restore_tar_archive
($archive, $vmid, $user, $opts);
5043 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5047 sub restore_update_config_line
{
5048 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5050 return if $line =~ m/^\#qmdump\#/;
5051 return if $line =~ m/^\#vzdump\#/;
5052 return if $line =~ m/^lock:/;
5053 return if $line =~ m/^unused\d+:/;
5054 return if $line =~ m/^parent:/;
5055 return if $line =~ m/^template:/; # restored VM is never a template
5057 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5058 # try to convert old 1.X settings
5059 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5060 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5061 my ($model, $macaddr) = split(/\=/, $devconfig);
5062 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5065 bridge
=> "vmbr$ind",
5066 macaddr
=> $macaddr,
5068 my $netstr = print_net
($net);
5070 print $outfd "net$cookie->{netcount}: $netstr\n";
5071 $cookie->{netcount
}++;
5073 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5074 my ($id, $netstr) = ($1, $2);
5075 my $net = parse_net
($netstr);
5076 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5077 $netstr = print_net
($net);
5078 print $outfd "$id: $netstr\n";
5079 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5082 if ($line =~ m/backup=no/) {
5083 print $outfd "#$line";
5084 } elsif ($virtdev && $map->{$virtdev}) {
5085 my $di = parse_drive
($virtdev, $value);
5086 delete $di->{format
}; # format can change on restore
5087 $di->{file
} = $map->{$virtdev};
5088 $value = print_drive
($vmid, $di);
5089 print $outfd "$virtdev: $value\n";
5099 my ($cfg, $vmid) = @_;
5101 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5103 my $volid_hash = {};
5104 foreach my $storeid (keys %$info) {
5105 foreach my $item (@{$info->{$storeid}}) {
5106 next if !($item->{volid
} && $item->{size
});
5107 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5108 $volid_hash->{$item->{volid
}} = $item;
5115 sub get_used_paths
{
5116 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5120 my $scan_config = sub {
5121 my ($cref, $snapname) = @_;
5123 foreach my $key (keys %$cref) {
5124 my $value = $cref->{$key};
5125 if (valid_drivename
($key)) {
5126 next if $skip_drive && $key eq $skip_drive;
5127 my $drive = parse_drive
($key, $value);
5128 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5129 if ($drive->{file
} =~ m!^/!) {
5130 $used_path->{$drive->{file
}}++; # = 1;
5132 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5134 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5136 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5137 $used_path->{$path}++; # = 1;
5143 &$scan_config($conf);
5147 if ($scan_snapshots) {
5148 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5149 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5156 sub update_disksize
{
5157 my ($vmid, $conf, $volid_hash) = @_;
5163 # Note: it is allowed to define multiple storages with same path (alias), so
5164 # we need to check both 'volid' and real 'path' (two different volid can point
5165 # to the same path).
5170 foreach my $opt (keys %$conf) {
5171 if (valid_drivename
($opt)) {
5172 my $drive = parse_drive
($opt, $conf->{$opt});
5173 my $volid = $drive->{file
};
5176 $used->{$volid} = 1;
5177 if ($volid_hash->{$volid} &&
5178 (my $path = $volid_hash->{$volid}->{path
})) {
5179 $usedpath->{$path} = 1;
5182 next if drive_is_cdrom
($drive);
5183 next if !$volid_hash->{$volid};
5185 $drive->{size
} = $volid_hash->{$volid}->{size
};
5186 my $new = print_drive
($vmid, $drive);
5187 if ($new ne $conf->{$opt}) {
5189 $conf->{$opt} = $new;
5194 # remove 'unusedX' entry if volume is used
5195 foreach my $opt (keys %$conf) {
5196 next if $opt !~ m/^unused\d+$/;
5197 my $volid = $conf->{$opt};
5198 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5199 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5201 delete $conf->{$opt};
5205 foreach my $volid (sort keys %$volid_hash) {
5206 next if $volid =~ m/vm-$vmid-state-/;
5207 next if $used->{$volid};
5208 my $path = $volid_hash->{$volid}->{path
};
5209 next if !$path; # just to be sure
5210 next if $usedpath->{$path};
5212 add_unused_volume
($conf, $volid);
5213 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5220 my ($vmid, $nolock) = @_;
5222 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5224 my $volid_hash = scan_volids
($cfg, $vmid);
5226 my $updatefn = sub {
5229 my $conf = load_config
($vmid);
5234 foreach my $volid (keys %$volid_hash) {
5235 my $info = $volid_hash->{$volid};
5236 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5239 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5241 update_config_nolock
($vmid, $conf, 1) if $changes;
5244 if (defined($vmid)) {
5248 lock_config
($vmid, $updatefn, $vmid);
5251 my $vmlist = config_list
();
5252 foreach my $vmid (keys %$vmlist) {
5256 lock_config
($vmid, $updatefn, $vmid);
5262 sub restore_vma_archive
{
5263 my ($archive, $vmid, $user, $opts, $comp) = @_;
5265 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5266 my $readfrom = $archive;
5271 my $qarchive = PVE
::Tools
::shellquote
($archive);
5272 if ($comp eq 'gzip') {
5273 $uncomp = "zcat $qarchive|";
5274 } elsif ($comp eq 'lzop') {
5275 $uncomp = "lzop -d -c $qarchive|";
5277 die "unknown compression method '$comp'\n";
5282 my $tmpdir = "/var/tmp/vzdumptmp$$";
5285 # disable interrupts (always do cleanups)
5286 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5287 warn "got interrupt - ignored\n";
5290 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5291 POSIX
::mkfifo
($mapfifo, 0600);
5294 my $openfifo = sub {
5295 open($fifofh, '>', $mapfifo) || die $!;
5298 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5305 my $rpcenv = PVE
::RPCEnvironment
::get
();
5307 my $conffile = config_file
($vmid);
5308 my $tmpfn = "$conffile.$$.tmp";
5310 # Note: $oldconf is undef if VM does not exists
5311 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5313 my $print_devmap = sub {
5314 my $virtdev_hash = {};
5316 my $cfgfn = "$tmpdir/qemu-server.conf";
5318 # we can read the config - that is already extracted
5319 my $fh = IO
::File-
>new($cfgfn, "r") ||
5320 "unable to read qemu-server.conf - $!\n";
5322 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5323 PVE
::Tools
::file_copy
($fwcfgfn, "/etc/pve/firewall/$vmid.fw")
5326 while (defined(my $line = <$fh>)) {
5327 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5328 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5329 die "archive does not contain data for drive '$virtdev'\n"
5330 if !$devinfo->{$devname};
5331 if (defined($opts->{storage
})) {
5332 $storeid = $opts->{storage
} || 'local';
5333 } elsif (!$storeid) {
5336 $format = 'raw' if !$format;
5337 $devinfo->{$devname}->{devname
} = $devname;
5338 $devinfo->{$devname}->{virtdev
} = $virtdev;
5339 $devinfo->{$devname}->{format
} = $format;
5340 $devinfo->{$devname}->{storeid
} = $storeid;
5342 # check permission on storage
5343 my $pool = $opts->{pool
}; # todo: do we need that?
5344 if ($user ne 'root@pam') {
5345 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5348 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5352 foreach my $devname (keys %$devinfo) {
5353 die "found no device mapping information for device '$devname'\n"
5354 if !$devinfo->{$devname}->{virtdev
};
5357 my $cfg = cfs_read_file
('storage.cfg');
5359 # create empty/temp config
5361 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5362 foreach_drive
($oldconf, sub {
5363 my ($ds, $drive) = @_;
5365 return if drive_is_cdrom
($drive);
5367 my $volid = $drive->{file
};
5369 return if !$volid || $volid =~ m
|^/|;
5371 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5372 return if !$path || !$owner || ($owner != $vmid);
5374 # Note: only delete disk we want to restore
5375 # other volumes will become unused
5376 if ($virtdev_hash->{$ds}) {
5377 PVE
::Storage
::vdisk_free
($cfg, $volid);
5383 foreach my $virtdev (sort keys %$virtdev_hash) {
5384 my $d = $virtdev_hash->{$virtdev};
5385 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5386 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5388 # test if requested format is supported
5389 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5390 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5391 $d->{format
} = $defFormat if !$supported;
5393 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5394 $d->{format
}, undef, $alloc_size);
5395 print STDERR
"new volume ID is '$volid'\n";
5396 $d->{volid
} = $volid;
5397 my $path = PVE
::Storage
::path
($cfg, $volid);
5399 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5401 my $write_zeros = 1;
5402 # fixme: what other storages types initialize volumes with zero?
5403 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5404 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5408 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5410 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5411 $map->{$virtdev} = $volid;
5414 $fh->seek(0, 0) || die "seek failed - $!\n";
5416 my $outfd = new IO
::File
($tmpfn, "w") ||
5417 die "unable to write config for VM $vmid\n";
5419 my $cookie = { netcount
=> 0 };
5420 while (defined(my $line = <$fh>)) {
5421 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5430 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5431 die "interrupted by signal\n";
5433 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5435 $oldtimeout = alarm($timeout);
5442 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5443 my ($dev_id, $size, $devname) = ($1, $2, $3);
5444 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5445 } elsif ($line =~ m/^CTIME: /) {
5446 # we correctly received the vma config, so we can disable
5447 # the timeout now for disk allocation (set to 10 minutes, so
5448 # that we always timeout if something goes wrong)
5451 print $fifofh "done\n";
5452 my $tmp = $oldtimeout || 0;
5453 $oldtimeout = undef;
5459 print "restore vma archive: $cmd\n";
5460 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5464 alarm($oldtimeout) if $oldtimeout;
5467 foreach my $devname (keys %$devinfo) {
5468 my $volid = $devinfo->{$devname}->{volid
};
5469 push @$vollist, $volid if $volid;
5472 my $cfg = cfs_read_file
('storage.cfg');
5473 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5481 foreach my $devname (keys %$devinfo) {
5482 my $volid = $devinfo->{$devname}->{volid
};
5485 if ($volid =~ m
|^/|) {
5486 unlink $volid || die 'unlink failed\n';
5488 PVE
::Storage
::vdisk_free
($cfg, $volid);
5490 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5492 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5499 rename($tmpfn, $conffile) ||
5500 die "unable to commit configuration file '$conffile'\n";
5502 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5504 eval { rescan
($vmid, 1); };
5508 sub restore_tar_archive
{
5509 my ($archive, $vmid, $user, $opts) = @_;
5511 if ($archive ne '-') {
5512 my $firstfile = tar_archive_read_firstfile
($archive);
5513 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5514 if $firstfile ne 'qemu-server.conf';
5517 my $storecfg = cfs_read_file
('storage.cfg');
5519 # destroy existing data - keep empty config
5520 my $vmcfgfn = config_file
($vmid);
5521 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5523 my $tocmd = "/usr/lib/qemu-server/qmextract";
5525 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5526 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5527 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5528 $tocmd .= ' --info' if $opts->{info
};
5530 # tar option "xf" does not autodetect compression when read from STDIN,
5531 # so we pipe to zcat
5532 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5533 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5535 my $tmpdir = "/var/tmp/vzdumptmp$$";
5538 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5539 local $ENV{VZDUMP_VMID
} = $vmid;
5540 local $ENV{VZDUMP_USER
} = $user;
5542 my $conffile = config_file
($vmid);
5543 my $tmpfn = "$conffile.$$.tmp";
5545 # disable interrupts (always do cleanups)
5546 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5547 print STDERR
"got interrupt - ignored\n";
5552 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5553 die "interrupted by signal\n";
5556 if ($archive eq '-') {
5557 print "extracting archive from STDIN\n";
5558 run_command
($cmd, input
=> "<&STDIN");
5560 print "extracting archive '$archive'\n";
5564 return if $opts->{info
};
5568 my $statfile = "$tmpdir/qmrestore.stat";
5569 if (my $fd = IO
::File-
>new($statfile, "r")) {
5570 while (defined (my $line = <$fd>)) {
5571 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5572 $map->{$1} = $2 if $1;
5574 print STDERR
"unable to parse line in statfile - $line\n";
5580 my $confsrc = "$tmpdir/qemu-server.conf";
5582 my $srcfd = new IO
::File
($confsrc, "r") ||
5583 die "unable to open file '$confsrc'\n";
5585 my $outfd = new IO
::File
($tmpfn, "w") ||
5586 die "unable to write config for VM $vmid\n";
5588 my $cookie = { netcount
=> 0 };
5589 while (defined (my $line = <$srcfd>)) {
5590 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5602 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5609 rename $tmpfn, $conffile ||
5610 die "unable to commit configuration file '$conffile'\n";
5612 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5614 eval { rescan
($vmid, 1); };
5619 # Internal snapshots
5621 # NOTE: Snapshot create/delete involves several non-atomic
5622 # action, and can take a long time.
5623 # So we try to avoid locking the file and use 'lock' variable
5624 # inside the config file instead.
5626 my $snapshot_copy_config = sub {
5627 my ($source, $dest) = @_;
5629 foreach my $k (keys %$source) {
5630 next if $k eq 'snapshots';
5631 next if $k eq 'snapstate';
5632 next if $k eq 'snaptime';
5633 next if $k eq 'vmstate';
5634 next if $k eq 'lock';
5635 next if $k eq 'digest';
5636 next if $k eq 'description';
5637 next if $k =~ m/^unused\d+$/;
5639 $dest->{$k} = $source->{$k};
5643 my $snapshot_apply_config = sub {
5644 my ($conf, $snap) = @_;
5646 # copy snapshot list
5648 snapshots
=> $conf->{snapshots
},
5651 # keep description and list of unused disks
5652 foreach my $k (keys %$conf) {
5653 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5654 $newconf->{$k} = $conf->{$k};
5657 &$snapshot_copy_config($snap, $newconf);
5662 sub foreach_writable_storage
{
5663 my ($conf, $func) = @_;
5667 foreach my $ds (keys %$conf) {
5668 next if !valid_drivename
($ds);
5670 my $drive = parse_drive
($ds, $conf->{$ds});
5672 next if drive_is_cdrom
($drive);
5674 my $volid = $drive->{file
};
5676 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5677 $sidhash->{$sid} = $sid if $sid;
5680 foreach my $sid (sort keys %$sidhash) {
5685 my $alloc_vmstate_volid = sub {
5686 my ($storecfg, $vmid, $conf, $snapname) = @_;
5688 # Note: we try to be smart when selecting a $target storage
5692 # search shared storage first
5693 foreach_writable_storage
($conf, sub {
5695 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5696 return if !$scfg->{shared
};
5698 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5702 # now search local storage
5703 foreach_writable_storage
($conf, sub {
5705 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5706 return if $scfg->{shared
};
5708 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5712 $target = 'local' if !$target;
5714 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5715 # we abort live save after $conf->{memory}, so we need at max twice that space
5716 my $size = $conf->{memory
}*2 + $driver_state_size;
5718 my $name = "vm-$vmid-state-$snapname";
5719 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5720 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5721 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5726 my $snapshot_prepare = sub {
5727 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5731 my $updatefn = sub {
5733 my $conf = load_config
($vmid);
5735 die "you can't take a snapshot if it's a template\n"
5736 if is_template
($conf);
5740 $conf->{lock} = 'snapshot';
5742 die "snapshot name '$snapname' already used\n"
5743 if defined($conf->{snapshots
}->{$snapname});
5745 my $storecfg = PVE
::Storage
::config
();
5746 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5748 $snap = $conf->{snapshots
}->{$snapname} = {};
5750 if ($save_vmstate && check_running
($vmid)) {
5751 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5754 &$snapshot_copy_config($conf, $snap);
5756 $snap->{snapstate
} = "prepare";
5757 $snap->{snaptime
} = time();
5758 $snap->{description
} = $comment if $comment;
5760 # always overwrite machine if we save vmstate. This makes sure we
5761 # can restore it later using correct machine type
5762 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5764 update_config_nolock
($vmid, $conf, 1);
5767 lock_config
($vmid, $updatefn);
5772 my $snapshot_commit = sub {
5773 my ($vmid, $snapname) = @_;
5775 my $updatefn = sub {
5777 my $conf = load_config
($vmid);
5779 die "missing snapshot lock\n"
5780 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5782 my $has_machine_config = defined($conf->{machine
});
5784 my $snap = $conf->{snapshots
}->{$snapname};
5786 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5788 die "wrong snapshot state\n"
5789 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5791 delete $snap->{snapstate
};
5792 delete $conf->{lock};
5794 my $newconf = &$snapshot_apply_config($conf, $snap);
5796 delete $newconf->{machine
} if !$has_machine_config;
5798 $newconf->{parent
} = $snapname;
5800 update_config_nolock
($vmid, $newconf, 1);
5803 lock_config
($vmid, $updatefn);
5806 sub snapshot_rollback
{
5807 my ($vmid, $snapname) = @_;
5811 my $storecfg = PVE
::Storage
::config
();
5813 my $conf = load_config
($vmid);
5815 my $get_snapshot_config = sub {
5817 die "you can't rollback if vm is a template\n" if is_template
($conf);
5819 my $res = $conf->{snapshots
}->{$snapname};
5821 die "snapshot '$snapname' does not exist\n" if !defined($res);
5826 my $snap = &$get_snapshot_config();
5828 foreach_drive
($snap, sub {
5829 my ($ds, $drive) = @_;
5831 return if drive_is_cdrom
($drive);
5833 my $volid = $drive->{file
};
5835 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5838 my $updatefn = sub {
5840 $conf = load_config
($vmid);
5842 $snap = &$get_snapshot_config();
5844 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5845 if $snap->{snapstate
};
5849 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5852 die "unable to rollback vm $vmid: vm is running\n"
5853 if check_running
($vmid);
5856 $conf->{lock} = 'rollback';
5858 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5859 delete $conf->{lock};
5865 my $has_machine_config = defined($conf->{machine
});
5867 # copy snapshot config to current config
5868 $conf = &$snapshot_apply_config($conf, $snap);
5869 $conf->{parent
} = $snapname;
5871 # Note: old code did not store 'machine', so we try to be smart
5872 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5873 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5874 # we remove the 'machine' configuration if not explicitly specified
5875 # in the original config.
5876 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5879 update_config_nolock
($vmid, $conf, 1);
5881 if (!$prepare && $snap->{vmstate
}) {
5882 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5883 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5887 lock_config
($vmid, $updatefn);
5889 foreach_drive
($snap, sub {
5890 my ($ds, $drive) = @_;
5892 return if drive_is_cdrom
($drive);
5894 my $volid = $drive->{file
};
5895 my $device = "drive-$ds";
5897 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5901 lock_config
($vmid, $updatefn);
5904 my $savevm_wait = sub {
5908 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5909 if (!$stat->{status
}) {
5910 die "savevm not active\n";
5911 } elsif ($stat->{status
} eq 'active') {
5914 } elsif ($stat->{status
} eq 'completed') {
5917 die "query-savevm returned status '$stat->{status}'\n";
5922 sub do_snapshots_with_qemu
{
5923 my ($storecfg, $volid) = @_;
5925 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5927 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5928 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5932 if ($volid =~ m/\.(qcow2|qed)$/){
5939 sub snapshot_create
{
5940 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5942 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5944 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5946 my $config = load_config
($vmid);
5948 my $running = check_running
($vmid);
5950 my $freezefs = $running && $config->{agent
};
5951 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5956 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5957 warn "guest-fsfreeze-freeze problems - $@" if $@;
5961 # create internal snapshots of all drives
5963 my $storecfg = PVE
::Storage
::config
();
5966 if ($snap->{vmstate
}) {
5967 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5968 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5969 &$savevm_wait($vmid);
5971 vm_mon_cmd
($vmid, "savevm-start");
5975 foreach_drive
($snap, sub {
5976 my ($ds, $drive) = @_;
5978 return if drive_is_cdrom
($drive);
5980 my $volid = $drive->{file
};
5981 my $device = "drive-$ds";
5983 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5984 $drivehash->{$ds} = 1;
5990 eval { vm_mon_cmd
($vmid, "savevm-end") };
5994 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5995 warn "guest-fsfreeze-thaw problems - $@" if $@;
5998 # savevm-end is async, we need to wait
6000 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6001 if (!$stat->{bytes
}) {
6004 print "savevm not yet finished\n";
6012 warn "snapshot create failed: starting cleanup\n";
6013 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6018 &$snapshot_commit($vmid, $snapname);
6021 # Note: $drivehash is only set when called from snapshot_create.
6022 sub snapshot_delete
{
6023 my ($vmid, $snapname, $force, $drivehash) = @_;
6030 my $unlink_parent = sub {
6031 my ($confref, $new_parent) = @_;
6033 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6035 $confref->{parent
} = $new_parent;
6037 delete $confref->{parent
};
6042 my $updatefn = sub {
6043 my ($remove_drive) = @_;
6045 my $conf = load_config
($vmid);
6049 die "you can't delete a snapshot if vm is a template\n"
6050 if is_template
($conf);
6053 $snap = $conf->{snapshots
}->{$snapname};
6055 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6057 # remove parent refs
6059 &$unlink_parent($conf, $snap->{parent
});
6060 foreach my $sn (keys %{$conf->{snapshots
}}) {
6061 next if $sn eq $snapname;
6062 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6066 if ($remove_drive) {
6067 if ($remove_drive eq 'vmstate') {
6068 delete $snap->{$remove_drive};
6070 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6071 my $volid = $drive->{file
};
6072 delete $snap->{$remove_drive};
6073 add_unused_volume
($conf, $volid);
6078 $snap->{snapstate
} = 'delete';
6080 delete $conf->{snapshots
}->{$snapname};
6081 delete $conf->{lock} if $drivehash;
6082 foreach my $volid (@$unused) {
6083 add_unused_volume
($conf, $volid);
6087 update_config_nolock
($vmid, $conf, 1);
6090 lock_config
($vmid, $updatefn);
6092 # now remove vmstate file
6094 my $storecfg = PVE
::Storage
::config
();
6096 if ($snap->{vmstate
}) {
6097 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6099 die $err if !$force;
6102 # save changes (remove vmstate from snapshot)
6103 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6106 # now remove all internal snapshots
6107 foreach_drive
($snap, sub {
6108 my ($ds, $drive) = @_;
6110 return if drive_is_cdrom
($drive);
6112 my $volid = $drive->{file
};
6113 my $device = "drive-$ds";
6115 if (!$drivehash || $drivehash->{$ds}) {
6116 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6118 die $err if !$force;
6123 # save changes (remove drive fron snapshot)
6124 lock_config
($vmid, $updatefn, $ds) if !$force;
6125 push @$unused, $volid;
6128 # now cleanup config
6130 lock_config
($vmid, $updatefn);
6134 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6137 foreach_drive
($conf, sub {
6138 my ($ds, $drive) = @_;
6140 return if drive_is_cdrom
($drive);
6141 my $volid = $drive->{file
};
6142 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6145 return $err ?
0 : 1;
6148 sub template_create
{
6149 my ($vmid, $conf, $disk) = @_;
6151 my $storecfg = PVE
::Storage
::config
();
6153 foreach_drive
($conf, sub {
6154 my ($ds, $drive) = @_;
6156 return if drive_is_cdrom
($drive);
6157 return if $disk && $ds ne $disk;
6159 my $volid = $drive->{file
};
6160 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6162 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6163 $drive->{file
} = $voliddst;
6164 $conf->{$ds} = print_drive
($vmid, $drive);
6165 update_config_nolock
($vmid, $conf, 1);
6172 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6175 sub qemu_img_convert
{
6176 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6178 my $storecfg = PVE
::Storage
::config
();
6179 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6180 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6182 if ($src_storeid && $dst_storeid) {
6184 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6186 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6187 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6189 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6190 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6192 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6193 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6196 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6197 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6198 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6202 if($line =~ m/\((\S+)\/100\
%\)/){
6204 my $transferred = int($size * $percent / 100);
6205 my $remaining = $size - $transferred;
6207 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6212 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6214 die "copy failed: $err" if $err;
6218 sub qemu_img_format
{
6219 my ($scfg, $volname) = @_;
6221 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6228 sub qemu_drive_mirror
{
6229 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6231 my $storecfg = PVE
::Storage
::config
();
6232 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6234 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6236 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6238 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6240 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6241 $opts->{format
} = $format if $format;
6243 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6246 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6248 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6249 my $stat = @$stats[0];
6250 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6251 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6253 my $busy = $stat->{busy
};
6254 my $ready = $stat->{ready
};
6256 if (my $total = $stat->{len
}) {
6257 my $transferred = $stat->{offset
} || 0;
6258 my $remaining = $total - $transferred;
6259 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6261 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6265 if ($stat->{ready
} eq 'true') {
6267 last if $vmiddst != $vmid;
6269 # try to switch the disk if source and destination are on the same guest
6270 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6272 die $@ if $@ !~ m/cannot be completed/;
6281 my $cancel_job = sub {
6282 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6284 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6285 my $stat = @$stats[0];
6292 eval { &$cancel_job(); };
6293 die "mirroring error: $err";
6296 if ($vmiddst != $vmid) {
6297 # if we clone a disk for a new target vm, we don't switch the disk
6298 &$cancel_job(); # so we call block-job-cancel
6303 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6304 $newvmid, $storage, $format, $full, $newvollist) = @_;
6309 print "create linked clone of drive $drivename ($drive->{file})\n";
6310 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6311 push @$newvollist, $newvolid;
6313 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6314 $storeid = $storage if $storage;
6316 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6318 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6319 $format = qemu_img_format
($scfg, $volname);
6322 # test if requested format is supported - else use default
6323 my $supported = grep { $_ eq $format } @$validFormats;
6324 $format = $defFormat if !$supported;
6326 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6328 print "create full clone of drive $drivename ($drive->{file})\n";
6329 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6330 push @$newvollist, $newvolid;
6332 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6334 if (!$running || $snapname) {
6335 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6337 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6341 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6344 $disk->{format
} = undef;
6345 $disk->{file
} = $newvolid;
6346 $disk->{size
} = $size;
6351 # this only works if VM is running
6352 sub get_current_qemu_machine
{
6355 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6356 my $res = vm_qmp_command
($vmid, $cmd);
6358 my ($current, $default);
6359 foreach my $e (@$res) {
6360 $default = $e->{name
} if $e->{'is-default'};
6361 $current = $e->{name
} if $e->{'is-current'};
6364 # fallback to the default machine if current is not supported by qemu
6365 return $current || $default || 'pc';
6368 sub qemu_machine_feature_enabled
{
6369 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6374 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6376 $current_major = $3;
6377 $current_minor = $4;
6379 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6381 $current_major = $1;
6382 $current_minor = $2;
6385 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6390 sub qemu_machine_pxe
{
6391 my ($vmid, $conf, $machine) = @_;
6393 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6395 foreach my $opt (keys %$conf) {
6396 next if $opt !~ m/^net(\d+)$/;
6397 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6399 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6400 return $machine.".pxe" if $romfile =~ m/pxe/;
6406 sub qemu_use_old_bios_files
{
6407 my ($machine_type) = @_;
6409 return if !$machine_type;
6411 my $use_old_bios_files = undef;
6413 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6415 $use_old_bios_files = 1;
6417 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6418 # load new efi bios files on migration. So this hack is required to allow
6419 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6420 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6421 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6424 return ($use_old_bios_files, $machine_type);
6431 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6432 my (undef, $id, $function) = @_;
6433 my $res = { id
=> $id, function
=> $function};
6434 push @{$devices->{$id}}, $res;
6440 sub vm_iothreads_list
{
6443 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6446 foreach my $iothread (@$res) {
6447 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6454 my ($conf, $drive) = @_;
6458 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6460 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6466 my $controller = int($drive->{index} / $maxdev);
6467 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6469 return ($maxdev, $controller, $controller_prefix);
6472 # bash completion helper
6474 sub complete_backup_archives
{
6475 my ($cmdname, $pname, $cvalue) = @_;
6477 my $cfg = PVE
::Storage
::config
();
6481 if ($cvalue =~ m/^([^:]+):/) {
6485 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6488 foreach my $id (keys %$data) {
6489 foreach my $item (@{$data->{$id}}) {
6490 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6491 push @$res, $item->{volid
} if defined($item->{volid
});
6498 my $complete_vmid_full = sub {
6501 my $idlist = vmstatus
();
6505 foreach my $id (keys %$idlist) {
6506 my $d = $idlist->{$id};
6507 if (defined($running)) {
6508 next if $d->{template
};
6509 next if $running && $d->{status
} ne 'running';
6510 next if !$running && $d->{status
} eq 'running';
6519 return &$complete_vmid_full();
6522 sub complete_vmid_stopped
{
6523 return &$complete_vmid_full(0);
6526 sub complete_vmid_running
{
6527 return &$complete_vmid_full(1);
6530 sub complete_storage
{
6532 my $cfg = PVE
::Storage
::config
();
6533 my $ids = $cfg->{ids
};
6536 foreach my $sid (keys %$ids) {
6537 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6538 next if !$ids->{$sid}->{content
}->{images
};