1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
36 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
38 # Note about locking: we use flock on the config file protect
39 # against concurent actions.
40 # Aditionaly, we have a 'lock' setting in the config file. This
41 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
42 # allowed when such lock is set. But you can ignore this kind of
43 # lock with the --skiplock flag.
45 cfs_register_file
('/qemu-server/',
49 PVE
::JSONSchema
::register_standard_option
('skiplock', {
50 description
=> "Ignore locks - only root is allowed to use this option.",
55 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
56 description
=> "Some command save/restore state from this location.",
62 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
63 description
=> "The name of the snapshot.",
64 type
=> 'string', format
=> 'pve-configid',
68 #no warnings 'redefine';
71 my ($controller, $vmid, $option, $value) = @_;
73 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
74 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
78 my $nodename = PVE
::INotify
::nodename
();
80 mkdir "/etc/pve/nodes/$nodename";
81 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
84 my $var_run_tmpdir = "/var/run/qemu-server";
85 mkdir $var_run_tmpdir;
87 my $lock_dir = "/var/lock/qemu-server";
90 my $pcisysfs = "/sys/bus/pci";
96 description
=> "Specifies whether a VM will be started during system bootup.",
102 description
=> "Automatic restart after crash (currently ignored).",
107 type
=> 'string', format
=> 'pve-hotplug-features',
108 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
109 default => 'network,disk,usb',
114 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
120 description
=> "Lock/unlock the VM.",
121 enum
=> [qw(migrate backup snapshot rollback)],
126 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
134 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
142 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
149 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
155 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
163 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
164 enum
=> PVE
::Tools
::kvmkeymaplist
(),
169 type
=> 'string', format
=> 'dns-name',
170 description
=> "Set a name for the VM. Only used on the configuration web interface.",
175 description
=> "scsi controller model",
176 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
182 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
187 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
188 description
=> <<EODESC,
189 Used to enable special optimization/features for specific
192 other => unspecified OS
193 wxp => Microsoft Windows XP
194 w2k => Microsoft Windows 2000
195 w2k3 => Microsoft Windows 2003
196 w2k8 => Microsoft Windows 2008
197 wvista => Microsoft Windows Vista
198 win7 => Microsoft Windows 7
199 win8 => Microsoft Windows 8/2012
200 l24 => Linux 2.4 Kernel
201 l26 => Linux 2.6/3.X Kernel
202 solaris => solaris/opensolaris/openindiania kernel
204 other|l24|l26|solaris ... no special behaviour
205 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
211 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
212 pattern
=> '[acdn]{1,4}',
217 type
=> 'string', format
=> 'pve-qm-bootdisk',
218 description
=> "Enable booting from specified disk.",
219 pattern
=> '(ide|sata|scsi|virtio)\d+',
224 description
=> "The number of CPUs. Please use option -sockets instead.",
231 description
=> "The number of CPU sockets.",
238 description
=> "The number of cores per socket.",
245 description
=> "Enable/disable Numa.",
251 description
=> "Number of hotplugged vcpus.",
258 description
=> "Enable/disable ACPI.",
264 description
=> "Enable/disable Qemu GuestAgent.",
270 description
=> "Enable/disable KVM hardware virtualization.",
276 description
=> "Enable/disable time drift fix.",
282 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
287 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
292 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
293 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
297 type
=> 'string', format
=> 'pve-qm-watchdog',
298 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
299 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
304 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
305 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
306 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
309 startup
=> get_standard_option
('pve-startup-order'),
313 description
=> "Enable/disable Template.",
319 description
=> <<EODESCR,
320 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
322 args: -no-reboot -no-hpet
329 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
334 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
338 migrate_downtime
=> {
341 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
347 type
=> 'string', format
=> 'pve-qm-drive',
348 typetext
=> 'volume',
349 description
=> "This is an alias for option -ide2",
353 description
=> "Emulated CPU type.",
355 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
358 parent
=> get_standard_option
('pve-snapshot-name', {
360 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
364 description
=> "Timestamp for snapshots.",
370 type
=> 'string', format
=> 'pve-volume-id',
371 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
374 description
=> "Specific the Qemu machine type.",
376 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
381 description
=> "Specify SMBIOS type 1 fields.",
382 type
=> 'string', format
=> 'pve-qm-smbios1',
383 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
390 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
395 # what about other qemu settings ?
397 #machine => 'string',
410 ##soundhw => 'string',
412 while (my ($k, $v) = each %$confdesc) {
413 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
416 my $MAX_IDE_DISKS = 4;
417 my $MAX_SCSI_DISKS = 14;
418 my $MAX_VIRTIO_DISKS = 16;
419 my $MAX_SATA_DISKS = 6;
420 my $MAX_USB_DEVICES = 5;
422 my $MAX_UNUSED_DISKS = 8;
423 my $MAX_HOSTPCI_DEVICES = 4;
424 my $MAX_SERIAL_PORTS = 4;
425 my $MAX_PARALLEL_PORTS = 3;
427 my $MAX_MEM = 4194304;
428 my $STATICMEM = 1024;
432 type
=> 'string', format
=> 'pve-qm-numanode',
433 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
434 description
=> "numa topology",
436 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
438 for (my $i = 0; $i < $MAX_NUMA; $i++) {
439 $confdesc->{"numa$i"} = $numadesc;
442 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
443 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
444 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
445 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
449 type
=> 'string', format
=> 'pve-qm-net',
450 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
451 description
=> <<EODESCR,
452 Specify network devices.
454 MODEL is one of: $nic_model_list_txt
456 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
457 automatically generated if not specified.
459 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
461 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
463 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
469 The DHCP server assign addresses to the guest starting from 10.0.2.15.
473 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
475 for (my $i = 0; $i < $MAX_NETS; $i++) {
476 $confdesc->{"net$i"} = $netdesc;
483 type
=> 'string', format
=> 'pve-qm-drive',
484 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,serial=serial][,model=model]',
485 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
487 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
491 type
=> 'string', format
=> 'pve-qm-drive',
492 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,queues=<nbqueues>] [,serial=serial]',
493 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
499 type
=> 'string', format
=> 'pve-qm-drive',
500 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,serial=serial]',
501 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
503 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
507 type
=> 'string', format
=> 'pve-qm-drive',
508 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,serial=serial]',
509 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
511 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
515 type
=> 'string', format
=> 'pve-qm-usb-device',
516 typetext
=> 'host=HOSTUSBDEVICE|spice',
517 description
=> <<EODESCR,
518 Configure an USB device (n is 0 to 4). This can be used to
519 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
521 'bus-port(.port)*' (decimal numbers) or
522 'vendor_id:product_id' (hexadeciaml numbers)
524 You can use the 'lsusb -t' command to list existing usb devices.
526 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
528 The value 'spice' can be used to add a usb redirection devices for spice.
532 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
536 type
=> 'string', format
=> 'pve-qm-hostpci',
537 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
538 description
=> <<EODESCR,
539 Map host pci devices. HOSTPCIDEVICE syntax is:
541 'bus:dev.func' (hexadecimal numbers)
543 You can us the 'lspci' command to list existing pci devices.
545 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
547 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
549 Experimental: user reported problems with this option.
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
557 pattern
=> '(/dev/.+|socket)',
558 description
=> <<EODESCR,
559 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
561 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
563 Experimental: user reported problems with this option.
570 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
571 description
=> <<EODESCR,
572 Map host parallel devices (n is 0 to 2).
574 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
576 Experimental: user reported problems with this option.
580 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
581 $confdesc->{"parallel$i"} = $paralleldesc;
584 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
585 $confdesc->{"serial$i"} = $serialdesc;
588 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
589 $confdesc->{"hostpci$i"} = $hostpcidesc;
592 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
593 $drivename_hash->{"ide$i"} = 1;
594 $confdesc->{"ide$i"} = $idedesc;
597 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
598 $drivename_hash->{"sata$i"} = 1;
599 $confdesc->{"sata$i"} = $satadesc;
602 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
603 $drivename_hash->{"scsi$i"} = 1;
604 $confdesc->{"scsi$i"} = $scsidesc ;
607 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
608 $drivename_hash->{"virtio$i"} = 1;
609 $confdesc->{"virtio$i"} = $virtiodesc;
612 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
613 $confdesc->{"usb$i"} = $usbdesc;
618 type
=> 'string', format
=> 'pve-volume-id',
619 description
=> "Reference to unused volumes.",
622 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
623 $confdesc->{"unused$i"} = $unuseddesc;
626 my $kvm_api_version = 0;
630 return $kvm_api_version if $kvm_api_version;
632 my $fh = IO
::File-
>new("</dev/kvm") ||
635 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
636 $kvm_api_version = $v;
641 return $kvm_api_version;
644 my $kvm_user_version;
646 sub kvm_user_version
{
648 return $kvm_user_version if $kvm_user_version;
650 $kvm_user_version = 'unknown';
652 my $tmp = `kvm -help 2>/dev/null`;
654 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
655 $kvm_user_version = $2;
658 return $kvm_user_version;
662 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
665 # order is important - used to autoselect boot disk
666 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
667 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
668 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
669 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
672 sub valid_drivename
{
675 return defined($drivename_hash->{$dev});
680 return defined($confdesc->{$key});
684 return $nic_model_list;
687 sub os_list_description
{
692 w2k
=> 'Windows 2000',
693 w2k3
=>, 'Windows 2003',
694 w2k8
=> 'Windows 2008',
695 wvista
=> 'Windows Vista',
697 win8
=> 'Windows 8/2012',
707 return $cdrom_path if $cdrom_path;
709 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
710 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
711 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
715 my ($storecfg, $vmid, $cdrom) = @_;
717 if ($cdrom eq 'cdrom') {
718 return get_cdrom_path
();
719 } elsif ($cdrom eq 'none') {
721 } elsif ($cdrom =~ m
|^/|) {
724 return PVE
::Storage
::path
($storecfg, $cdrom);
728 # try to convert old style file names to volume IDs
729 sub filename_to_volume_id
{
730 my ($vmid, $file, $media) = @_;
732 if (!($file eq 'none' || $file eq 'cdrom' ||
733 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
735 return undef if $file =~ m
|/|;
737 if ($media && $media eq 'cdrom') {
738 $file = "local:iso/$file";
740 $file = "local:$vmid/$file";
747 sub verify_media_type
{
748 my ($opt, $vtype, $media) = @_;
753 if ($media eq 'disk') {
755 } elsif ($media eq 'cdrom') {
758 die "internal error";
761 return if ($vtype eq $etype);
763 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
766 sub cleanup_drive_path
{
767 my ($opt, $storecfg, $drive) = @_;
769 # try to convert filesystem paths to volume IDs
771 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
772 ($drive->{file
} !~ m
|^/dev/.+|) &&
773 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
774 ($drive->{file
} !~ m/^\d+$/)) {
775 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
776 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
777 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
778 verify_media_type
($opt, $vtype, $drive->{media
});
779 $drive->{file
} = $volid;
782 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
785 sub create_conf_nolock
{
786 my ($vmid, $settings) = @_;
788 my $filename = config_file
($vmid);
790 die "configuration file '$filename' already exists\n" if -f
$filename;
792 my $defaults = load_defaults
();
794 $settings->{name
} = "vm$vmid" if !$settings->{name
};
795 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
798 foreach my $opt (keys %$settings) {
799 next if !$confdesc->{$opt};
801 my $value = $settings->{$opt};
804 $data .= "$opt: $value\n";
807 PVE
::Tools
::file_set_contents
($filename, $data);
810 sub parse_hotplug_features
{
815 return $res if $data eq '0';
817 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
819 foreach my $feature (PVE
::Tools
::split_list
($data)) {
820 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
823 warn "ignoring unknown hotplug feature '$feature'\n";
829 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
830 sub pve_verify_hotplug_features
{
831 my ($value, $noerr) = @_;
833 return $value if parse_hotplug_features
($value);
835 return undef if $noerr;
837 die "unable to parse hotplug option\n";
840 my $parse_size = sub {
843 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
844 my ($size, $unit) = ($1, $3);
847 $size = $size * 1024;
848 } elsif ($unit eq 'M') {
849 $size = $size * 1024 * 1024;
850 } elsif ($unit eq 'G') {
851 $size = $size * 1024 * 1024 * 1024;
857 my $format_size = sub {
862 my $kb = int($size/1024);
863 return $size if $kb*1024 != $size;
865 my $mb = int($kb/1024);
866 return "${kb}K" if $mb*1024 != $kb;
868 my $gb = int($mb/1024);
869 return "${mb}M" if $gb*1024 != $mb;
874 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
875 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
876 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
877 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
878 # [,serial=serial][,model=model]
881 my ($key, $data) = @_;
885 # $key may be undefined - used to verify JSON parameters
886 if (!defined($key)) {
887 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
889 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
890 $res->{interface
} = $1;
896 foreach my $p (split (/,/, $data)) {
897 next if $p =~ m/^\s*$/;
899 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues|serial|model)=(.+)$/) {
900 my ($k, $v) = ($1, $2);
902 $k = 'file' if $k eq 'volume';
904 return undef if defined $res->{$k};
906 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
907 return undef if !$v || $v !~ m/^\d+/;
909 $v = sprintf("%.3f", $v / (1024*1024));
913 if (!$res->{file
} && $p !~ m/=/) {
921 return undef if !$res->{file
};
923 return undef if $res->{cache
} &&
924 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
925 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
926 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
927 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
928 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
929 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
930 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
931 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
932 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
933 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
934 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
935 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
936 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
937 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
938 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
940 return undef if $res->{mbps_rd
} && $res->{mbps
};
941 return undef if $res->{mbps_wr
} && $res->{mbps
};
943 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
944 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
945 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
946 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
947 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{iops_rd
} && $res->{iops
};
951 return undef if $res->{iops_wr
} && $res->{iops
};
954 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
955 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
956 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
957 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
958 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
959 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
962 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
965 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
966 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
967 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
968 return undef if $res->{interface
} eq 'virtio';
971 # rerror does not work with scsi drives
972 if ($res->{rerror
}) {
973 return undef if $res->{interface
} eq 'scsi';
979 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
982 my ($vmid, $drive) = @_;
985 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
986 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
989 if ($drive->{size
}) {
990 $opts .= ",size=" . &$format_size($drive->{size
});
993 if (my $model = $drive->{model
}) {
994 $opts .= ",model=$model";
997 return "$drive->{file}$opts";
1001 my($fh, $noerr) = @_;
1004 my $SG_GET_VERSION_NUM = 0x2282;
1006 my $versionbuf = "\x00" x
8;
1007 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1009 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1012 my $version = unpack("I", $versionbuf);
1013 if ($version < 30000) {
1014 die "scsi generic interface too old\n" if !$noerr;
1018 my $buf = "\x00" x
36;
1019 my $sensebuf = "\x00" x
8;
1020 my $cmd = pack("C x3 C x1", 0x12, 36);
1022 # see /usr/include/scsi/sg.h
1023 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1025 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1026 length($sensebuf), 0, length($buf), $buf,
1027 $cmd, $sensebuf, 6000);
1029 $ret = ioctl($fh, $SG_IO, $packet);
1031 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1035 my @res = unpack($sg_io_hdr_t, $packet);
1036 if ($res[17] || $res[18]) {
1037 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1042 (my $byte0, my $byte1, $res->{vendor
},
1043 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1045 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1046 $res->{type
} = $byte0 & 31;
1054 my $fh = IO
::File-
>new("+<$path") || return undef;
1055 my $res = scsi_inquiry
($fh, 1);
1061 sub machine_type_is_q35
{
1064 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1067 sub print_tabletdevice_full
{
1070 my $q35 = machine_type_is_q35
($conf);
1072 # we use uhci for old VMs because tablet driver was buggy in older qemu
1073 my $usbbus = $q35 ?
"ehci" : "uhci";
1075 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1078 sub print_drivedevice_full
{
1079 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1084 if ($drive->{interface
} eq 'virtio') {
1085 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1086 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1087 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1088 } elsif ($drive->{interface
} eq 'scsi') {
1090 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1091 my $unit = $drive->{index} % $maxdev;
1092 my $devicetype = 'hd';
1094 if (drive_is_cdrom
($drive)) {
1097 if ($drive->{file
} =~ m
|^/|) {
1098 $path = $drive->{file
};
1100 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1103 if($path =~ m/^iscsi\:\/\
//){
1104 $devicetype = 'generic';
1106 if (my $info = path_is_scsi
($path)) {
1107 if ($info->{type
} == 0) {
1108 $devicetype = 'block';
1109 } elsif ($info->{type
} == 1) { # tape
1110 $devicetype = 'generic';
1116 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1117 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1122 } elsif ($drive->{interface
} eq 'ide'){
1124 my $controller = int($drive->{index} / $maxdev);
1125 my $unit = $drive->{index} % $maxdev;
1126 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1128 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1129 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1130 $device .= ",model=$model";
1132 } elsif ($drive->{interface
} eq 'sata'){
1133 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1134 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1135 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1136 } elsif ($drive->{interface
} eq 'usb') {
1138 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1140 die "unsupported interface type";
1143 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1148 sub get_initiator_name
{
1151 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1152 while (defined(my $line = <$fh>)) {
1153 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1162 sub print_drive_full
{
1163 my ($storecfg, $vmid, $drive) = @_;
1166 my $volid = $drive->{file
};
1169 if (drive_is_cdrom
($drive)) {
1170 $path = get_iso_path
($storecfg, $vmid, $volid);
1172 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1174 $path = PVE
::Storage
::path
($storecfg, $volid);
1175 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1176 $format = qemu_img_format
($scfg, $volname);
1183 foreach my $o (@qemu_drive_options) {
1184 next if $o eq 'bootindex';
1185 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1188 $opts .= ",format=$format" if $format && !$drive->{format
};
1190 foreach my $o (qw(bps bps_rd bps_wr)) {
1191 my $v = $drive->{"m$o"};
1192 $opts .= ",$o=" . int($v*1024*1024) if $v;
1195 my $cache_direct = 0;
1197 if (my $cache = $drive->{cache
}) {
1198 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1199 } elsif (!drive_is_cdrom
($drive)) {
1200 $opts .= ",cache=none";
1204 # aio native works only with O_DIRECT
1205 if (!$drive->{aio
}) {
1207 $opts .= ",aio=native";
1209 $opts .= ",aio=threads";
1213 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1214 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1216 my $pathinfo = $path ?
"file=$path," : '';
1218 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1221 sub print_netdevice_full
{
1222 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1224 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1226 my $device = $net->{model
};
1227 if ($net->{model
} eq 'virtio') {
1228 $device = 'virtio-net-pci';
1231 my $pciaddr = print_pci_addr
("$netid", $bridges);
1232 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1233 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1234 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1235 my $vectors = $net->{queues
} * 2 + 2;
1236 $tmpstr .= ",vectors=$vectors,mq=on";
1238 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1240 if ($use_old_bios_files) {
1242 if ($device eq 'virtio-net-pci') {
1243 $romfile = 'pxe-virtio.rom';
1244 } elsif ($device eq 'e1000') {
1245 $romfile = 'pxe-e1000.rom';
1246 } elsif ($device eq 'ne2k') {
1247 $romfile = 'pxe-ne2k_pci.rom';
1248 } elsif ($device eq 'pcnet') {
1249 $romfile = 'pxe-pcnet.rom';
1250 } elsif ($device eq 'rtl8139') {
1251 $romfile = 'pxe-rtl8139.rom';
1253 $tmpstr .= ",romfile=$romfile" if $romfile;
1259 sub print_netdev_full
{
1260 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1263 if ($netid =~ m/^net(\d+)$/) {
1267 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1269 my $ifname = "tap${vmid}i$i";
1271 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1272 die "interface name '$ifname' is too long (max 15 character)\n"
1273 if length($ifname) >= 16;
1275 my $vhostparam = '';
1276 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1278 my $vmname = $conf->{name
} || "vm$vmid";
1281 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1283 if ($net->{bridge
}) {
1284 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1286 $netdev = "type=user,id=$netid,hostname=$vmname";
1289 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1294 sub drive_is_cdrom
{
1297 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1306 foreach my $kvp (split(/,/, $data)) {
1308 if ($kvp =~ m/^memory=(\S+)$/) {
1309 $res->{memory
} = $1;
1310 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1311 $res->{policy
} = $1;
1312 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1313 $res->{cpus
}->{start
} = $1;
1314 $res->{cpus
}->{end
} = $3;
1315 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1316 $res->{hostnodes
}->{start
} = $1;
1317 $res->{hostnodes
}->{end
} = $3;
1329 return undef if !$value;
1332 my @list = split(/,/, $value);
1336 foreach my $kv (@list) {
1338 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1341 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1344 my $pcidevices = lspci
($2);
1345 $res->{pciid
} = $pcidevices->{$2};
1347 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1348 $res->{rombar
} = $1;
1349 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1350 $res->{'x-vga'} = $1;
1351 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1352 $res->{pcie
} = 1 if $1 == 1;
1354 warn "unknown hostpci setting '$kv'\n";
1358 return undef if !$found;
1363 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1369 foreach my $kvp (split(/,/, $data)) {
1371 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1373 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1374 $res->{model
} = $model;
1375 $res->{macaddr
} = $mac;
1376 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1377 $res->{bridge
} = $1;
1378 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1379 $res->{queues
} = $1;
1380 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1382 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1384 } elsif ($kvp =~ m/^firewall=([01])$/) {
1385 $res->{firewall
} = $1;
1386 } elsif ($kvp =~ m/^link_down=([01])$/) {
1387 $res->{link_down
} = $1;
1394 return undef if !$res->{model
};
1402 my $res = "$net->{model}";
1403 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1404 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1405 $res .= ",rate=$net->{rate}" if $net->{rate
};
1406 $res .= ",tag=$net->{tag}" if $net->{tag
};
1407 $res .= ",firewall=1" if $net->{firewall
};
1408 $res .= ",link_down=1" if $net->{link_down
};
1409 $res .= ",queues=$net->{queues}" if $net->{queues
};
1414 sub add_random_macs
{
1415 my ($settings) = @_;
1417 foreach my $opt (keys %$settings) {
1418 next if $opt !~ m/^net(\d+)$/;
1419 my $net = parse_net
($settings->{$opt});
1421 $settings->{$opt} = print_net
($net);
1425 sub add_unused_volume
{
1426 my ($config, $volid) = @_;
1429 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1430 my $test = "unused$ind";
1431 if (my $vid = $config->{$test}) {
1432 return if $vid eq $volid; # do not add duplicates
1438 die "To many unused volume - please delete them first.\n" if !$key;
1440 $config->{$key} = $volid;
1445 sub vm_is_volid_owner
{
1446 my ($storecfg, $vmid, $volid) = @_;
1448 if ($volid !~ m
|^/|) {
1450 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1451 if ($owner && ($owner == $vmid)) {
1459 sub split_flagged_list
{
1460 my $text = shift || '';
1461 $text =~ s/[,;]/ /g;
1463 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1466 sub join_flagged_list
{
1467 my ($how, $lst) = @_;
1468 join $how, map { $lst->{$_} . $_ } keys %$lst;
1471 sub vmconfig_delete_pending_option
{
1472 my ($conf, $key, $force) = @_;
1474 delete $conf->{pending
}->{$key};
1475 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1476 $pending_delete_hash->{$key} = $force ?
'!' : '';
1477 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1480 sub vmconfig_undelete_pending_option
{
1481 my ($conf, $key) = @_;
1483 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1484 delete $pending_delete_hash->{$key};
1486 if (%$pending_delete_hash) {
1487 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1489 delete $conf->{pending
}->{delete};
1493 sub vmconfig_register_unused_drive
{
1494 my ($storecfg, $vmid, $conf, $drive) = @_;
1496 if (!drive_is_cdrom
($drive)) {
1497 my $volid = $drive->{file
};
1498 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1499 add_unused_volume
($conf, $volid, $vmid);
1504 sub vmconfig_cleanup_pending
{
1507 # remove pending changes when nothing changed
1509 foreach my $opt (keys %{$conf->{pending
}}) {
1510 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1512 delete $conf->{pending
}->{$opt};
1516 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1517 my $pending_delete_hash = {};
1518 while (my ($opt, $force) = each %$current_delete_hash) {
1519 if (defined($conf->{$opt})) {
1520 $pending_delete_hash->{$opt} = $force;
1526 if (%$pending_delete_hash) {
1527 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1529 delete $conf->{pending
}->{delete};
1535 my $valid_smbios1_options = {
1536 manufacturer
=> '\S+',
1540 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1545 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1551 foreach my $kvp (split(/,/, $data)) {
1552 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1553 my ($k, $v) = split(/=/, $kvp);
1554 return undef if !defined($k) || !defined($v);
1555 return undef if !$valid_smbios1_options->{$k};
1556 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1567 foreach my $k (keys %$smbios1) {
1568 next if !defined($smbios1->{$k});
1569 next if !$valid_smbios1_options->{$k};
1570 $data .= ',' if $data;
1571 $data .= "$k=$smbios1->{$k}";
1576 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1577 sub verify_smbios1
{
1578 my ($value, $noerr) = @_;
1580 return $value if parse_smbios1
($value);
1582 return undef if $noerr;
1584 die "unable to parse smbios (type 1) options\n";
1587 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1588 sub verify_bootdisk
{
1589 my ($value, $noerr) = @_;
1591 return $value if valid_drivename
($value);
1593 return undef if $noerr;
1595 die "invalid boot disk '$value'\n";
1598 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1600 my ($value, $noerr) = @_;
1602 return $value if parse_numa
($value);
1604 return undef if $noerr;
1606 die "unable to parse numa options\n";
1609 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1611 my ($value, $noerr) = @_;
1613 return $value if parse_net
($value);
1615 return undef if $noerr;
1617 die "unable to parse network options\n";
1620 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1622 my ($value, $noerr) = @_;
1624 return $value if parse_drive
(undef, $value);
1626 return undef if $noerr;
1628 die "unable to parse drive options\n";
1631 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1632 sub verify_hostpci
{
1633 my ($value, $noerr) = @_;
1635 return $value if parse_hostpci
($value);
1637 return undef if $noerr;
1639 die "unable to parse pci id\n";
1642 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1643 sub verify_watchdog
{
1644 my ($value, $noerr) = @_;
1646 return $value if parse_watchdog
($value);
1648 return undef if $noerr;
1650 die "unable to parse watchdog options\n";
1653 sub parse_watchdog
{
1656 return undef if !$value;
1660 foreach my $p (split(/,/, $value)) {
1661 next if $p =~ m/^\s*$/;
1663 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1665 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1666 $res->{action
} = $2;
1675 sub parse_usb_device
{
1678 return undef if !$value;
1680 my @dl = split(/,/, $value);
1684 foreach my $v (@dl) {
1685 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1687 $res->{vendorid
} = $2;
1688 $res->{productid
} = $4;
1689 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1691 $res->{hostbus
} = $1;
1692 $res->{hostport
} = $2;
1693 } elsif ($v =~ m/^spice$/) {
1700 return undef if !$found;
1705 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1706 sub verify_usb_device
{
1707 my ($value, $noerr) = @_;
1709 return $value if parse_usb_device
($value);
1711 return undef if $noerr;
1713 die "unable to parse usb device\n";
1716 # add JSON properties for create and set function
1717 sub json_config_properties
{
1720 foreach my $opt (keys %$confdesc) {
1721 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1722 $prop->{$opt} = $confdesc->{$opt};
1729 my ($key, $value) = @_;
1731 die "unknown setting '$key'\n" if !$confdesc->{$key};
1733 my $type = $confdesc->{$key}->{type
};
1735 if (!defined($value)) {
1736 die "got undefined value\n";
1739 if ($value =~ m/[\n\r]/) {
1740 die "property contains a line feed\n";
1743 if ($type eq 'boolean') {
1744 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1745 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1746 die "type check ('boolean') failed - got '$value'\n";
1747 } elsif ($type eq 'integer') {
1748 return int($1) if $value =~ m/^(\d+)$/;
1749 die "type check ('integer') failed - got '$value'\n";
1750 } elsif ($type eq 'number') {
1751 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1752 die "type check ('number') failed - got '$value'\n";
1753 } elsif ($type eq 'string') {
1754 if (my $fmt = $confdesc->{$key}->{format
}) {
1755 if ($fmt eq 'pve-qm-drive') {
1756 # special case - we need to pass $key to parse_drive()
1757 my $drive = parse_drive
($key, $value);
1758 return $value if $drive;
1759 die "unable to parse drive options\n";
1761 PVE
::JSONSchema
::check_format
($fmt, $value);
1764 $value =~ s/^\"(.*)\"$/$1/;
1767 die "internal error"
1771 sub lock_config_full
{
1772 my ($vmid, $timeout, $code, @param) = @_;
1774 my $filename = config_file_lock
($vmid);
1776 my $res = lock_file
($filename, $timeout, $code, @param);
1783 sub lock_config_mode
{
1784 my ($vmid, $timeout, $shared, $code, @param) = @_;
1786 my $filename = config_file_lock
($vmid);
1788 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1796 my ($vmid, $code, @param) = @_;
1798 return lock_config_full
($vmid, 10, $code, @param);
1801 sub cfs_config_path
{
1802 my ($vmid, $node) = @_;
1804 $node = $nodename if !$node;
1805 return "nodes/$node/qemu-server/$vmid.conf";
1808 sub check_iommu_support
{
1809 #fixme : need to check IOMMU support
1810 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1818 my ($vmid, $node) = @_;
1820 my $cfspath = cfs_config_path
($vmid, $node);
1821 return "/etc/pve/$cfspath";
1824 sub config_file_lock
{
1827 return "$lock_dir/lock-$vmid.conf";
1833 my $conf = config_file
($vmid);
1834 utime undef, undef, $conf;
1838 my ($storecfg, $vmid, $keep_empty_config) = @_;
1840 my $conffile = config_file
($vmid);
1842 my $conf = load_config
($vmid);
1846 # only remove disks owned by this VM
1847 foreach_drive
($conf, sub {
1848 my ($ds, $drive) = @_;
1850 return if drive_is_cdrom
($drive);
1852 my $volid = $drive->{file
};
1854 return if !$volid || $volid =~ m
|^/|;
1856 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1857 return if !$path || !$owner || ($owner != $vmid);
1859 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1862 if ($keep_empty_config) {
1863 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1868 # also remove unused disk
1870 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1873 PVE
::Storage
::foreach_volid
($dl, sub {
1874 my ($volid, $sid, $volname, $d) = @_;
1875 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1885 my ($vmid, $node) = @_;
1887 my $cfspath = cfs_config_path
($vmid, $node);
1889 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1891 die "no such VM ('$vmid')\n" if !defined($conf);
1896 sub parse_vm_config
{
1897 my ($filename, $raw) = @_;
1899 return undef if !defined($raw);
1902 digest
=> Digest
::SHA
::sha1_hex
($raw),
1907 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1908 || die "got strange filename '$filename'";
1916 my @lines = split(/\n/, $raw);
1917 foreach my $line (@lines) {
1918 next if $line =~ m/^\s*$/;
1920 if ($line =~ m/^\[PENDING\]\s*$/i) {
1921 $section = 'pending';
1922 if (defined($descr)) {
1924 $conf->{description
} = $descr;
1927 $conf = $res->{$section} = {};
1930 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1932 if (defined($descr)) {
1934 $conf->{description
} = $descr;
1937 $conf = $res->{snapshots
}->{$section} = {};
1941 if ($line =~ m/^\#(.*)\s*$/) {
1942 $descr = '' if !defined($descr);
1943 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1947 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1948 $descr = '' if !defined($descr);
1949 $descr .= PVE
::Tools
::decode_text
($2);
1950 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1951 $conf->{snapstate
} = $1;
1952 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1955 $conf->{$key} = $value;
1956 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1958 if ($section eq 'pending') {
1959 $conf->{delete} = $value; # we parse this later
1961 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1963 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1966 eval { $value = check_type
($key, $value); };
1968 warn "vm $vmid - unable to parse value of '$key' - $@";
1970 my $fmt = $confdesc->{$key}->{format
};
1971 if ($fmt && $fmt eq 'pve-qm-drive') {
1972 my $v = parse_drive
($key, $value);
1973 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1974 $v->{file
} = $volid;
1975 $value = print_drive
($vmid, $v);
1977 warn "vm $vmid - unable to parse value of '$key'\n";
1982 if ($key eq 'cdrom') {
1983 $conf->{ide2
} = $value;
1985 $conf->{$key} = $value;
1991 if (defined($descr)) {
1993 $conf->{description
} = $descr;
1995 delete $res->{snapstate
}; # just to be sure
2000 sub write_vm_config
{
2001 my ($filename, $conf) = @_;
2003 delete $conf->{snapstate
}; # just to be sure
2005 if ($conf->{cdrom
}) {
2006 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2007 $conf->{ide2
} = $conf->{cdrom
};
2008 delete $conf->{cdrom
};
2011 # we do not use 'smp' any longer
2012 if ($conf->{sockets
}) {
2013 delete $conf->{smp
};
2014 } elsif ($conf->{smp
}) {
2015 $conf->{sockets
} = $conf->{smp
};
2016 delete $conf->{cores
};
2017 delete $conf->{smp
};
2020 my $used_volids = {};
2022 my $cleanup_config = sub {
2023 my ($cref, $pending, $snapname) = @_;
2025 foreach my $key (keys %$cref) {
2026 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2027 $key eq 'snapstate' || $key eq 'pending';
2028 my $value = $cref->{$key};
2029 if ($key eq 'delete') {
2030 die "propertry 'delete' is only allowed in [PENDING]\n"
2032 # fixme: check syntax?
2035 eval { $value = check_type
($key, $value); };
2036 die "unable to parse value of '$key' - $@" if $@;
2038 $cref->{$key} = $value;
2040 if (!$snapname && valid_drivename
($key)) {
2041 my $drive = parse_drive
($key, $value);
2042 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2047 &$cleanup_config($conf);
2049 &$cleanup_config($conf->{pending
}, 1);
2051 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2052 die "internal error" if $snapname eq 'pending';
2053 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2056 # remove 'unusedX' settings if we re-add a volume
2057 foreach my $key (keys %$conf) {
2058 my $value = $conf->{$key};
2059 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2060 delete $conf->{$key};
2064 my $generate_raw_config = sub {
2065 my ($conf, $pending) = @_;
2069 # add description as comment to top of file
2070 if (defined(my $descr = $conf->{description
})) {
2072 foreach my $cl (split(/\n/, $descr)) {
2073 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2076 $raw .= "#\n" if $pending;
2080 foreach my $key (sort keys %$conf) {
2081 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2082 $raw .= "$key: $conf->{$key}\n";
2087 my $raw = &$generate_raw_config($conf);
2089 if (scalar(keys %{$conf->{pending
}})){
2090 $raw .= "\n[PENDING]\n";
2091 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2094 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2095 $raw .= "\n[$snapname]\n";
2096 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2102 sub update_config_nolock
{
2103 my ($vmid, $conf, $skiplock) = @_;
2105 check_lock
($conf) if !$skiplock;
2107 my $cfspath = cfs_config_path
($vmid);
2109 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2113 my ($vmid, $conf, $skiplock) = @_;
2115 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2122 # we use static defaults from our JSON schema configuration
2123 foreach my $key (keys %$confdesc) {
2124 if (defined(my $default = $confdesc->{$key}->{default})) {
2125 $res->{$key} = $default;
2129 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2130 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2136 my $vmlist = PVE
::Cluster
::get_vmlist
();
2138 return $res if !$vmlist || !$vmlist->{ids
};
2139 my $ids = $vmlist->{ids
};
2141 foreach my $vmid (keys %$ids) {
2142 my $d = $ids->{$vmid};
2143 next if !$d->{node
} || $d->{node
} ne $nodename;
2144 next if !$d->{type
} || $d->{type
} ne 'qemu';
2145 $res->{$vmid}->{exists} = 1;
2150 # test if VM uses local resources (to prevent migration)
2151 sub check_local_resources
{
2152 my ($conf, $noerr) = @_;
2156 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2157 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2159 foreach my $k (keys %$conf) {
2160 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2161 # sockets are safe: they will recreated be on the target side post-migrate
2162 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2163 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2166 die "VM uses local resources\n" if $loc_res && !$noerr;
2171 # check if used storages are available on all nodes (use by migrate)
2172 sub check_storage_availability
{
2173 my ($storecfg, $conf, $node) = @_;
2175 foreach_drive
($conf, sub {
2176 my ($ds, $drive) = @_;
2178 my $volid = $drive->{file
};
2181 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2184 # check if storage is available on both nodes
2185 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2186 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2190 # list nodes where all VM images are available (used by has_feature API)
2192 my ($conf, $storecfg) = @_;
2194 my $nodelist = PVE
::Cluster
::get_nodelist
();
2195 my $nodehash = { map { $_ => 1 } @$nodelist };
2196 my $nodename = PVE
::INotify
::nodename
();
2198 foreach_drive
($conf, sub {
2199 my ($ds, $drive) = @_;
2201 my $volid = $drive->{file
};
2204 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2206 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2207 if ($scfg->{disable
}) {
2209 } elsif (my $avail = $scfg->{nodes
}) {
2210 foreach my $node (keys %$nodehash) {
2211 delete $nodehash->{$node} if !$avail->{$node};
2213 } elsif (!$scfg->{shared
}) {
2214 foreach my $node (keys %$nodehash) {
2215 delete $nodehash->{$node} if $node ne $nodename
2227 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2231 my ($pidfile, $pid) = @_;
2233 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2237 return undef if !$line;
2238 my @param = split(/\0/, $line);
2240 my $cmd = $param[0];
2241 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2243 for (my $i = 0; $i < scalar (@param); $i++) {
2246 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2247 my $p = $param[$i+1];
2248 return 1 if $p && ($p eq $pidfile);
2257 my ($vmid, $nocheck, $node) = @_;
2259 my $filename = config_file
($vmid, $node);
2261 die "unable to find configuration file for VM $vmid - no such machine\n"
2262 if !$nocheck && ! -f
$filename;
2264 my $pidfile = pidfile_name
($vmid);
2266 if (my $fd = IO
::File-
>new("<$pidfile")) {
2271 my $mtime = $st->mtime;
2272 if ($mtime > time()) {
2273 warn "file '$filename' modified in future\n";
2276 if ($line =~ m/^(\d+)$/) {
2278 if (check_cmdline
($pidfile, $pid)) {
2279 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2291 my $vzlist = config_list
();
2293 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2295 while (defined(my $de = $fd->read)) {
2296 next if $de !~ m/^(\d+)\.pid$/;
2298 next if !defined($vzlist->{$vmid});
2299 if (my $pid = check_running
($vmid)) {
2300 $vzlist->{$vmid}->{pid
} = $pid;
2308 my ($storecfg, $conf) = @_;
2310 my $bootdisk = $conf->{bootdisk
};
2311 return undef if !$bootdisk;
2312 return undef if !valid_drivename
($bootdisk);
2314 return undef if !$conf->{$bootdisk};
2316 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2317 return undef if !defined($drive);
2319 return undef if drive_is_cdrom
($drive);
2321 my $volid = $drive->{file
};
2322 return undef if !$volid;
2324 return $drive->{size
};
2327 my $last_proc_pid_stat;
2329 # get VM status information
2330 # This must be fast and should not block ($full == false)
2331 # We only query KVM using QMP if $full == true (this can be slow)
2333 my ($opt_vmid, $full) = @_;
2337 my $storecfg = PVE
::Storage
::config
();
2339 my $list = vzlist
();
2340 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2342 my $cpucount = $cpuinfo->{cpus
} || 1;
2344 foreach my $vmid (keys %$list) {
2345 next if $opt_vmid && ($vmid ne $opt_vmid);
2347 my $cfspath = cfs_config_path
($vmid);
2348 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2351 $d->{pid
} = $list->{$vmid}->{pid
};
2353 # fixme: better status?
2354 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2356 my $size = disksize
($storecfg, $conf);
2357 if (defined($size)) {
2358 $d->{disk
} = 0; # no info available
2359 $d->{maxdisk
} = $size;
2365 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2366 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2367 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2369 $d->{name
} = $conf->{name
} || "VM $vmid";
2370 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2372 if ($conf->{balloon
}) {
2373 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2374 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2385 $d->{diskwrite
} = 0;
2387 $d->{template
} = is_template
($conf);
2392 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2393 foreach my $dev (keys %$netdev) {
2394 next if $dev !~ m/^tap([1-9]\d*)i/;
2396 my $d = $res->{$vmid};
2399 $d->{netout
} += $netdev->{$dev}->{receive
};
2400 $d->{netin
} += $netdev->{$dev}->{transmit
};
2403 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2404 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2409 my $ctime = gettimeofday
;
2411 foreach my $vmid (keys %$list) {
2413 my $d = $res->{$vmid};
2414 my $pid = $d->{pid
};
2417 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2418 next if !$pstat; # not running
2420 my $used = $pstat->{utime} + $pstat->{stime
};
2422 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2424 if ($pstat->{vsize
}) {
2425 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2428 my $old = $last_proc_pid_stat->{$pid};
2430 $last_proc_pid_stat->{$pid} = {
2438 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2440 if ($dtime > 1000) {
2441 my $dutime = $used - $old->{used
};
2443 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2444 $last_proc_pid_stat->{$pid} = {
2450 $d->{cpu
} = $old->{cpu
};
2454 return $res if !$full;
2456 my $qmpclient = PVE
::QMPClient-
>new();
2458 my $ballooncb = sub {
2459 my ($vmid, $resp) = @_;
2461 my $info = $resp->{'return'};
2462 return if !$info->{max_mem
};
2464 my $d = $res->{$vmid};
2466 # use memory assigned to VM
2467 $d->{maxmem
} = $info->{max_mem
};
2468 $d->{balloon
} = $info->{actual
};
2470 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2471 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2472 $d->{freemem
} = $info->{free_mem
};
2475 $d->{ballooninfo
} = $info;
2478 my $blockstatscb = sub {
2479 my ($vmid, $resp) = @_;
2480 my $data = $resp->{'return'} || [];
2481 my $totalrdbytes = 0;
2482 my $totalwrbytes = 0;
2484 for my $blockstat (@$data) {
2485 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2486 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2488 $blockstat->{device
} =~ s/drive-//;
2489 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2491 $res->{$vmid}->{diskread
} = $totalrdbytes;
2492 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2495 my $statuscb = sub {
2496 my ($vmid, $resp) = @_;
2498 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2499 # this fails if ballon driver is not loaded, so this must be
2500 # the last commnand (following command are aborted if this fails).
2501 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2503 my $status = 'unknown';
2504 if (!defined($status = $resp->{'return'}->{status
})) {
2505 warn "unable to get VM status\n";
2509 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2512 foreach my $vmid (keys %$list) {
2513 next if $opt_vmid && ($vmid ne $opt_vmid);
2514 next if !$res->{$vmid}->{pid
}; # not running
2515 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2518 $qmpclient->queue_execute(undef, 1);
2520 foreach my $vmid (keys %$list) {
2521 next if $opt_vmid && ($vmid ne $opt_vmid);
2522 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2529 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2532 my $current_size = 1024;
2533 my $dimm_size = 512;
2534 return if $current_size == $memory;
2536 for (my $j = 0; $j < 8; $j++) {
2537 for (my $i = 0; $i < 32; $i++) {
2538 my $name = "dimm${dimm_id}";
2540 my $numanode = $i % $sockets;
2541 $current_size += $dimm_size;
2542 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2543 return $current_size if $current_size >= $memory;
2549 sub foreach_reverse_dimm
{
2550 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2553 my $current_size = 4177920;
2554 my $dimm_size = 65536;
2555 return if $current_size == $memory;
2557 for (my $j = 0; $j < 8; $j++) {
2558 for (my $i = 0; $i < 32; $i++) {
2559 my $name = "dimm${dimm_id}";
2561 my $numanode = $i % $sockets;
2562 $current_size -= $dimm_size;
2563 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2564 return $current_size if $current_size <= $memory;
2571 my ($conf, $func) = @_;
2573 foreach my $ds (keys %$conf) {
2574 next if !valid_drivename
($ds);
2576 my $drive = parse_drive
($ds, $conf->{$ds});
2579 &$func($ds, $drive);
2584 my ($conf, $func) = @_;
2588 my $test_volid = sub {
2589 my ($volid, $is_cdrom) = @_;
2593 $volhash->{$volid} = $is_cdrom || 0;
2596 foreach_drive
($conf, sub {
2597 my ($ds, $drive) = @_;
2598 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2601 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2602 my $snap = $conf->{snapshots
}->{$snapname};
2603 &$test_volid($snap->{vmstate
}, 0);
2604 foreach_drive
($snap, sub {
2605 my ($ds, $drive) = @_;
2606 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2610 foreach my $volid (keys %$volhash) {
2611 &$func($volid, $volhash->{$volid});
2615 sub vga_conf_has_spice
{
2618 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2623 sub config_to_command
{
2624 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2627 my $globalFlags = [];
2628 my $machineFlags = [];
2634 my $kvmver = kvm_user_version
();
2635 my $vernum = 0; # unknown
2636 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2637 $vernum = $1*1000000+$2*1000;
2638 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2639 $vernum = $1*1000000+$2*1000+$3;
2642 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2644 my $have_ovz = -f
'/proc/vz/vestat';
2646 my $q35 = machine_type_is_q35
($conf);
2647 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2648 my $machine_type = $forcemachine || $conf->{machine
};
2649 my $use_old_bios_files = undef;
2650 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2652 my $cpuunits = defined($conf->{cpuunits
}) ?
2653 $conf->{cpuunits
} : $defaults->{cpuunits
};
2655 push @$cmd, '/usr/bin/systemd-run';
2656 push @$cmd, '--scope';
2657 push @$cmd, '--slice', "qemu";
2658 push @$cmd, '--unit', $vmid;
2659 # set KillMode=none, so that systemd don't kill those scopes
2660 # at shutdown (pve-manager service should stop the VMs instead)
2661 push @$cmd, '-p', "KillMode=none";
2662 push @$cmd, '-p', "CPUShares=$cpuunits";
2663 if ($conf->{cpulimit
}) {
2664 my $cpulimit = int($conf->{cpulimit
} * 100);
2665 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2668 push @$cmd, '/usr/bin/kvm';
2670 push @$cmd, '-id', $vmid;
2674 my $qmpsocket = qmp_socket
($vmid);
2675 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2676 push @$cmd, '-mon', "chardev=qmp,mode=control";
2678 my $socket = vnc_socket
($vmid);
2679 push @$cmd, '-vnc', "unix:$socket,x509,password";
2681 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2683 push @$cmd, '-daemonize';
2685 if ($conf->{smbios1
}) {
2686 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2690 # the q35 chipset support native usb2, so we enable usb controller
2691 # by default for this machine type
2692 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2694 $pciaddr = print_pci_addr
("piix3", $bridges);
2695 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2698 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2699 next if !$conf->{"usb$i"};
2702 # include usb device config
2703 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2706 my $vga = $conf->{vga
};
2708 my $qxlnum = vga_conf_has_spice
($vga);
2709 $vga = 'qxl' if $qxlnum;
2712 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2713 $conf->{ostype
} eq 'win7' ||
2714 $conf->{ostype
} eq 'w2k8')) {
2721 # enable absolute mouse coordinates (needed by vnc)
2723 if (defined($conf->{tablet
})) {
2724 $tablet = $conf->{tablet
};
2726 $tablet = $defaults->{tablet
};
2727 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2728 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2731 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2734 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2735 my $d = parse_hostpci
($conf->{"hostpci$i"});
2738 my $pcie = $d->{pcie
};
2740 die "q35 machine model is not enabled" if !$q35;
2741 $pciaddr = print_pcie_addr
("hostpci$i");
2743 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2746 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2747 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2748 if ($xvga && $xvga ne '') {
2749 push @$cpuFlags, 'kvm=off';
2752 my $pcidevices = $d->{pciid
};
2753 my $multifunction = 1 if @$pcidevices > 1;
2756 foreach my $pcidevice (@$pcidevices) {
2758 my $id = "hostpci$i";
2759 $id .= ".$j" if $multifunction;
2760 my $addr = $pciaddr;
2761 $addr .= ".$j" if $multifunction;
2762 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2765 $devicestr .= "$rombar$xvga";
2766 $devicestr .= ",multifunction=on" if $multifunction;
2769 push @$devices, '-device', $devicestr;
2775 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2776 my $d = parse_usb_device
($conf->{"usb$i"});
2778 if ($d->{vendorid
} && $d->{productid
}) {
2779 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2780 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2781 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2782 } elsif ($d->{spice
}) {
2783 # usb redir support for spice
2784 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2785 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2790 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2791 if (my $path = $conf->{"serial$i"}) {
2792 if ($path eq 'socket') {
2793 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2794 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2795 push @$devices, '-device', "isa-serial,chardev=serial$i";
2797 die "no such serial device\n" if ! -c
$path;
2798 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2799 push @$devices, '-device', "isa-serial,chardev=serial$i";
2805 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2806 if (my $path = $conf->{"parallel$i"}) {
2807 die "no such parallel device\n" if ! -c
$path;
2808 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2809 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2810 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2814 my $vmname = $conf->{name
} || "vm$vmid";
2816 push @$cmd, '-name', $vmname;
2819 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2820 $sockets = $conf->{sockets
} if $conf->{sockets
};
2822 my $cores = $conf->{cores
} || 1;
2824 my $maxcpus = $sockets * $cores;
2826 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2828 my $allowed_vcpus = $cpuinfo->{cpus
};
2830 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2831 if ($allowed_vcpus < $maxcpus);
2833 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2835 push @$cmd, '-nodefaults';
2837 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2839 my $bootindex_hash = {};
2841 foreach my $o (split(//, $bootorder)) {
2842 $bootindex_hash->{$o} = $i*100;
2846 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2848 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2850 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2852 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2855 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2857 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2858 my $useLocaltime = $conf->{localtime};
2860 if (my $ost = $conf->{ostype
}) {
2861 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2863 if ($ost =~ m/^w/) { # windows
2864 $useLocaltime = 1 if !defined($conf->{localtime});
2866 # use time drift fix when acpi is enabled
2867 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2868 $tdf = 1 if !defined($conf->{tdf
});
2872 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2874 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2875 push @$cmd, '-no-hpet';
2876 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2877 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2878 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2879 push @$cpuFlags , 'hv_time' if !$nokvm;
2882 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2886 if ($ost eq 'win7' || $ost eq 'win8') {
2887 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2891 push @$rtcFlags, 'driftfix=slew' if $tdf;
2894 push @$machineFlags, 'accel=tcg';
2896 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2899 if ($machine_type) {
2900 push @$machineFlags, "type=${machine_type}";
2903 if ($conf->{startdate
}) {
2904 push @$rtcFlags, "base=$conf->{startdate}";
2905 } elsif ($useLocaltime) {
2906 push @$rtcFlags, 'base=localtime';
2909 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2910 $cpu = $conf->{cpu
} if $conf->{cpu
};
2912 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2914 push @$cpuFlags , '-x2apic'
2915 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2917 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2919 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2921 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2923 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2924 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2927 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2929 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2931 push @$cmd, '-cpu', $cpu;
2933 my $memory = $conf->{memory
} || $defaults->{memory
};
2934 my $static_memory = 0;
2935 my $dimm_memory = 0;
2937 if ($hotplug_features->{memory
}) {
2938 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2939 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2940 $static_memory = $STATICMEM;
2941 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2942 $dimm_memory = $memory - $static_memory;
2943 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2947 $static_memory = $memory;
2948 push @$cmd, '-m', $static_memory;
2951 if ($conf->{numa
}) {
2953 my $numa_totalmemory = undef;
2954 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2955 next if !$conf->{"numa$i"};
2956 my $numa = parse_numa
($conf->{"numa$i"});
2959 die "missing numa node$i memory value\n" if !$numa->{memory
};
2960 my $numa_memory = $numa->{memory
};
2961 $numa_totalmemory += $numa_memory;
2962 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2965 my $cpus_start = $numa->{cpus
}->{start
};
2966 die "missing numa node$i cpus\n" if !defined($cpus_start);
2967 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2968 my $cpus = $cpus_start;
2969 if (defined($cpus_end)) {
2970 $cpus .= "-$cpus_end";
2971 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2975 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2976 if (defined($hostnodes_start)) {
2977 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2978 my $hostnodes = $hostnodes_start;
2979 if (defined($hostnodes_end)) {
2980 $hostnodes .= "-$hostnodes_end";
2981 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2984 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2985 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2986 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2990 my $policy = $numa->{policy
};
2991 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2992 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2995 push @$cmd, '-object', $numa_object;
2996 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2999 die "total memory for NUMA nodes must be equal to vm static memory\n"
3000 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3002 #if no custom tology, we split memory and cores across numa nodes
3003 if(!$numa_totalmemory) {
3005 my $numa_memory = ($static_memory / $sockets) . "M";
3007 for (my $i = 0; $i < $sockets; $i++) {
3009 my $cpustart = ($cores * $i);
3010 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3011 my $cpus = $cpustart;
3012 $cpus .= "-$cpuend" if $cpuend;
3014 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3015 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3020 if ($hotplug_features->{memory
}) {
3021 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3022 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3023 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3024 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3026 #if dimm_memory is not aligned to dimm map
3027 if($current_size > $memory) {
3028 $conf->{memory
} = $current_size;
3029 update_config_nolock
($vmid, $conf, 1);
3034 push @$cmd, '-S' if $conf->{freeze
};
3036 # set keyboard layout
3037 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3038 push @$cmd, '-k', $kb if $kb;
3041 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3042 #push @$cmd, '-soundhw', 'es1370';
3043 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3045 if($conf->{agent
}) {
3046 my $qgasocket = qmp_socket
($vmid, 1);
3047 my $pciaddr = print_pci_addr
("qga0", $bridges);
3048 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3049 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3050 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3057 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3058 for(my $i = 1; $i < $qxlnum; $i++){
3059 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3060 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3063 # assume other OS works like Linux
3064 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3065 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3069 my $pciaddr = print_pci_addr
("spice", $bridges);
3071 my $nodename = PVE
::INotify
::nodename
();
3072 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3073 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3075 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3077 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3078 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3079 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3082 # enable balloon by default, unless explicitly disabled
3083 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3084 $pciaddr = print_pci_addr
("balloon0", $bridges);
3085 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3088 if ($conf->{watchdog
}) {
3089 my $wdopts = parse_watchdog
($conf->{watchdog
});
3090 $pciaddr = print_pci_addr
("watchdog", $bridges);
3091 my $watchdog = $wdopts->{model
} || 'i6300esb';
3092 push @$devices, '-device', "$watchdog$pciaddr";
3093 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3097 my $scsicontroller = {};
3098 my $ahcicontroller = {};
3099 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3101 # Add iscsi initiator name if available
3102 if (my $initiator = get_initiator_name
()) {
3103 push @$devices, '-iscsi', "initiator-name=$initiator";
3106 foreach_drive
($conf, sub {
3107 my ($ds, $drive) = @_;
3109 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3110 push @$vollist, $drive->{file
};
3113 $use_virtio = 1 if $ds =~ m/^virtio/;
3115 if (drive_is_cdrom
($drive)) {
3116 if ($bootindex_hash->{d
}) {
3117 $drive->{bootindex
} = $bootindex_hash->{d
};
3118 $bootindex_hash->{d
} += 1;
3121 if ($bootindex_hash->{c
}) {
3122 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3123 $bootindex_hash->{c
} += 1;
3127 if($drive->{interface
} eq 'virtio'){
3128 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3131 if ($drive->{interface
} eq 'scsi') {
3133 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3135 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3136 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3139 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3140 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3141 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3145 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3146 $queues = ",num_queues=$drive->{queues}";
3149 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3150 $scsicontroller->{$controller}=1;
3153 if ($drive->{interface
} eq 'sata') {
3154 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3155 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3156 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3157 $ahcicontroller->{$controller}=1;
3160 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3161 push @$devices, '-drive',$drive_cmd;
3162 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3165 for (my $i = 0; $i < $MAX_NETS; $i++) {
3166 next if !$conf->{"net$i"};
3167 my $d = parse_net
($conf->{"net$i"});
3170 $use_virtio = 1 if $d->{model
} eq 'virtio';
3172 if ($bootindex_hash->{n
}) {
3173 $d->{bootindex
} = $bootindex_hash->{n
};
3174 $bootindex_hash->{n
} += 1;
3177 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3178 push @$devices, '-netdev', $netdevfull;
3180 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3181 push @$devices, '-device', $netdevicefull;
3186 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3191 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3193 while (my ($k, $v) = each %$bridges) {
3194 $pciaddr = print_pci_addr
("pci.$k");
3195 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3200 if ($conf->{args
}) {
3201 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3205 push @$cmd, @$devices;
3206 push @$cmd, '-rtc', join(',', @$rtcFlags)
3207 if scalar(@$rtcFlags);
3208 push @$cmd, '-machine', join(',', @$machineFlags)
3209 if scalar(@$machineFlags);
3210 push @$cmd, '-global', join(',', @$globalFlags)
3211 if scalar(@$globalFlags);
3213 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3218 return "${var_run_tmpdir}/$vmid.vnc";
3224 my $res = vm_mon_cmd
($vmid, 'query-spice');
3226 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3230 my ($vmid, $qga) = @_;
3231 my $sockettype = $qga ?
'qga' : 'qmp';
3232 return "${var_run_tmpdir}/$vmid.$sockettype";
3237 return "${var_run_tmpdir}/$vmid.pid";
3240 sub vm_devices_list
{
3243 my $res = vm_mon_cmd
($vmid, 'query-pci');
3245 foreach my $pcibus (@$res) {
3246 foreach my $device (@{$pcibus->{devices
}}) {
3247 next if !$device->{'qdev_id'};
3248 if ($device->{'pci_bridge'}) {
3249 $devices->{$device->{'qdev_id'}} = 1;
3250 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3251 next if !$bridge_device->{'qdev_id'};
3252 $devices->{$bridge_device->{'qdev_id'}} = 1;
3253 $devices->{$device->{'qdev_id'}}++;
3256 $devices->{$device->{'qdev_id'}} = 1;
3261 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3262 foreach my $block (@$resblock) {
3263 if($block->{device
} =~ m/^drive-(\S+)/){
3268 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3269 foreach my $mice (@$resmice) {
3270 if ($mice->{name
} eq 'QEMU HID Tablet') {
3271 $devices->{tablet
} = 1;
3280 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3282 my $q35 = machine_type_is_q35
($conf);
3284 my $devices_list = vm_devices_list
($vmid);
3285 return 1 if defined($devices_list->{$deviceid});
3287 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3289 if ($deviceid eq 'tablet') {
3291 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3293 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3295 qemu_iothread_add
($vmid, $deviceid, $device);
3297 qemu_driveadd
($storecfg, $vmid, $device);
3298 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3300 qemu_deviceadd
($vmid, $devicefull);
3301 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3303 eval { qemu_drivedel
($vmid, $deviceid); };
3308 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3311 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3312 my $pciaddr = print_pci_addr
($deviceid);
3313 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3315 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3317 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3318 qemu_iothread_add
($vmid, $deviceid, $device);
3319 $devicefull .= ",iothread=iothread-$deviceid";
3322 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3323 $devicefull .= ",num_queues=$device->{queues}";
3326 qemu_deviceadd
($vmid, $devicefull);
3327 qemu_deviceaddverify
($vmid, $deviceid);
3329 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3331 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3332 qemu_driveadd
($storecfg, $vmid, $device);
3334 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3335 eval { qemu_deviceadd
($vmid, $devicefull); };
3337 eval { qemu_drivedel
($vmid, $deviceid); };
3342 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3344 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3346 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3347 my $use_old_bios_files = undef;
3348 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3350 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3351 qemu_deviceadd
($vmid, $netdevicefull);
3352 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3354 eval { qemu_netdevdel
($vmid, $deviceid); };
3359 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3362 my $pciaddr = print_pci_addr
($deviceid);
3363 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3365 qemu_deviceadd
($vmid, $devicefull);
3366 qemu_deviceaddverify
($vmid, $deviceid);
3369 die "can't hotplug device '$deviceid'\n";
3375 # fixme: this should raise exceptions on error!
3376 sub vm_deviceunplug
{
3377 my ($vmid, $conf, $deviceid) = @_;
3379 my $devices_list = vm_devices_list
($vmid);
3380 return 1 if !defined($devices_list->{$deviceid});
3382 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3384 if ($deviceid eq 'tablet') {
3386 qemu_devicedel
($vmid, $deviceid);
3388 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3390 qemu_devicedel
($vmid, $deviceid);
3391 qemu_devicedelverify
($vmid, $deviceid);
3392 qemu_drivedel
($vmid, $deviceid);
3393 qemu_iothread_del
($conf, $vmid, $deviceid);
3395 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3397 qemu_devicedel
($vmid, $deviceid);
3398 qemu_devicedelverify
($vmid, $deviceid);
3399 qemu_iothread_del
($conf, $vmid, $deviceid);
3401 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3403 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3404 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3405 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3407 qemu_devicedel
($vmid, $deviceid);
3408 qemu_drivedel
($vmid, $deviceid);
3409 qemu_deletescsihw
($conf, $vmid, $deviceid);
3411 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3413 qemu_devicedel
($vmid, $deviceid);
3414 qemu_devicedelverify
($vmid, $deviceid);
3415 qemu_netdevdel
($vmid, $deviceid);
3418 die "can't unplug device '$deviceid'\n";
3424 sub qemu_deviceadd
{
3425 my ($vmid, $devicefull) = @_;
3427 $devicefull = "driver=".$devicefull;
3428 my %options = split(/[=,]/, $devicefull);
3430 vm_mon_cmd
($vmid, "device_add" , %options);
3433 sub qemu_devicedel
{
3434 my ($vmid, $deviceid) = @_;
3436 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3439 sub qemu_iothread_add
{
3440 my($vmid, $deviceid, $device) = @_;
3442 if ($device->{iothread
}) {
3443 my $iothreads = vm_iothreads_list
($vmid);
3444 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3448 sub qemu_iothread_del
{
3449 my($conf, $vmid, $deviceid) = @_;
3451 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3452 if ($device->{iothread
}) {
3453 my $iothreads = vm_iothreads_list
($vmid);
3454 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3458 sub qemu_objectadd
{
3459 my($vmid, $objectid, $qomtype) = @_;
3461 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3466 sub qemu_objectdel
{
3467 my($vmid, $objectid) = @_;
3469 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3475 my ($storecfg, $vmid, $device) = @_;
3477 my $drive = print_drive_full
($storecfg, $vmid, $device);
3478 $drive =~ s/\\/\\\\/g;
3479 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3481 # If the command succeeds qemu prints: "OK
"
3482 return 1 if $ret =~ m/OK/s;
3484 die "adding drive failed
: $ret\n";
3488 my($vmid, $deviceid) = @_;
3490 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3493 return 1 if $ret eq "";
3495 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3496 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3498 die "deleting drive
$deviceid failed
: $ret\n";
3501 sub qemu_deviceaddverify {
3502 my ($vmid, $deviceid) = @_;
3504 for (my $i = 0; $i <= 5; $i++) {
3505 my $devices_list = vm_devices_list($vmid);
3506 return 1 if defined($devices_list->{$deviceid});
3510 die "error on hotplug device
'$deviceid'\n";
3514 sub qemu_devicedelverify {
3515 my ($vmid, $deviceid) = @_;
3517 # need to verify that the device is correctly removed as device_del
3518 # is async and empty return is not reliable
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 hot-unplugging device
'$deviceid'\n";
3529 sub qemu_findorcreatescsihw {
3530 my ($storecfg, $conf, $vmid, $device) = @_;
3532 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3534 my $scsihwid="$controller_prefix$controller";
3535 my $devices_list = vm_devices_list($vmid);
3537 if(!defined($devices_list->{$scsihwid})) {
3538 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3544 sub qemu_deletescsihw {
3545 my ($conf, $vmid, $opt) = @_;
3547 my $device = parse_drive($opt, $conf->{$opt});
3549 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3550 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3554 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3556 my $devices_list = vm_devices_list($vmid);
3557 foreach my $opt (keys %{$devices_list}) {
3558 if (PVE::QemuServer::valid_drivename($opt)) {
3559 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3560 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3566 my $scsihwid="scsihw
$controller";
3568 vm_deviceunplug($vmid, $conf, $scsihwid);
3573 sub qemu_add_pci_bridge {
3574 my ($storecfg, $conf, $vmid, $device) = @_;
3580 print_pci_addr($device, $bridges);
3582 while (my ($k, $v) = each %$bridges) {
3585 return 1 if !defined($bridgeid) || $bridgeid < 1;
3587 my $bridge = "pci
.$bridgeid";
3588 my $devices_list = vm_devices_list($vmid);
3590 if (!defined($devices_list->{$bridge})) {
3591 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3597 sub qemu_set_link_status {
3598 my ($vmid, $device, $up) = @_;
3600 vm_mon_cmd($vmid, "set_link
", name => $device,
3601 up => $up ? JSON::true : JSON::false);
3604 sub qemu_netdevadd {
3605 my ($vmid, $conf, $device, $deviceid) = @_;
3607 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3608 my %options = split(/[=,]/, $netdev);
3610 vm_mon_cmd($vmid, "netdev_add
", %options);
3614 sub qemu_netdevdel {
3615 my ($vmid, $deviceid) = @_;
3617 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3620 sub qemu_cpu_hotplug {
3621 my ($vmid, $conf, $vcpus) = @_;
3624 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3625 $sockets = $conf->{sockets} if $conf->{sockets};
3626 my $cores = $conf->{cores} || 1;
3627 my $maxcpus = $sockets * $cores;
3629 $vcpus = $maxcpus if !$vcpus;
3631 die "you can
't add more vcpus than maxcpus\n"
3632 if $vcpus > $maxcpus;
3634 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3635 die "online cpu unplug is not yet possible\n"
3636 if $vcpus < $currentvcpus;
3638 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3639 die "vcpus in running vm is different than configuration\n"
3640 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3642 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3643 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3647 sub qemu_memory_hotplug {
3648 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3650 return $value if !check_running($vmid);
3652 my $memory = $conf->{memory} || $defaults->{memory};
3653 $value = $defaults->{memory} if !$value;
3654 return $value if $value == $memory;
3656 my $static_memory = $STATICMEM;
3657 my $dimm_memory = $memory - $static_memory;
3659 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3660 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3664 $sockets = $conf->{sockets} if $conf->{sockets};
3666 if($value > $memory) {
3668 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3669 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3671 return if $current_size <= $conf->{memory};
3673 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3675 eval { qemu_objectdel($vmid, "mem-
$name"); };
3679 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3681 eval { qemu_objectdel($vmid, "mem-
$name"); };
3684 #update conf after each succesful module hotplug
3685 $conf->{memory} = $current_size;
3686 update_config_nolock($vmid, $conf, 1);
3691 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3692 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3694 return if $current_size >= $conf->{memory};
3695 print "try to unplug memory dimm
$name\n";
3699 eval { qemu_devicedel($vmid, $name) };
3701 my $dimm_list = qemu_dimm_list($vmid);
3702 last if !$dimm_list->{$name};
3703 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3707 #update conf after each succesful module unplug
3708 $conf->{memory} = $current_size;
3710 eval { qemu_objectdel($vmid, "mem-
$name"); };
3711 update_config_nolock($vmid, $conf, 1);
3716 sub qemu_dimm_list {
3719 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3722 foreach my $dimm (@$dimmarray) {
3724 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3725 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3726 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3727 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3728 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3733 sub qemu_block_set_io_throttle {
3734 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3736 return if !check_running($vmid) ;
3738 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));
3742 # old code, only used to shutdown old VM after update
3744 my ($fh, $timeout) = @_;
3746 my $sel = new IO::Select;
3753 while (scalar (@ready = $sel->can_read($timeout))) {
3755 if ($count = $fh->sysread($buf, 8192)) {
3756 if ($buf =~ /^(.*)\(qemu\) $/s) {
3763 if (!defined($count)) {
3770 die "monitor
read timeout
\n" if !scalar(@ready);
3775 # old code, only used to shutdown old VM after update
3776 sub vm_monitor_command {
3777 my ($vmid, $cmdstr, $nocheck) = @_;
3782 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3784 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3786 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3787 die "unable to
connect to VM
$vmid socket - $!\n";
3791 # hack: migrate sometime blocks the monitor (when migrate_downtime
3793 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3794 $timeout = 60*60; # 1 hour
3798 my $data = __read_avail($sock, $timeout);
3800 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3801 die "got unexpected qemu monitor banner
\n";
3804 my $sel = new IO::Select;
3807 if (!scalar(my @ready = $sel->can_write($timeout))) {
3808 die "monitor
write error
- timeout
";
3811 my $fullcmd = "$cmdstr\r";
3813 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3816 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3817 die "monitor
write error
- $!";
3820 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3824 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3825 $timeout = 60*60; # 1 hour
3826 } elsif ($cmdstr =~ m/^(eject|change)/) {
3827 $timeout = 60; # note: cdrom mount command is slow
3829 if ($res = __read_avail($sock, $timeout)) {
3831 my @lines = split("\r?
\n", $res);
3833 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3835 $res = join("\n", @lines);
3843 syslog("err
", "VM
$vmid monitor command failed
- $err");
3850 sub qemu_block_resize {
3851 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3853 my $running = check_running($vmid);
3855 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3857 return if !$running;
3859 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3863 sub qemu_volume_snapshot {
3864 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3866 my $running = check_running($vmid);
3868 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3869 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3871 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3875 sub qemu_volume_snapshot_delete {
3876 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3878 my $running = check_running($vmid);
3880 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3882 return if !$running;
3884 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3887 sub set_migration_caps {
3893 "auto-converge
" => 1,
3895 "x-rdma-pin-all
" => 0,
3900 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3902 for my $supported_capability (@$supported_capabilities) {
3904 capability => $supported_capability->{capability},
3905 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3909 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3912 my $fast_plug_option = {
3921 # hotplug changes in [PENDING]
3922 # $selection hash can be used to only apply specified options, for
3923 # example: { cores => 1 } (only apply changed 'cores')
3924 # $errors ref is used to return error messages
3925 sub vmconfig_hotplug_pending {
3926 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3928 my $defaults = load_defaults();
3930 # commit values which do not have any impact on running VM first
3931 # Note: those option cannot raise errors, we we do not care about
3932 # $selection and always apply them.
3934 my $add_error = sub {
3935 my ($opt, $msg) = @_;
3936 $errors->{$opt} = "hotplug problem
- $msg";
3940 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3941 if ($fast_plug_option->{$opt}) {
3942 $conf->{$opt} = $conf->{pending}->{$opt};
3943 delete $conf->{pending}->{$opt};
3949 update_config_nolock($vmid, $conf, 1);
3950 $conf = load_config($vmid); # update/reload
3953 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3955 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3956 while (my ($opt, $force) = each %$pending_delete_hash) {
3957 next if $selection && !$selection->{$opt};
3959 if ($opt eq 'hotplug') {
3960 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3961 } elsif ($opt eq 'tablet') {
3962 die "skip
\n" if !$hotplug_features->{usb};
3963 if ($defaults->{tablet}) {
3964 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3966 vm_deviceunplug($vmid, $conf, $opt);
3968 } elsif ($opt eq 'vcpus') {
3969 die "skip
\n" if !$hotplug_features->{cpu};
3970 qemu_cpu_hotplug($vmid, $conf, undef);
3971 } elsif ($opt eq 'balloon') {
3972 # enable balloon device is not hotpluggable
3973 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3974 } elsif ($fast_plug_option->{$opt}) {
3976 } elsif ($opt =~ m/^net(\d+)$/) {
3977 die "skip
\n" if !$hotplug_features->{network};
3978 vm_deviceunplug($vmid, $conf, $opt);
3979 } elsif (valid_drivename($opt)) {
3980 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3981 vm_deviceunplug($vmid, $conf, $opt);
3982 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3983 } elsif ($opt =~ m/^memory$/) {
3984 die "skip
\n" if !$hotplug_features->{memory};
3985 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3986 } elsif ($opt eq 'cpuunits') {
3987 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3988 } elsif ($opt eq 'cpulimit') {
3989 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3995 &$add_error($opt, $err) if $err ne "skip
\n";
3997 # save new config if hotplug was successful
3998 delete $conf->{$opt};
3999 vmconfig_undelete_pending_option($conf, $opt);
4000 update_config_nolock($vmid, $conf, 1);
4001 $conf = load_config($vmid); # update/reload
4005 foreach my $opt (keys %{$conf->{pending}}) {
4006 next if $selection && !$selection->{$opt};
4007 my $value = $conf->{pending}->{$opt};
4009 if ($opt eq 'hotplug') {
4010 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4011 } elsif ($opt eq 'tablet') {
4012 die "skip
\n" if !$hotplug_features->{usb};
4014 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4015 } elsif ($value == 0) {
4016 vm_deviceunplug($vmid, $conf, $opt);
4018 } elsif ($opt eq 'vcpus') {
4019 die "skip
\n" if !$hotplug_features->{cpu};
4020 qemu_cpu_hotplug($vmid, $conf, $value);
4021 } elsif ($opt eq 'balloon') {
4022 # enable/disable balloning device is not hotpluggable
4023 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4024 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4025 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4027 # allow manual ballooning if shares is set to zero
4028 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4029 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4030 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4032 } elsif ($opt =~ m/^net(\d+)$/) {
4033 # some changes can be done without hotplug
4034 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4035 $vmid, $opt, $value);
4036 } elsif (valid_drivename($opt)) {
4037 # some changes can be done without hotplug
4038 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4039 $vmid, $opt, $value, 1);
4040 } elsif ($opt =~ m/^memory$/) { #dimms
4041 die "skip
\n" if !$hotplug_features->{memory};
4042 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4043 } elsif ($opt eq 'cpuunits') {
4044 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4045 } elsif ($opt eq 'cpulimit') {
4046 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4047 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4049 die "skip
\n"; # skip non-hot-pluggable options
4053 &$add_error($opt, $err) if $err ne "skip
\n";
4055 # save new config if hotplug was successful
4056 $conf->{$opt} = $value;
4057 delete $conf->{pending}->{$opt};
4058 update_config_nolock($vmid, $conf, 1);
4059 $conf = load_config($vmid); # update/reload
4064 sub try_deallocate_drive {
4065 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4067 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4068 my $volid = $drive->{file};
4069 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4070 my $sid = PVE::Storage::parse_volume_id($volid);
4071 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4073 # check if the disk is really unused
4074 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4075 my $path = PVE::Storage::path($storecfg, $volid);
4076 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4077 if $used_paths->{$path};
4078 PVE::Storage::vdisk_free($storecfg, $volid);
4081 # If vm is not owner of this disk remove from config
4089 sub vmconfig_delete_or_detach_drive {
4090 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4092 my $drive = parse_drive($opt, $conf->{$opt});
4094 my $rpcenv = PVE::RPCEnvironment::get();
4095 my $authuser = $rpcenv->get_user();
4098 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4099 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4101 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4105 sub vmconfig_apply_pending {
4106 my ($vmid, $conf, $storecfg) = @_;
4110 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4111 while (my ($opt, $force) = each %$pending_delete_hash) {
4112 die "internal error
" if $opt =~ m/^unused/;
4113 $conf = load_config($vmid); # update/reload
4114 if (!defined($conf->{$opt})) {
4115 vmconfig_undelete_pending_option($conf, $opt);
4116 update_config_nolock($vmid, $conf, 1);
4117 } elsif (valid_drivename($opt)) {
4118 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4119 vmconfig_undelete_pending_option($conf, $opt);
4120 delete $conf->{$opt};
4121 update_config_nolock($vmid, $conf, 1);
4123 vmconfig_undelete_pending_option($conf, $opt);
4124 delete $conf->{$opt};
4125 update_config_nolock($vmid, $conf, 1);
4129 $conf = load_config($vmid); # update/reload
4131 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4132 $conf = load_config($vmid); # update/reload
4134 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4135 # skip if nothing changed
4136 } elsif (valid_drivename($opt)) {
4137 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4138 if defined($conf->{$opt});
4139 $conf->{$opt} = $conf->{pending}->{$opt};
4141 $conf->{$opt} = $conf->{pending}->{$opt};
4144 delete $conf->{pending}->{$opt};
4145 update_config_nolock($vmid, $conf, 1);
4149 my $safe_num_ne = sub {
4152 return 0 if !defined($a) && !defined($b);
4153 return 1 if !defined($a);
4154 return 1 if !defined($b);
4159 my $safe_string_ne = sub {
4162 return 0 if !defined($a) && !defined($b);
4163 return 1 if !defined($a);
4164 return 1 if !defined($b);
4169 sub vmconfig_update_net {
4170 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4172 my $newnet = parse_net($value);
4174 if ($conf->{$opt}) {
4175 my $oldnet = parse_net($conf->{$opt});
4177 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4178 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4179 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4180 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4182 # for non online change, we try to hot-unplug
4183 die "skip
\n" if !$hotplug;
4184 vm_deviceunplug($vmid, $conf, $opt);
4187 die "internal error
" if $opt !~ m/net(\d+)/;
4188 my $iface = "tap
${vmid
}i
$1";
4190 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4191 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4194 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4195 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4196 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4197 PVE::Network::tap_unplug($iface);
4198 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4201 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4202 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4210 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4216 sub vmconfig_update_disk {
4217 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4219 # fixme: do we need force?
4221 my $drive = parse_drive($opt, $value);
4223 if ($conf->{$opt}) {
4225 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4227 my $media = $drive->{media} || 'disk';
4228 my $oldmedia = $old_drive->{media} || 'disk';
4229 die "unable to change media type
\n" if $media ne $oldmedia;
4231 if (!drive_is_cdrom($old_drive)) {
4233 if ($drive->{file} ne $old_drive->{file}) {
4235 die "skip
\n" if !$hotplug;
4237 # unplug and register as unused
4238 vm_deviceunplug($vmid, $conf, $opt);
4239 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4242 # update existing disk
4244 # skip non hotpluggable value
4245 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4246 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4247 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4248 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4253 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4254 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4255 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4256 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4257 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4258 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4259 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4260 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4261 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4262 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4263 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4264 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4266 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4267 ($drive->{mbps} || 0)*1024*1024,
4268 ($drive->{mbps_rd} || 0)*1024*1024,
4269 ($drive->{mbps_wr} || 0)*1024*1024,
4270 $drive->{iops} || 0,
4271 $drive->{iops_rd} || 0,
4272 $drive->{iops_wr} || 0,
4273 ($drive->{mbps_max} || 0)*1024*1024,
4274 ($drive->{mbps_rd_max} || 0)*1024*1024,
4275 ($drive->{mbps_wr_max} || 0)*1024*1024,
4276 $drive->{iops_max} || 0,
4277 $drive->{iops_rd_max} || 0,
4278 $drive->{iops_wr_max} || 0);
4287 if ($drive->{file} eq 'none') {
4288 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4290 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4291 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4292 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4300 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4302 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
4303 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4307 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4308 $forcemachine, $spice_ticket) = @_;
4310 lock_config($vmid, sub {
4311 my $conf = load_config($vmid, $migratedfrom);
4313 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4315 check_lock($conf) if !$skiplock;
4317 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4319 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4320 vmconfig_apply_pending($vmid, $conf, $storecfg);
4321 $conf = load_config($vmid); # update/reload
4324 my $defaults = load_defaults();
4326 # set environment variable useful inside network script
4327 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4329 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4331 my $migrate_port = 0;
4334 if ($statefile eq 'tcp') {
4335 my $localip = "localhost
";
4336 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4337 my $nodename = PVE::INotify::nodename();
4338 if ($datacenterconf->{migration_unsecure}) {
4339 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4340 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4342 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4343 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4344 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4345 push @$cmd, '-incoming', $migrate_uri;
4348 push @$cmd, '-loadstate', $statefile;
4355 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4356 my $d = parse_hostpci($conf->{"hostpci
$i"});
4358 my $pcidevices = $d->{pciid};
4359 foreach my $pcidevice (@$pcidevices) {
4360 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4362 my $info = pci_device_info("0000:$pciid");
4363 die "IOMMU
not present
\n" if !check_iommu_support();
4364 die "no pci device info
for device
'$pciid'\n" if !$info;
4365 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4366 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4370 PVE::Storage::activate_volumes($storecfg, $vollist);
4372 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4375 die "start failed
: $err" if $err;
4377 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4379 if ($statefile && $statefile ne 'tcp') {
4380 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4384 if ($migratedfrom) {
4387 set_migration_caps($vmid);
4392 print "spice listens on port
$spice_port\n";
4393 if ($spice_ticket) {
4394 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4395 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4401 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4402 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4403 if $conf->{balloon};
4406 foreach my $opt (keys %$conf) {
4407 next if $opt !~ m/^net\d+$/;
4408 my $nicconf = parse_net($conf->{$opt});
4409 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4413 vm_mon_cmd_nocheck($vmid, 'qom-set',
4414 path => "machine
/peripheral/balloon0
",
4415 property => "guest-stats-polling-interval
",
4416 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4422 my ($vmid, $execute, %params) = @_;
4424 my $cmd = { execute => $execute, arguments => \%params };
4425 vm_qmp_command($vmid, $cmd);
4428 sub vm_mon_cmd_nocheck {
4429 my ($vmid, $execute, %params) = @_;
4431 my $cmd = { execute => $execute, arguments => \%params };
4432 vm_qmp_command($vmid, $cmd, 1);
4435 sub vm_qmp_command {
4436 my ($vmid, $cmd, $nocheck) = @_;
4441 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4442 $timeout = $cmd->{arguments}->{timeout};
4443 delete $cmd->{arguments}->{timeout};
4447 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4448 my $sname = qmp_socket($vmid);
4449 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4450 my $qmpclient = PVE::QMPClient->new();
4452 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4453 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4454 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4455 if scalar(%{$cmd->{arguments}});
4456 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4458 die "unable to open monitor socket\n";
4462 syslog("err", "VM $vmid qmp command failed - $err");
4469 sub vm_human_monitor_command {
4470 my ($vmid, $cmdline) = @_;
4475 execute => 'human-monitor-command
',
4476 arguments => { 'command-line
' => $cmdline},
4479 return vm_qmp_command($vmid, $cmd);
4482 sub vm_commandline {
4483 my ($storecfg, $vmid) = @_;
4485 my $conf = load_config($vmid);
4487 my $defaults = load_defaults();
4489 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4491 return join(' ', @$cmd);
4495 my ($vmid, $skiplock) = @_;
4497 lock_config($vmid, sub {
4499 my $conf = load_config($vmid);
4501 check_lock($conf) if !$skiplock;
4503 vm_mon_cmd($vmid, "system_reset");
4507 sub get_vm_volumes {
4511 foreach_volid($conf, sub {
4512 my ($volid, $is_cdrom) = @_;
4514 return if $volid =~ m|^/|;
4516 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4519 push @$vollist, $volid;
4525 sub vm_stop_cleanup {
4526 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4531 my $vollist = get_vm_volumes($conf);
4532 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4535 foreach my $ext (qw(mon qmp pid vnc qga)) {
4536 unlink "/var/run/qemu-server/${vmid}.$ext";
4539 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4541 warn $@ if $@; # avoid errors - just warn
4544 # Note: use $nockeck to skip tests if VM configuration file exists.
4545 # We need that when migration VMs to other nodes (files already moved)
4546 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4548 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4550 $force = 1 if !defined($force) && !$shutdown;
4553 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4554 kill 15, $pid if $pid;
4555 my $conf = load_config
($vmid, $migratedfrom);
4556 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4560 lock_config
($vmid, sub {
4562 my $pid = check_running
($vmid, $nocheck);
4567 $conf = load_config
($vmid);
4568 check_lock
($conf) if !$skiplock;
4569 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4570 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4571 $timeout = $opts->{down
} if $opts->{down
};
4575 $timeout = 60 if !defined($timeout);
4579 if (defined($conf) && $conf->{agent
}) {
4580 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4582 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4585 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4592 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4597 if ($count >= $timeout) {
4599 warn "VM still running - terminating now with SIGTERM\n";
4602 die "VM quit/powerdown failed - got timeout\n";
4605 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4610 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4613 die "VM quit/powerdown failed\n";
4621 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4626 if ($count >= $timeout) {
4627 warn "VM still running - terminating now with SIGKILL\n";
4632 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4637 my ($vmid, $skiplock) = @_;
4639 lock_config
($vmid, sub {
4641 my $conf = load_config
($vmid);
4643 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4645 vm_mon_cmd
($vmid, "stop");
4650 my ($vmid, $skiplock, $nocheck) = @_;
4652 lock_config
($vmid, sub {
4656 my $conf = load_config
($vmid);
4658 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4660 vm_mon_cmd
($vmid, "cont");
4663 vm_mon_cmd_nocheck
($vmid, "cont");
4669 my ($vmid, $skiplock, $key) = @_;
4671 lock_config
($vmid, sub {
4673 my $conf = load_config
($vmid);
4675 # there is no qmp command, so we use the human monitor command
4676 vm_human_monitor_command
($vmid, "sendkey $key");
4681 my ($storecfg, $vmid, $skiplock) = @_;
4683 lock_config
($vmid, sub {
4685 my $conf = load_config
($vmid);
4687 check_lock
($conf) if !$skiplock;
4689 if (!check_running
($vmid)) {
4690 destroy_vm
($storecfg, $vmid);
4692 die "VM $vmid is running - destroy failed\n";
4700 my ($filename, $buf) = @_;
4702 my $fh = IO
::File-
>new($filename, "w");
4703 return undef if !$fh;
4705 my $res = print $fh $buf;
4712 sub pci_device_info
{
4717 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4718 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4720 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4721 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4723 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4724 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4726 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4727 return undef if !defined($product) || $product !~ s/^0x//;
4732 product
=> $product,
4738 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4747 my $name = $dev->{name
};
4749 my $fn = "$pcisysfs/devices/$name/reset";
4751 return file_write
($fn, "1");
4754 sub pci_dev_bind_to_vfio
{
4757 my $name = $dev->{name
};
4759 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4761 if (!-d
$vfio_basedir) {
4762 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4764 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4766 my $testdir = "$vfio_basedir/$name";
4767 return 1 if -d
$testdir;
4769 my $data = "$dev->{vendor} $dev->{product}";
4770 return undef if !file_write
("$vfio_basedir/new_id", $data);
4772 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4773 if (!file_write
($fn, $name)) {
4774 return undef if -f
$fn;
4777 $fn = "$vfio_basedir/bind";
4778 if (! -d
$testdir) {
4779 return undef if !file_write
($fn, $name);
4785 sub pci_dev_group_bind_to_vfio
{
4788 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4790 if (!-d
$vfio_basedir) {
4791 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4793 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4795 # get IOMMU group devices
4796 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4797 my @devs = grep /^0000:/, readdir($D);
4800 foreach my $pciid (@devs) {
4801 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4803 # pci bridges, switches or root ports are not supported
4804 # they have a pci_bus subdirectory so skip them
4805 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4807 my $info = pci_device_info
($1);
4808 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4814 sub print_pci_addr
{
4815 my ($id, $bridges) = @_;
4819 piix3
=> { bus
=> 0, addr
=> 1 },
4820 #addr2 : first videocard
4821 balloon0
=> { bus
=> 0, addr
=> 3 },
4822 watchdog
=> { bus
=> 0, addr
=> 4 },
4823 scsihw0
=> { bus
=> 0, addr
=> 5 },
4824 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4825 scsihw1
=> { bus
=> 0, addr
=> 6 },
4826 ahci0
=> { bus
=> 0, addr
=> 7 },
4827 qga0
=> { bus
=> 0, addr
=> 8 },
4828 spice
=> { bus
=> 0, addr
=> 9 },
4829 virtio0
=> { bus
=> 0, addr
=> 10 },
4830 virtio1
=> { bus
=> 0, addr
=> 11 },
4831 virtio2
=> { bus
=> 0, addr
=> 12 },
4832 virtio3
=> { bus
=> 0, addr
=> 13 },
4833 virtio4
=> { bus
=> 0, addr
=> 14 },
4834 virtio5
=> { bus
=> 0, addr
=> 15 },
4835 hostpci0
=> { bus
=> 0, addr
=> 16 },
4836 hostpci1
=> { bus
=> 0, addr
=> 17 },
4837 net0
=> { bus
=> 0, addr
=> 18 },
4838 net1
=> { bus
=> 0, addr
=> 19 },
4839 net2
=> { bus
=> 0, addr
=> 20 },
4840 net3
=> { bus
=> 0, addr
=> 21 },
4841 net4
=> { bus
=> 0, addr
=> 22 },
4842 net5
=> { bus
=> 0, addr
=> 23 },
4843 vga1
=> { bus
=> 0, addr
=> 24 },
4844 vga2
=> { bus
=> 0, addr
=> 25 },
4845 vga3
=> { bus
=> 0, addr
=> 26 },
4846 hostpci2
=> { bus
=> 0, addr
=> 27 },
4847 hostpci3
=> { bus
=> 0, addr
=> 28 },
4848 #addr29 : usb-host (pve-usb.cfg)
4849 'pci.1' => { bus
=> 0, addr
=> 30 },
4850 'pci.2' => { bus
=> 0, addr
=> 31 },
4851 'net6' => { bus
=> 1, addr
=> 1 },
4852 'net7' => { bus
=> 1, addr
=> 2 },
4853 'net8' => { bus
=> 1, addr
=> 3 },
4854 'net9' => { bus
=> 1, addr
=> 4 },
4855 'net10' => { bus
=> 1, addr
=> 5 },
4856 'net11' => { bus
=> 1, addr
=> 6 },
4857 'net12' => { bus
=> 1, addr
=> 7 },
4858 'net13' => { bus
=> 1, addr
=> 8 },
4859 'net14' => { bus
=> 1, addr
=> 9 },
4860 'net15' => { bus
=> 1, addr
=> 10 },
4861 'net16' => { bus
=> 1, addr
=> 11 },
4862 'net17' => { bus
=> 1, addr
=> 12 },
4863 'net18' => { bus
=> 1, addr
=> 13 },
4864 'net19' => { bus
=> 1, addr
=> 14 },
4865 'net20' => { bus
=> 1, addr
=> 15 },
4866 'net21' => { bus
=> 1, addr
=> 16 },
4867 'net22' => { bus
=> 1, addr
=> 17 },
4868 'net23' => { bus
=> 1, addr
=> 18 },
4869 'net24' => { bus
=> 1, addr
=> 19 },
4870 'net25' => { bus
=> 1, addr
=> 20 },
4871 'net26' => { bus
=> 1, addr
=> 21 },
4872 'net27' => { bus
=> 1, addr
=> 22 },
4873 'net28' => { bus
=> 1, addr
=> 23 },
4874 'net29' => { bus
=> 1, addr
=> 24 },
4875 'net30' => { bus
=> 1, addr
=> 25 },
4876 'net31' => { bus
=> 1, addr
=> 26 },
4877 'virtio6' => { bus
=> 2, addr
=> 1 },
4878 'virtio7' => { bus
=> 2, addr
=> 2 },
4879 'virtio8' => { bus
=> 2, addr
=> 3 },
4880 'virtio9' => { bus
=> 2, addr
=> 4 },
4881 'virtio10' => { bus
=> 2, addr
=> 5 },
4882 'virtio11' => { bus
=> 2, addr
=> 6 },
4883 'virtio12' => { bus
=> 2, addr
=> 7 },
4884 'virtio13' => { bus
=> 2, addr
=> 8 },
4885 'virtio14' => { bus
=> 2, addr
=> 9 },
4886 'virtio15' => { bus
=> 2, addr
=> 10 },
4887 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4888 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4889 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4890 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4891 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4892 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4893 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4894 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4895 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4896 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4897 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4898 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4899 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4900 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4901 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4902 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4903 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4904 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4905 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4906 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4907 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4908 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4909 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4910 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4911 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4912 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4913 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4914 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4915 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4916 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4917 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4921 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4922 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4923 my $bus = $devices->{$id}->{bus
};
4924 $res = ",bus=pci.$bus,addr=$addr";
4925 $bridges->{$bus} = 1 if $bridges;
4931 sub print_pcie_addr
{
4936 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4937 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4938 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4939 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4942 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4943 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4944 my $bus = $devices->{$id}->{bus
};
4945 $res = ",bus=$bus,addr=$addr";
4951 # vzdump restore implementaion
4953 sub tar_archive_read_firstfile
{
4954 my $archive = shift;
4956 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4958 # try to detect archive type first
4959 my $pid = open (TMP
, "tar tf '$archive'|") ||
4960 die "unable to open file '$archive'\n";
4961 my $firstfile = <TMP
>;
4965 die "ERROR: archive contaions no data\n" if !$firstfile;
4971 sub tar_restore_cleanup
{
4972 my ($storecfg, $statfile) = @_;
4974 print STDERR
"starting cleanup\n";
4976 if (my $fd = IO
::File-
>new($statfile, "r")) {
4977 while (defined(my $line = <$fd>)) {
4978 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4981 if ($volid =~ m
|^/|) {
4982 unlink $volid || die 'unlink failed\n';
4984 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4986 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4988 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4990 print STDERR
"unable to parse line in statfile - $line";
4997 sub restore_archive
{
4998 my ($archive, $vmid, $user, $opts) = @_;
5000 my $format = $opts->{format
};
5003 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5004 $format = 'tar' if !$format;
5006 } elsif ($archive =~ m/\.tar$/) {
5007 $format = 'tar' if !$format;
5008 } elsif ($archive =~ m/.tar.lzo$/) {
5009 $format = 'tar' if !$format;
5011 } elsif ($archive =~ m/\.vma$/) {
5012 $format = 'vma' if !$format;
5013 } elsif ($archive =~ m/\.vma\.gz$/) {
5014 $format = 'vma' if !$format;
5016 } elsif ($archive =~ m/\.vma\.lzo$/) {
5017 $format = 'vma' if !$format;
5020 $format = 'vma' if !$format; # default
5023 # try to detect archive format
5024 if ($format eq 'tar') {
5025 return restore_tar_archive
($archive, $vmid, $user, $opts);
5027 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5031 sub restore_update_config_line
{
5032 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5034 return if $line =~ m/^\#qmdump\#/;
5035 return if $line =~ m/^\#vzdump\#/;
5036 return if $line =~ m/^lock:/;
5037 return if $line =~ m/^unused\d+:/;
5038 return if $line =~ m/^parent:/;
5039 return if $line =~ m/^template:/; # restored VM is never a template
5041 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5042 # try to convert old 1.X settings
5043 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5044 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5045 my ($model, $macaddr) = split(/\=/, $devconfig);
5046 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5049 bridge
=> "vmbr$ind",
5050 macaddr
=> $macaddr,
5052 my $netstr = print_net
($net);
5054 print $outfd "net$cookie->{netcount}: $netstr\n";
5055 $cookie->{netcount
}++;
5057 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5058 my ($id, $netstr) = ($1, $2);
5059 my $net = parse_net
($netstr);
5060 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5061 $netstr = print_net
($net);
5062 print $outfd "$id: $netstr\n";
5063 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5066 if ($line =~ m/backup=no/) {
5067 print $outfd "#$line";
5068 } elsif ($virtdev && $map->{$virtdev}) {
5069 my $di = parse_drive
($virtdev, $value);
5070 delete $di->{format
}; # format can change on restore
5071 $di->{file
} = $map->{$virtdev};
5072 $value = print_drive
($vmid, $di);
5073 print $outfd "$virtdev: $value\n";
5083 my ($cfg, $vmid) = @_;
5085 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5087 my $volid_hash = {};
5088 foreach my $storeid (keys %$info) {
5089 foreach my $item (@{$info->{$storeid}}) {
5090 next if !($item->{volid
} && $item->{size
});
5091 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5092 $volid_hash->{$item->{volid
}} = $item;
5099 sub get_used_paths
{
5100 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5104 my $scan_config = sub {
5105 my ($cref, $snapname) = @_;
5107 foreach my $key (keys %$cref) {
5108 my $value = $cref->{$key};
5109 if (valid_drivename
($key)) {
5110 next if $skip_drive && $key eq $skip_drive;
5111 my $drive = parse_drive
($key, $value);
5112 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5113 if ($drive->{file
} =~ m!^/!) {
5114 $used_path->{$drive->{file
}}++; # = 1;
5116 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5118 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5120 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5121 $used_path->{$path}++; # = 1;
5127 &$scan_config($conf);
5131 if ($scan_snapshots) {
5132 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5133 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5140 sub update_disksize
{
5141 my ($vmid, $conf, $volid_hash) = @_;
5147 # Note: it is allowed to define multiple storages with same path (alias), so
5148 # we need to check both 'volid' and real 'path' (two different volid can point
5149 # to the same path).
5154 foreach my $opt (keys %$conf) {
5155 if (valid_drivename
($opt)) {
5156 my $drive = parse_drive
($opt, $conf->{$opt});
5157 my $volid = $drive->{file
};
5160 $used->{$volid} = 1;
5161 if ($volid_hash->{$volid} &&
5162 (my $path = $volid_hash->{$volid}->{path
})) {
5163 $usedpath->{$path} = 1;
5166 next if drive_is_cdrom
($drive);
5167 next if !$volid_hash->{$volid};
5169 $drive->{size
} = $volid_hash->{$volid}->{size
};
5170 my $new = print_drive
($vmid, $drive);
5171 if ($new ne $conf->{$opt}) {
5173 $conf->{$opt} = $new;
5178 # remove 'unusedX' entry if volume is used
5179 foreach my $opt (keys %$conf) {
5180 next if $opt !~ m/^unused\d+$/;
5181 my $volid = $conf->{$opt};
5182 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5183 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5185 delete $conf->{$opt};
5189 foreach my $volid (sort keys %$volid_hash) {
5190 next if $volid =~ m/vm-$vmid-state-/;
5191 next if $used->{$volid};
5192 my $path = $volid_hash->{$volid}->{path
};
5193 next if !$path; # just to be sure
5194 next if $usedpath->{$path};
5196 add_unused_volume
($conf, $volid);
5197 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5204 my ($vmid, $nolock) = @_;
5206 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5208 my $volid_hash = scan_volids
($cfg, $vmid);
5210 my $updatefn = sub {
5213 my $conf = load_config
($vmid);
5218 foreach my $volid (keys %$volid_hash) {
5219 my $info = $volid_hash->{$volid};
5220 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5223 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5225 update_config_nolock
($vmid, $conf, 1) if $changes;
5228 if (defined($vmid)) {
5232 lock_config
($vmid, $updatefn, $vmid);
5235 my $vmlist = config_list
();
5236 foreach my $vmid (keys %$vmlist) {
5240 lock_config
($vmid, $updatefn, $vmid);
5246 sub restore_vma_archive
{
5247 my ($archive, $vmid, $user, $opts, $comp) = @_;
5249 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5250 my $readfrom = $archive;
5255 my $qarchive = PVE
::Tools
::shellquote
($archive);
5256 if ($comp eq 'gzip') {
5257 $uncomp = "zcat $qarchive|";
5258 } elsif ($comp eq 'lzop') {
5259 $uncomp = "lzop -d -c $qarchive|";
5261 die "unknown compression method '$comp'\n";
5266 my $tmpdir = "/var/tmp/vzdumptmp$$";
5269 # disable interrupts (always do cleanups)
5270 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5271 warn "got interrupt - ignored\n";
5274 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5275 POSIX
::mkfifo
($mapfifo, 0600);
5278 my $openfifo = sub {
5279 open($fifofh, '>', $mapfifo) || die $!;
5282 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5289 my $rpcenv = PVE
::RPCEnvironment
::get
();
5291 my $conffile = config_file
($vmid);
5292 my $tmpfn = "$conffile.$$.tmp";
5294 # Note: $oldconf is undef if VM does not exists
5295 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5297 my $print_devmap = sub {
5298 my $virtdev_hash = {};
5300 my $cfgfn = "$tmpdir/qemu-server.conf";
5302 # we can read the config - that is already extracted
5303 my $fh = IO
::File-
>new($cfgfn, "r") ||
5304 "unable to read qemu-server.conf - $!\n";
5306 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5307 PVE
::Tools
::file_copy
($fwcfgfn, "/etc/pve/firewall/$vmid.fw")
5310 while (defined(my $line = <$fh>)) {
5311 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5312 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5313 die "archive does not contain data for drive '$virtdev'\n"
5314 if !$devinfo->{$devname};
5315 if (defined($opts->{storage
})) {
5316 $storeid = $opts->{storage
} || 'local';
5317 } elsif (!$storeid) {
5320 $format = 'raw' if !$format;
5321 $devinfo->{$devname}->{devname
} = $devname;
5322 $devinfo->{$devname}->{virtdev
} = $virtdev;
5323 $devinfo->{$devname}->{format
} = $format;
5324 $devinfo->{$devname}->{storeid
} = $storeid;
5326 # check permission on storage
5327 my $pool = $opts->{pool
}; # todo: do we need that?
5328 if ($user ne 'root@pam') {
5329 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5332 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5336 foreach my $devname (keys %$devinfo) {
5337 die "found no device mapping information for device '$devname'\n"
5338 if !$devinfo->{$devname}->{virtdev
};
5341 my $cfg = cfs_read_file
('storage.cfg');
5343 # create empty/temp config
5345 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5346 foreach_drive
($oldconf, sub {
5347 my ($ds, $drive) = @_;
5349 return if drive_is_cdrom
($drive);
5351 my $volid = $drive->{file
};
5353 return if !$volid || $volid =~ m
|^/|;
5355 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5356 return if !$path || !$owner || ($owner != $vmid);
5358 # Note: only delete disk we want to restore
5359 # other volumes will become unused
5360 if ($virtdev_hash->{$ds}) {
5361 PVE
::Storage
::vdisk_free
($cfg, $volid);
5367 foreach my $virtdev (sort keys %$virtdev_hash) {
5368 my $d = $virtdev_hash->{$virtdev};
5369 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5370 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5372 # test if requested format is supported
5373 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5374 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5375 $d->{format
} = $defFormat if !$supported;
5377 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5378 $d->{format
}, undef, $alloc_size);
5379 print STDERR
"new volume ID is '$volid'\n";
5380 $d->{volid
} = $volid;
5381 my $path = PVE
::Storage
::path
($cfg, $volid);
5383 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5385 my $write_zeros = 1;
5386 # fixme: what other storages types initialize volumes with zero?
5387 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5388 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5392 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5394 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5395 $map->{$virtdev} = $volid;
5398 $fh->seek(0, 0) || die "seek failed - $!\n";
5400 my $outfd = new IO
::File
($tmpfn, "w") ||
5401 die "unable to write config for VM $vmid\n";
5403 my $cookie = { netcount
=> 0 };
5404 while (defined(my $line = <$fh>)) {
5405 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5414 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5415 die "interrupted by signal\n";
5417 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5419 $oldtimeout = alarm($timeout);
5426 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5427 my ($dev_id, $size, $devname) = ($1, $2, $3);
5428 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5429 } elsif ($line =~ m/^CTIME: /) {
5430 # we correctly received the vma config, so we can disable
5431 # the timeout now for disk allocation (set to 10 minutes, so
5432 # that we always timeout if something goes wrong)
5435 print $fifofh "done\n";
5436 my $tmp = $oldtimeout || 0;
5437 $oldtimeout = undef;
5443 print "restore vma archive: $cmd\n";
5444 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5448 alarm($oldtimeout) if $oldtimeout;
5451 foreach my $devname (keys %$devinfo) {
5452 my $volid = $devinfo->{$devname}->{volid
};
5453 push @$vollist, $volid if $volid;
5456 my $cfg = cfs_read_file
('storage.cfg');
5457 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5465 foreach my $devname (keys %$devinfo) {
5466 my $volid = $devinfo->{$devname}->{volid
};
5469 if ($volid =~ m
|^/|) {
5470 unlink $volid || die 'unlink failed\n';
5472 PVE
::Storage
::vdisk_free
($cfg, $volid);
5474 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5476 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5483 rename($tmpfn, $conffile) ||
5484 die "unable to commit configuration file '$conffile'\n";
5486 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5488 eval { rescan
($vmid, 1); };
5492 sub restore_tar_archive
{
5493 my ($archive, $vmid, $user, $opts) = @_;
5495 if ($archive ne '-') {
5496 my $firstfile = tar_archive_read_firstfile
($archive);
5497 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5498 if $firstfile ne 'qemu-server.conf';
5501 my $storecfg = cfs_read_file
('storage.cfg');
5503 # destroy existing data - keep empty config
5504 my $vmcfgfn = config_file
($vmid);
5505 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5507 my $tocmd = "/usr/lib/qemu-server/qmextract";
5509 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5510 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5511 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5512 $tocmd .= ' --info' if $opts->{info
};
5514 # tar option "xf" does not autodetect compression when read from STDIN,
5515 # so we pipe to zcat
5516 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5517 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5519 my $tmpdir = "/var/tmp/vzdumptmp$$";
5522 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5523 local $ENV{VZDUMP_VMID
} = $vmid;
5524 local $ENV{VZDUMP_USER
} = $user;
5526 my $conffile = config_file
($vmid);
5527 my $tmpfn = "$conffile.$$.tmp";
5529 # disable interrupts (always do cleanups)
5530 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5531 print STDERR
"got interrupt - ignored\n";
5536 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5537 die "interrupted by signal\n";
5540 if ($archive eq '-') {
5541 print "extracting archive from STDIN\n";
5542 run_command
($cmd, input
=> "<&STDIN");
5544 print "extracting archive '$archive'\n";
5548 return if $opts->{info
};
5552 my $statfile = "$tmpdir/qmrestore.stat";
5553 if (my $fd = IO
::File-
>new($statfile, "r")) {
5554 while (defined (my $line = <$fd>)) {
5555 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5556 $map->{$1} = $2 if $1;
5558 print STDERR
"unable to parse line in statfile - $line\n";
5564 my $confsrc = "$tmpdir/qemu-server.conf";
5566 my $srcfd = new IO
::File
($confsrc, "r") ||
5567 die "unable to open file '$confsrc'\n";
5569 my $outfd = new IO
::File
($tmpfn, "w") ||
5570 die "unable to write config for VM $vmid\n";
5572 my $cookie = { netcount
=> 0 };
5573 while (defined (my $line = <$srcfd>)) {
5574 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5586 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5593 rename $tmpfn, $conffile ||
5594 die "unable to commit configuration file '$conffile'\n";
5596 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5598 eval { rescan
($vmid, 1); };
5603 # Internal snapshots
5605 # NOTE: Snapshot create/delete involves several non-atomic
5606 # action, and can take a long time.
5607 # So we try to avoid locking the file and use 'lock' variable
5608 # inside the config file instead.
5610 my $snapshot_copy_config = sub {
5611 my ($source, $dest) = @_;
5613 foreach my $k (keys %$source) {
5614 next if $k eq 'snapshots';
5615 next if $k eq 'snapstate';
5616 next if $k eq 'snaptime';
5617 next if $k eq 'vmstate';
5618 next if $k eq 'lock';
5619 next if $k eq 'digest';
5620 next if $k eq 'description';
5621 next if $k =~ m/^unused\d+$/;
5623 $dest->{$k} = $source->{$k};
5627 my $snapshot_apply_config = sub {
5628 my ($conf, $snap) = @_;
5630 # copy snapshot list
5632 snapshots
=> $conf->{snapshots
},
5635 # keep description and list of unused disks
5636 foreach my $k (keys %$conf) {
5637 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5638 $newconf->{$k} = $conf->{$k};
5641 &$snapshot_copy_config($snap, $newconf);
5646 sub foreach_writable_storage
{
5647 my ($conf, $func) = @_;
5651 foreach my $ds (keys %$conf) {
5652 next if !valid_drivename
($ds);
5654 my $drive = parse_drive
($ds, $conf->{$ds});
5656 next if drive_is_cdrom
($drive);
5658 my $volid = $drive->{file
};
5660 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5661 $sidhash->{$sid} = $sid if $sid;
5664 foreach my $sid (sort keys %$sidhash) {
5669 my $alloc_vmstate_volid = sub {
5670 my ($storecfg, $vmid, $conf, $snapname) = @_;
5672 # Note: we try to be smart when selecting a $target storage
5676 # search shared storage first
5677 foreach_writable_storage
($conf, sub {
5679 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5680 return if !$scfg->{shared
};
5682 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5686 # now search local storage
5687 foreach_writable_storage
($conf, sub {
5689 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5690 return if $scfg->{shared
};
5692 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5696 $target = 'local' if !$target;
5698 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5699 # we abort live save after $conf->{memory}, so we need at max twice that space
5700 my $size = $conf->{memory
}*2 + $driver_state_size;
5702 my $name = "vm-$vmid-state-$snapname";
5703 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5704 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5705 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5710 my $snapshot_prepare = sub {
5711 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5715 my $updatefn = sub {
5717 my $conf = load_config
($vmid);
5719 die "you can't take a snapshot if it's a template\n"
5720 if is_template
($conf);
5724 $conf->{lock} = 'snapshot';
5726 die "snapshot name '$snapname' already used\n"
5727 if defined($conf->{snapshots
}->{$snapname});
5729 my $storecfg = PVE
::Storage
::config
();
5730 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5732 $snap = $conf->{snapshots
}->{$snapname} = {};
5734 if ($save_vmstate && check_running
($vmid)) {
5735 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5738 &$snapshot_copy_config($conf, $snap);
5740 $snap->{snapstate
} = "prepare";
5741 $snap->{snaptime
} = time();
5742 $snap->{description
} = $comment if $comment;
5744 # always overwrite machine if we save vmstate. This makes sure we
5745 # can restore it later using correct machine type
5746 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5748 update_config_nolock
($vmid, $conf, 1);
5751 lock_config
($vmid, $updatefn);
5756 my $snapshot_commit = sub {
5757 my ($vmid, $snapname) = @_;
5759 my $updatefn = sub {
5761 my $conf = load_config
($vmid);
5763 die "missing snapshot lock\n"
5764 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5766 my $has_machine_config = defined($conf->{machine
});
5768 my $snap = $conf->{snapshots
}->{$snapname};
5770 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5772 die "wrong snapshot state\n"
5773 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5775 delete $snap->{snapstate
};
5776 delete $conf->{lock};
5778 my $newconf = &$snapshot_apply_config($conf, $snap);
5780 delete $newconf->{machine
} if !$has_machine_config;
5782 $newconf->{parent
} = $snapname;
5784 update_config_nolock
($vmid, $newconf, 1);
5787 lock_config
($vmid, $updatefn);
5790 sub snapshot_rollback
{
5791 my ($vmid, $snapname) = @_;
5795 my $storecfg = PVE
::Storage
::config
();
5797 my $conf = load_config
($vmid);
5799 my $get_snapshot_config = sub {
5801 die "you can't rollback if vm is a template\n" if is_template
($conf);
5803 my $res = $conf->{snapshots
}->{$snapname};
5805 die "snapshot '$snapname' does not exist\n" if !defined($res);
5810 my $snap = &$get_snapshot_config();
5812 foreach_drive
($snap, sub {
5813 my ($ds, $drive) = @_;
5815 return if drive_is_cdrom
($drive);
5817 my $volid = $drive->{file
};
5819 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5822 my $updatefn = sub {
5824 $conf = load_config
($vmid);
5826 $snap = &$get_snapshot_config();
5828 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5829 if $snap->{snapstate
};
5833 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5836 die "unable to rollback vm $vmid: vm is running\n"
5837 if check_running
($vmid);
5840 $conf->{lock} = 'rollback';
5842 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5843 delete $conf->{lock};
5849 my $has_machine_config = defined($conf->{machine
});
5851 # copy snapshot config to current config
5852 $conf = &$snapshot_apply_config($conf, $snap);
5853 $conf->{parent
} = $snapname;
5855 # Note: old code did not store 'machine', so we try to be smart
5856 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5857 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5858 # we remove the 'machine' configuration if not explicitly specified
5859 # in the original config.
5860 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5863 update_config_nolock
($vmid, $conf, 1);
5865 if (!$prepare && $snap->{vmstate
}) {
5866 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5867 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5871 lock_config
($vmid, $updatefn);
5873 foreach_drive
($snap, sub {
5874 my ($ds, $drive) = @_;
5876 return if drive_is_cdrom
($drive);
5878 my $volid = $drive->{file
};
5879 my $device = "drive-$ds";
5881 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5885 lock_config
($vmid, $updatefn);
5888 my $savevm_wait = sub {
5892 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5893 if (!$stat->{status
}) {
5894 die "savevm not active\n";
5895 } elsif ($stat->{status
} eq 'active') {
5898 } elsif ($stat->{status
} eq 'completed') {
5901 die "query-savevm returned status '$stat->{status}'\n";
5906 sub do_snapshots_with_qemu
{
5907 my ($storecfg, $volid) = @_;
5909 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5911 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5912 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5916 if ($volid =~ m/\.(qcow2|qed)$/){
5923 sub snapshot_create
{
5924 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5926 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5928 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5930 my $config = load_config
($vmid);
5932 my $running = check_running
($vmid);
5934 my $freezefs = $running && $config->{agent
};
5935 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5940 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5941 warn "guest-fsfreeze-freeze problems - $@" if $@;
5945 # create internal snapshots of all drives
5947 my $storecfg = PVE
::Storage
::config
();
5950 if ($snap->{vmstate
}) {
5951 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5952 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5953 &$savevm_wait($vmid);
5955 vm_mon_cmd
($vmid, "savevm-start");
5959 foreach_drive
($snap, sub {
5960 my ($ds, $drive) = @_;
5962 return if drive_is_cdrom
($drive);
5964 my $volid = $drive->{file
};
5965 my $device = "drive-$ds";
5967 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5968 $drivehash->{$ds} = 1;
5974 eval { vm_mon_cmd
($vmid, "savevm-end") };
5978 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5979 warn "guest-fsfreeze-thaw problems - $@" if $@;
5982 # savevm-end is async, we need to wait
5984 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5985 if (!$stat->{bytes
}) {
5988 print "savevm not yet finished\n";
5996 warn "snapshot create failed: starting cleanup\n";
5997 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6002 &$snapshot_commit($vmid, $snapname);
6005 # Note: $drivehash is only set when called from snapshot_create.
6006 sub snapshot_delete
{
6007 my ($vmid, $snapname, $force, $drivehash) = @_;
6014 my $unlink_parent = sub {
6015 my ($confref, $new_parent) = @_;
6017 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6019 $confref->{parent
} = $new_parent;
6021 delete $confref->{parent
};
6026 my $updatefn = sub {
6027 my ($remove_drive) = @_;
6029 my $conf = load_config
($vmid);
6033 die "you can't delete a snapshot if vm is a template\n"
6034 if is_template
($conf);
6037 $snap = $conf->{snapshots
}->{$snapname};
6039 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6041 # remove parent refs
6043 &$unlink_parent($conf, $snap->{parent
});
6044 foreach my $sn (keys %{$conf->{snapshots
}}) {
6045 next if $sn eq $snapname;
6046 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6050 if ($remove_drive) {
6051 if ($remove_drive eq 'vmstate') {
6052 delete $snap->{$remove_drive};
6054 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6055 my $volid = $drive->{file
};
6056 delete $snap->{$remove_drive};
6057 add_unused_volume
($conf, $volid);
6062 $snap->{snapstate
} = 'delete';
6064 delete $conf->{snapshots
}->{$snapname};
6065 delete $conf->{lock} if $drivehash;
6066 foreach my $volid (@$unused) {
6067 add_unused_volume
($conf, $volid);
6071 update_config_nolock
($vmid, $conf, 1);
6074 lock_config
($vmid, $updatefn);
6076 # now remove vmstate file
6078 my $storecfg = PVE
::Storage
::config
();
6080 if ($snap->{vmstate
}) {
6081 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6083 die $err if !$force;
6086 # save changes (remove vmstate from snapshot)
6087 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6090 # now remove all internal snapshots
6091 foreach_drive
($snap, sub {
6092 my ($ds, $drive) = @_;
6094 return if drive_is_cdrom
($drive);
6096 my $volid = $drive->{file
};
6097 my $device = "drive-$ds";
6099 if (!$drivehash || $drivehash->{$ds}) {
6100 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6102 die $err if !$force;
6107 # save changes (remove drive fron snapshot)
6108 lock_config
($vmid, $updatefn, $ds) if !$force;
6109 push @$unused, $volid;
6112 # now cleanup config
6114 lock_config
($vmid, $updatefn);
6118 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6121 foreach_drive
($conf, sub {
6122 my ($ds, $drive) = @_;
6124 return if drive_is_cdrom
($drive);
6125 my $volid = $drive->{file
};
6126 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6129 return $err ?
0 : 1;
6132 sub template_create
{
6133 my ($vmid, $conf, $disk) = @_;
6135 my $storecfg = PVE
::Storage
::config
();
6137 foreach_drive
($conf, sub {
6138 my ($ds, $drive) = @_;
6140 return if drive_is_cdrom
($drive);
6141 return if $disk && $ds ne $disk;
6143 my $volid = $drive->{file
};
6144 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6146 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6147 $drive->{file
} = $voliddst;
6148 $conf->{$ds} = print_drive
($vmid, $drive);
6149 update_config_nolock
($vmid, $conf, 1);
6156 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6159 sub qemu_img_convert
{
6160 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6162 my $storecfg = PVE
::Storage
::config
();
6163 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6164 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6166 if ($src_storeid && $dst_storeid) {
6168 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6170 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6171 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6173 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6174 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6176 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6177 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6180 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6181 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6182 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6186 if($line =~ m/\((\S+)\/100\
%\)/){
6188 my $transferred = int($size * $percent / 100);
6189 my $remaining = $size - $transferred;
6191 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6196 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6198 die "copy failed: $err" if $err;
6202 sub qemu_img_format
{
6203 my ($scfg, $volname) = @_;
6205 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6212 sub qemu_drive_mirror
{
6213 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6215 my $storecfg = PVE
::Storage
::config
();
6216 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6218 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6220 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6222 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6224 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6225 $opts->{format
} = $format if $format;
6227 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6230 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6232 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6233 my $stat = @$stats[0];
6234 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6235 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6237 my $busy = $stat->{busy
};
6238 my $ready = $stat->{ready
};
6240 if (my $total = $stat->{len
}) {
6241 my $transferred = $stat->{offset
} || 0;
6242 my $remaining = $total - $transferred;
6243 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6245 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6249 if ($stat->{ready
} eq 'true') {
6251 last if $vmiddst != $vmid;
6253 # try to switch the disk if source and destination are on the same guest
6254 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6256 die $@ if $@ !~ m/cannot be completed/;
6265 my $cancel_job = sub {
6266 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6268 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6269 my $stat = @$stats[0];
6276 eval { &$cancel_job(); };
6277 die "mirroring error: $err";
6280 if ($vmiddst != $vmid) {
6281 # if we clone a disk for a new target vm, we don't switch the disk
6282 &$cancel_job(); # so we call block-job-cancel
6287 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6288 $newvmid, $storage, $format, $full, $newvollist) = @_;
6293 print "create linked clone of drive $drivename ($drive->{file})\n";
6294 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6295 push @$newvollist, $newvolid;
6297 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6298 $storeid = $storage if $storage;
6300 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6302 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6303 $format = qemu_img_format
($scfg, $volname);
6306 # test if requested format is supported - else use default
6307 my $supported = grep { $_ eq $format } @$validFormats;
6308 $format = $defFormat if !$supported;
6310 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6312 print "create full clone of drive $drivename ($drive->{file})\n";
6313 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6314 push @$newvollist, $newvolid;
6316 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6318 if (!$running || $snapname) {
6319 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6321 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6325 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6328 $disk->{format
} = undef;
6329 $disk->{file
} = $newvolid;
6330 $disk->{size
} = $size;
6335 # this only works if VM is running
6336 sub get_current_qemu_machine
{
6339 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6340 my $res = vm_qmp_command
($vmid, $cmd);
6342 my ($current, $default);
6343 foreach my $e (@$res) {
6344 $default = $e->{name
} if $e->{'is-default'};
6345 $current = $e->{name
} if $e->{'is-current'};
6348 # fallback to the default machine if current is not supported by qemu
6349 return $current || $default || 'pc';
6352 sub qemu_machine_feature_enabled
{
6353 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6358 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6360 $current_major = $3;
6361 $current_minor = $4;
6363 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6365 $current_major = $1;
6366 $current_minor = $2;
6369 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6374 sub qemu_machine_pxe
{
6375 my ($vmid, $conf, $machine) = @_;
6377 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6379 foreach my $opt (keys %$conf) {
6380 next if $opt !~ m/^net(\d+)$/;
6381 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6383 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6384 return $machine.".pxe" if $romfile =~ m/pxe/;
6390 sub qemu_use_old_bios_files
{
6391 my ($machine_type) = @_;
6393 return if !$machine_type;
6395 my $use_old_bios_files = undef;
6397 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6399 $use_old_bios_files = 1;
6401 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6402 # load new efi bios files on migration. So this hack is required to allow
6403 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6404 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6405 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6408 return ($use_old_bios_files, $machine_type);
6415 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6416 my (undef, $id, $function) = @_;
6417 my $res = { id
=> $id, function
=> $function};
6418 push @{$devices->{$id}}, $res;
6424 sub vm_iothreads_list
{
6427 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6430 foreach my $iothread (@$res) {
6431 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6438 my ($conf, $drive) = @_;
6442 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6444 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6450 my $controller = int($drive->{index} / $maxdev);
6451 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6453 return ($maxdev, $controller, $controller_prefix);
6456 # bash completion helper
6458 sub complete_backup_archives
{
6459 my ($cmdname, $pname, $cvalue) = @_;
6461 my $cfg = PVE
::Storage
::config
();
6465 if ($cvalue =~ m/^([^:]+):/) {
6469 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6472 foreach my $id (keys %$data) {
6473 foreach my $item (@{$data->{$id}}) {
6474 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6475 push @$res, $item->{volid
} if defined($item->{volid
});
6482 my $complete_vmid_full = sub {
6485 my $idlist = vmstatus
();
6489 foreach my $id (keys %$idlist) {
6490 my $d = $idlist->{$id};
6491 if (defined($running)) {
6492 next if $d->{template
};
6493 next if $running && $d->{status
} ne 'running';
6494 next if !$running && $d->{status
} eq 'running';
6503 return &$complete_vmid_full();
6506 sub complete_vmid_stopped
{
6507 return &$complete_vmid_full(0);
6510 sub complete_vmid_running
{
6511 return &$complete_vmid_full(1);
6514 sub complete_storage
{
6516 my $cfg = PVE
::Storage
::config
();
6517 my $ids = $cfg->{ids
};
6520 foreach my $sid (keys %$ids) {
6521 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6522 next if !$ids->{$sid}->{content
}->{images
};