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 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4306 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4307 $forcemachine, $spice_ticket) = @_;
4309 lock_config($vmid, sub {
4310 my $conf = load_config($vmid, $migratedfrom);
4312 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4314 check_lock($conf) if !$skiplock;
4316 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4318 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4319 vmconfig_apply_pending($vmid, $conf, $storecfg);
4320 $conf = load_config($vmid); # update/reload
4323 my $defaults = load_defaults();
4325 # set environment variable useful inside network script
4326 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4328 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4330 my $migrate_port = 0;
4333 if ($statefile eq 'tcp') {
4334 my $localip = "localhost
";
4335 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4336 my $nodename = PVE::INotify::nodename();
4337 if ($datacenterconf->{migration_unsecure}) {
4338 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4339 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4341 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4342 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4343 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4344 push @$cmd, '-incoming', $migrate_uri;
4347 push @$cmd, '-loadstate', $statefile;
4354 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4355 my $d = parse_hostpci($conf->{"hostpci
$i"});
4357 my $pcidevices = $d->{pciid};
4358 foreach my $pcidevice (@$pcidevices) {
4359 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4361 my $info = pci_device_info("0000:$pciid");
4362 die "IOMMU
not present
\n" if !check_iommu_support();
4363 die "no pci device info
for device
'$pciid'\n" if !$info;
4364 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4365 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4369 PVE::Storage::activate_volumes($storecfg, $vollist);
4371 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4374 die "start failed
: $err" if $err;
4376 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4378 if ($statefile && $statefile ne 'tcp') {
4379 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4383 if ($migratedfrom) {
4386 set_migration_caps($vmid);
4391 print "spice listens on port
$spice_port\n";
4392 if ($spice_ticket) {
4393 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4394 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4400 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4401 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4402 if $conf->{balloon};
4405 foreach my $opt (keys %$conf) {
4406 next if $opt !~ m/^net\d+$/;
4407 my $nicconf = parse_net($conf->{$opt});
4408 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4412 vm_mon_cmd_nocheck($vmid, 'qom-set',
4413 path => "machine
/peripheral/balloon0
",
4414 property => "guest-stats-polling-interval
",
4415 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4421 my ($vmid, $execute, %params) = @_;
4423 my $cmd = { execute => $execute, arguments => \%params };
4424 vm_qmp_command($vmid, $cmd);
4427 sub vm_mon_cmd_nocheck {
4428 my ($vmid, $execute, %params) = @_;
4430 my $cmd = { execute => $execute, arguments => \%params };
4431 vm_qmp_command($vmid, $cmd, 1);
4434 sub vm_qmp_command {
4435 my ($vmid, $cmd, $nocheck) = @_;
4440 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4441 $timeout = $cmd->{arguments}->{timeout};
4442 delete $cmd->{arguments}->{timeout};
4446 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4447 my $sname = qmp_socket($vmid);
4448 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4449 my $qmpclient = PVE::QMPClient->new();
4451 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4452 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4453 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4454 if scalar(%{$cmd->{arguments}});
4455 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4457 die "unable to open monitor socket\n";
4461 syslog("err", "VM $vmid qmp command failed - $err");
4468 sub vm_human_monitor_command {
4469 my ($vmid, $cmdline) = @_;
4474 execute => 'human-monitor-command
',
4475 arguments => { 'command-line
' => $cmdline},
4478 return vm_qmp_command($vmid, $cmd);
4481 sub vm_commandline {
4482 my ($storecfg, $vmid) = @_;
4484 my $conf = load_config($vmid);
4486 my $defaults = load_defaults();
4488 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4490 return join(' ', @$cmd);
4494 my ($vmid, $skiplock) = @_;
4496 lock_config($vmid, sub {
4498 my $conf = load_config($vmid);
4500 check_lock($conf) if !$skiplock;
4502 vm_mon_cmd($vmid, "system_reset");
4506 sub get_vm_volumes {
4510 foreach_volid($conf, sub {
4511 my ($volid, $is_cdrom) = @_;
4513 return if $volid =~ m|^/|;
4515 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4518 push @$vollist, $volid;
4524 sub vm_stop_cleanup {
4525 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4530 my $vollist = get_vm_volumes($conf);
4531 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4534 foreach my $ext (qw(mon qmp pid vnc qga)) {
4535 unlink "/var/run/qemu-server/${vmid}.$ext";
4538 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4540 warn $@ if $@; # avoid errors - just warn
4543 # Note: use $nockeck to skip tests if VM configuration file exists.
4544 # We need that when migration VMs to other nodes (files already moved)
4545 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4547 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4549 $force = 1 if !defined($force) && !$shutdown;
4552 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4553 kill 15, $pid if $pid;
4554 my $conf = load_config
($vmid, $migratedfrom);
4555 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4559 lock_config
($vmid, sub {
4561 my $pid = check_running
($vmid, $nocheck);
4566 $conf = load_config
($vmid);
4567 check_lock
($conf) if !$skiplock;
4568 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4569 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4570 $timeout = $opts->{down
} if $opts->{down
};
4574 $timeout = 60 if !defined($timeout);
4578 if (defined($conf) && $conf->{agent
}) {
4579 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4581 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4584 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4591 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4596 if ($count >= $timeout) {
4598 warn "VM still running - terminating now with SIGTERM\n";
4601 die "VM quit/powerdown failed - got timeout\n";
4604 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4609 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4612 die "VM quit/powerdown failed\n";
4620 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4625 if ($count >= $timeout) {
4626 warn "VM still running - terminating now with SIGKILL\n";
4631 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4636 my ($vmid, $skiplock) = @_;
4638 lock_config
($vmid, sub {
4640 my $conf = load_config
($vmid);
4642 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4644 vm_mon_cmd
($vmid, "stop");
4649 my ($vmid, $skiplock, $nocheck) = @_;
4651 lock_config
($vmid, sub {
4655 my $conf = load_config
($vmid);
4657 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4659 vm_mon_cmd
($vmid, "cont");
4662 vm_mon_cmd_nocheck
($vmid, "cont");
4668 my ($vmid, $skiplock, $key) = @_;
4670 lock_config
($vmid, sub {
4672 my $conf = load_config
($vmid);
4674 # there is no qmp command, so we use the human monitor command
4675 vm_human_monitor_command
($vmid, "sendkey $key");
4680 my ($storecfg, $vmid, $skiplock) = @_;
4682 lock_config
($vmid, sub {
4684 my $conf = load_config
($vmid);
4686 check_lock
($conf) if !$skiplock;
4688 if (!check_running
($vmid)) {
4689 destroy_vm
($storecfg, $vmid);
4691 die "VM $vmid is running - destroy failed\n";
4699 my ($filename, $buf) = @_;
4701 my $fh = IO
::File-
>new($filename, "w");
4702 return undef if !$fh;
4704 my $res = print $fh $buf;
4711 sub pci_device_info
{
4716 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4717 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4719 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4720 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4722 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4723 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4725 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4726 return undef if !defined($product) || $product !~ s/^0x//;
4731 product
=> $product,
4737 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4746 my $name = $dev->{name
};
4748 my $fn = "$pcisysfs/devices/$name/reset";
4750 return file_write
($fn, "1");
4753 sub pci_dev_bind_to_vfio
{
4756 my $name = $dev->{name
};
4758 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4760 if (!-d
$vfio_basedir) {
4761 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4763 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4765 my $testdir = "$vfio_basedir/$name";
4766 return 1 if -d
$testdir;
4768 my $data = "$dev->{vendor} $dev->{product}";
4769 return undef if !file_write
("$vfio_basedir/new_id", $data);
4771 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4772 if (!file_write
($fn, $name)) {
4773 return undef if -f
$fn;
4776 $fn = "$vfio_basedir/bind";
4777 if (! -d
$testdir) {
4778 return undef if !file_write
($fn, $name);
4784 sub pci_dev_group_bind_to_vfio
{
4787 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4789 if (!-d
$vfio_basedir) {
4790 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4792 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4794 # get IOMMU group devices
4795 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4796 my @devs = grep /^0000:/, readdir($D);
4799 foreach my $pciid (@devs) {
4800 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4802 # pci bridges, switches or root ports are not supported
4803 # they have a pci_bus subdirectory so skip them
4804 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4806 my $info = pci_device_info
($1);
4807 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4813 sub print_pci_addr
{
4814 my ($id, $bridges) = @_;
4818 piix3
=> { bus
=> 0, addr
=> 1 },
4819 #addr2 : first videocard
4820 balloon0
=> { bus
=> 0, addr
=> 3 },
4821 watchdog
=> { bus
=> 0, addr
=> 4 },
4822 scsihw0
=> { bus
=> 0, addr
=> 5 },
4823 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4824 scsihw1
=> { bus
=> 0, addr
=> 6 },
4825 ahci0
=> { bus
=> 0, addr
=> 7 },
4826 qga0
=> { bus
=> 0, addr
=> 8 },
4827 spice
=> { bus
=> 0, addr
=> 9 },
4828 virtio0
=> { bus
=> 0, addr
=> 10 },
4829 virtio1
=> { bus
=> 0, addr
=> 11 },
4830 virtio2
=> { bus
=> 0, addr
=> 12 },
4831 virtio3
=> { bus
=> 0, addr
=> 13 },
4832 virtio4
=> { bus
=> 0, addr
=> 14 },
4833 virtio5
=> { bus
=> 0, addr
=> 15 },
4834 hostpci0
=> { bus
=> 0, addr
=> 16 },
4835 hostpci1
=> { bus
=> 0, addr
=> 17 },
4836 net0
=> { bus
=> 0, addr
=> 18 },
4837 net1
=> { bus
=> 0, addr
=> 19 },
4838 net2
=> { bus
=> 0, addr
=> 20 },
4839 net3
=> { bus
=> 0, addr
=> 21 },
4840 net4
=> { bus
=> 0, addr
=> 22 },
4841 net5
=> { bus
=> 0, addr
=> 23 },
4842 vga1
=> { bus
=> 0, addr
=> 24 },
4843 vga2
=> { bus
=> 0, addr
=> 25 },
4844 vga3
=> { bus
=> 0, addr
=> 26 },
4845 hostpci2
=> { bus
=> 0, addr
=> 27 },
4846 hostpci3
=> { bus
=> 0, addr
=> 28 },
4847 #addr29 : usb-host (pve-usb.cfg)
4848 'pci.1' => { bus
=> 0, addr
=> 30 },
4849 'pci.2' => { bus
=> 0, addr
=> 31 },
4850 'net6' => { bus
=> 1, addr
=> 1 },
4851 'net7' => { bus
=> 1, addr
=> 2 },
4852 'net8' => { bus
=> 1, addr
=> 3 },
4853 'net9' => { bus
=> 1, addr
=> 4 },
4854 'net10' => { bus
=> 1, addr
=> 5 },
4855 'net11' => { bus
=> 1, addr
=> 6 },
4856 'net12' => { bus
=> 1, addr
=> 7 },
4857 'net13' => { bus
=> 1, addr
=> 8 },
4858 'net14' => { bus
=> 1, addr
=> 9 },
4859 'net15' => { bus
=> 1, addr
=> 10 },
4860 'net16' => { bus
=> 1, addr
=> 11 },
4861 'net17' => { bus
=> 1, addr
=> 12 },
4862 'net18' => { bus
=> 1, addr
=> 13 },
4863 'net19' => { bus
=> 1, addr
=> 14 },
4864 'net20' => { bus
=> 1, addr
=> 15 },
4865 'net21' => { bus
=> 1, addr
=> 16 },
4866 'net22' => { bus
=> 1, addr
=> 17 },
4867 'net23' => { bus
=> 1, addr
=> 18 },
4868 'net24' => { bus
=> 1, addr
=> 19 },
4869 'net25' => { bus
=> 1, addr
=> 20 },
4870 'net26' => { bus
=> 1, addr
=> 21 },
4871 'net27' => { bus
=> 1, addr
=> 22 },
4872 'net28' => { bus
=> 1, addr
=> 23 },
4873 'net29' => { bus
=> 1, addr
=> 24 },
4874 'net30' => { bus
=> 1, addr
=> 25 },
4875 'net31' => { bus
=> 1, addr
=> 26 },
4876 'virtio6' => { bus
=> 2, addr
=> 1 },
4877 'virtio7' => { bus
=> 2, addr
=> 2 },
4878 'virtio8' => { bus
=> 2, addr
=> 3 },
4879 'virtio9' => { bus
=> 2, addr
=> 4 },
4880 'virtio10' => { bus
=> 2, addr
=> 5 },
4881 'virtio11' => { bus
=> 2, addr
=> 6 },
4882 'virtio12' => { bus
=> 2, addr
=> 7 },
4883 'virtio13' => { bus
=> 2, addr
=> 8 },
4884 'virtio14' => { bus
=> 2, addr
=> 9 },
4885 'virtio15' => { bus
=> 2, addr
=> 10 },
4886 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4887 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4888 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4889 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4890 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4891 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4892 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4893 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4894 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4895 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4896 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4897 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4898 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4899 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4900 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4901 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4902 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4903 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4904 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4905 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4906 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4907 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4908 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4909 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4910 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4911 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4912 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4913 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4914 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4915 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4916 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4920 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4921 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4922 my $bus = $devices->{$id}->{bus
};
4923 $res = ",bus=pci.$bus,addr=$addr";
4924 $bridges->{$bus} = 1 if $bridges;
4930 sub print_pcie_addr
{
4935 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4936 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4937 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4938 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4941 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4942 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4943 my $bus = $devices->{$id}->{bus
};
4944 $res = ",bus=$bus,addr=$addr";
4950 # vzdump restore implementaion
4952 sub tar_archive_read_firstfile
{
4953 my $archive = shift;
4955 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4957 # try to detect archive type first
4958 my $pid = open (TMP
, "tar tf '$archive'|") ||
4959 die "unable to open file '$archive'\n";
4960 my $firstfile = <TMP
>;
4964 die "ERROR: archive contaions no data\n" if !$firstfile;
4970 sub tar_restore_cleanup
{
4971 my ($storecfg, $statfile) = @_;
4973 print STDERR
"starting cleanup\n";
4975 if (my $fd = IO
::File-
>new($statfile, "r")) {
4976 while (defined(my $line = <$fd>)) {
4977 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4980 if ($volid =~ m
|^/|) {
4981 unlink $volid || die 'unlink failed\n';
4983 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4985 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4987 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4989 print STDERR
"unable to parse line in statfile - $line";
4996 sub restore_archive
{
4997 my ($archive, $vmid, $user, $opts) = @_;
4999 my $format = $opts->{format
};
5002 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5003 $format = 'tar' if !$format;
5005 } elsif ($archive =~ m/\.tar$/) {
5006 $format = 'tar' if !$format;
5007 } elsif ($archive =~ m/.tar.lzo$/) {
5008 $format = 'tar' if !$format;
5010 } elsif ($archive =~ m/\.vma$/) {
5011 $format = 'vma' if !$format;
5012 } elsif ($archive =~ m/\.vma\.gz$/) {
5013 $format = 'vma' if !$format;
5015 } elsif ($archive =~ m/\.vma\.lzo$/) {
5016 $format = 'vma' if !$format;
5019 $format = 'vma' if !$format; # default
5022 # try to detect archive format
5023 if ($format eq 'tar') {
5024 return restore_tar_archive
($archive, $vmid, $user, $opts);
5026 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5030 sub restore_update_config_line
{
5031 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5033 return if $line =~ m/^\#qmdump\#/;
5034 return if $line =~ m/^\#vzdump\#/;
5035 return if $line =~ m/^lock:/;
5036 return if $line =~ m/^unused\d+:/;
5037 return if $line =~ m/^parent:/;
5038 return if $line =~ m/^template:/; # restored VM is never a template
5040 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5041 # try to convert old 1.X settings
5042 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5043 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5044 my ($model, $macaddr) = split(/\=/, $devconfig);
5045 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5048 bridge
=> "vmbr$ind",
5049 macaddr
=> $macaddr,
5051 my $netstr = print_net
($net);
5053 print $outfd "net$cookie->{netcount}: $netstr\n";
5054 $cookie->{netcount
}++;
5056 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5057 my ($id, $netstr) = ($1, $2);
5058 my $net = parse_net
($netstr);
5059 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5060 $netstr = print_net
($net);
5061 print $outfd "$id: $netstr\n";
5062 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5065 if ($line =~ m/backup=no/) {
5066 print $outfd "#$line";
5067 } elsif ($virtdev && $map->{$virtdev}) {
5068 my $di = parse_drive
($virtdev, $value);
5069 delete $di->{format
}; # format can change on restore
5070 $di->{file
} = $map->{$virtdev};
5071 $value = print_drive
($vmid, $di);
5072 print $outfd "$virtdev: $value\n";
5082 my ($cfg, $vmid) = @_;
5084 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5086 my $volid_hash = {};
5087 foreach my $storeid (keys %$info) {
5088 foreach my $item (@{$info->{$storeid}}) {
5089 next if !($item->{volid
} && $item->{size
});
5090 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5091 $volid_hash->{$item->{volid
}} = $item;
5098 sub get_used_paths
{
5099 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5103 my $scan_config = sub {
5104 my ($cref, $snapname) = @_;
5106 foreach my $key (keys %$cref) {
5107 my $value = $cref->{$key};
5108 if (valid_drivename
($key)) {
5109 next if $skip_drive && $key eq $skip_drive;
5110 my $drive = parse_drive
($key, $value);
5111 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5112 if ($drive->{file
} =~ m!^/!) {
5113 $used_path->{$drive->{file
}}++; # = 1;
5115 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5117 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5119 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5120 $used_path->{$path}++; # = 1;
5126 &$scan_config($conf);
5130 if ($scan_snapshots) {
5131 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5132 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5139 sub update_disksize
{
5140 my ($vmid, $conf, $volid_hash) = @_;
5146 # Note: it is allowed to define multiple storages with same path (alias), so
5147 # we need to check both 'volid' and real 'path' (two different volid can point
5148 # to the same path).
5153 foreach my $opt (keys %$conf) {
5154 if (valid_drivename
($opt)) {
5155 my $drive = parse_drive
($opt, $conf->{$opt});
5156 my $volid = $drive->{file
};
5159 $used->{$volid} = 1;
5160 if ($volid_hash->{$volid} &&
5161 (my $path = $volid_hash->{$volid}->{path
})) {
5162 $usedpath->{$path} = 1;
5165 next if drive_is_cdrom
($drive);
5166 next if !$volid_hash->{$volid};
5168 $drive->{size
} = $volid_hash->{$volid}->{size
};
5169 my $new = print_drive
($vmid, $drive);
5170 if ($new ne $conf->{$opt}) {
5172 $conf->{$opt} = $new;
5177 # remove 'unusedX' entry if volume is used
5178 foreach my $opt (keys %$conf) {
5179 next if $opt !~ m/^unused\d+$/;
5180 my $volid = $conf->{$opt};
5181 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5182 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5184 delete $conf->{$opt};
5188 foreach my $volid (sort keys %$volid_hash) {
5189 next if $volid =~ m/vm-$vmid-state-/;
5190 next if $used->{$volid};
5191 my $path = $volid_hash->{$volid}->{path
};
5192 next if !$path; # just to be sure
5193 next if $usedpath->{$path};
5195 add_unused_volume
($conf, $volid);
5196 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5203 my ($vmid, $nolock) = @_;
5205 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5207 my $volid_hash = scan_volids
($cfg, $vmid);
5209 my $updatefn = sub {
5212 my $conf = load_config
($vmid);
5217 foreach my $volid (keys %$volid_hash) {
5218 my $info = $volid_hash->{$volid};
5219 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5222 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5224 update_config_nolock
($vmid, $conf, 1) if $changes;
5227 if (defined($vmid)) {
5231 lock_config
($vmid, $updatefn, $vmid);
5234 my $vmlist = config_list
();
5235 foreach my $vmid (keys %$vmlist) {
5239 lock_config
($vmid, $updatefn, $vmid);
5245 sub restore_vma_archive
{
5246 my ($archive, $vmid, $user, $opts, $comp) = @_;
5248 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5249 my $readfrom = $archive;
5254 my $qarchive = PVE
::Tools
::shellquote
($archive);
5255 if ($comp eq 'gzip') {
5256 $uncomp = "zcat $qarchive|";
5257 } elsif ($comp eq 'lzop') {
5258 $uncomp = "lzop -d -c $qarchive|";
5260 die "unknown compression method '$comp'\n";
5265 my $tmpdir = "/var/tmp/vzdumptmp$$";
5268 # disable interrupts (always do cleanups)
5269 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5270 warn "got interrupt - ignored\n";
5273 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5274 POSIX
::mkfifo
($mapfifo, 0600);
5277 my $openfifo = sub {
5278 open($fifofh, '>', $mapfifo) || die $!;
5281 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5288 my $rpcenv = PVE
::RPCEnvironment
::get
();
5290 my $conffile = config_file
($vmid);
5291 my $tmpfn = "$conffile.$$.tmp";
5293 # Note: $oldconf is undef if VM does not exists
5294 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5296 my $print_devmap = sub {
5297 my $virtdev_hash = {};
5299 my $cfgfn = "$tmpdir/qemu-server.conf";
5301 # we can read the config - that is already extracted
5302 my $fh = IO
::File-
>new($cfgfn, "r") ||
5303 "unable to read qemu-server.conf - $!\n";
5305 while (defined(my $line = <$fh>)) {
5306 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5307 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5308 die "archive does not contain data for drive '$virtdev'\n"
5309 if !$devinfo->{$devname};
5310 if (defined($opts->{storage
})) {
5311 $storeid = $opts->{storage
} || 'local';
5312 } elsif (!$storeid) {
5315 $format = 'raw' if !$format;
5316 $devinfo->{$devname}->{devname
} = $devname;
5317 $devinfo->{$devname}->{virtdev
} = $virtdev;
5318 $devinfo->{$devname}->{format
} = $format;
5319 $devinfo->{$devname}->{storeid
} = $storeid;
5321 # check permission on storage
5322 my $pool = $opts->{pool
}; # todo: do we need that?
5323 if ($user ne 'root@pam') {
5324 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5327 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5331 foreach my $devname (keys %$devinfo) {
5332 die "found no device mapping information for device '$devname'\n"
5333 if !$devinfo->{$devname}->{virtdev
};
5336 my $cfg = cfs_read_file
('storage.cfg');
5338 # create empty/temp config
5340 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5341 foreach_drive
($oldconf, sub {
5342 my ($ds, $drive) = @_;
5344 return if drive_is_cdrom
($drive);
5346 my $volid = $drive->{file
};
5348 return if !$volid || $volid =~ m
|^/|;
5350 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5351 return if !$path || !$owner || ($owner != $vmid);
5353 # Note: only delete disk we want to restore
5354 # other volumes will become unused
5355 if ($virtdev_hash->{$ds}) {
5356 PVE
::Storage
::vdisk_free
($cfg, $volid);
5362 foreach my $virtdev (sort keys %$virtdev_hash) {
5363 my $d = $virtdev_hash->{$virtdev};
5364 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5365 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5367 # test if requested format is supported
5368 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5369 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5370 $d->{format
} = $defFormat if !$supported;
5372 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5373 $d->{format
}, undef, $alloc_size);
5374 print STDERR
"new volume ID is '$volid'\n";
5375 $d->{volid
} = $volid;
5376 my $path = PVE
::Storage
::path
($cfg, $volid);
5378 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5380 my $write_zeros = 1;
5381 # fixme: what other storages types initialize volumes with zero?
5382 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5383 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5387 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5389 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5390 $map->{$virtdev} = $volid;
5393 $fh->seek(0, 0) || die "seek failed - $!\n";
5395 my $outfd = new IO
::File
($tmpfn, "w") ||
5396 die "unable to write config for VM $vmid\n";
5398 my $cookie = { netcount
=> 0 };
5399 while (defined(my $line = <$fh>)) {
5400 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5409 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5410 die "interrupted by signal\n";
5412 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5414 $oldtimeout = alarm($timeout);
5421 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5422 my ($dev_id, $size, $devname) = ($1, $2, $3);
5423 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5424 } elsif ($line =~ m/^CTIME: /) {
5425 # we correctly received the vma config, so we can disable
5426 # the timeout now for disk allocation (set to 10 minutes, so
5427 # that we always timeout if something goes wrong)
5430 print $fifofh "done\n";
5431 my $tmp = $oldtimeout || 0;
5432 $oldtimeout = undef;
5438 print "restore vma archive: $cmd\n";
5439 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5443 alarm($oldtimeout) if $oldtimeout;
5446 foreach my $devname (keys %$devinfo) {
5447 my $volid = $devinfo->{$devname}->{volid
};
5448 push @$vollist, $volid if $volid;
5451 my $cfg = cfs_read_file
('storage.cfg');
5452 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5460 foreach my $devname (keys %$devinfo) {
5461 my $volid = $devinfo->{$devname}->{volid
};
5464 if ($volid =~ m
|^/|) {
5465 unlink $volid || die 'unlink failed\n';
5467 PVE
::Storage
::vdisk_free
($cfg, $volid);
5469 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5471 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5478 rename($tmpfn, $conffile) ||
5479 die "unable to commit configuration file '$conffile'\n";
5481 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5483 eval { rescan
($vmid, 1); };
5487 sub restore_tar_archive
{
5488 my ($archive, $vmid, $user, $opts) = @_;
5490 if ($archive ne '-') {
5491 my $firstfile = tar_archive_read_firstfile
($archive);
5492 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5493 if $firstfile ne 'qemu-server.conf';
5496 my $storecfg = cfs_read_file
('storage.cfg');
5498 # destroy existing data - keep empty config
5499 my $vmcfgfn = config_file
($vmid);
5500 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5502 my $tocmd = "/usr/lib/qemu-server/qmextract";
5504 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5505 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5506 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5507 $tocmd .= ' --info' if $opts->{info
};
5509 # tar option "xf" does not autodetect compression when read from STDIN,
5510 # so we pipe to zcat
5511 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5512 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5514 my $tmpdir = "/var/tmp/vzdumptmp$$";
5517 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5518 local $ENV{VZDUMP_VMID
} = $vmid;
5519 local $ENV{VZDUMP_USER
} = $user;
5521 my $conffile = config_file
($vmid);
5522 my $tmpfn = "$conffile.$$.tmp";
5524 # disable interrupts (always do cleanups)
5525 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5526 print STDERR
"got interrupt - ignored\n";
5531 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5532 die "interrupted by signal\n";
5535 if ($archive eq '-') {
5536 print "extracting archive from STDIN\n";
5537 run_command
($cmd, input
=> "<&STDIN");
5539 print "extracting archive '$archive'\n";
5543 return if $opts->{info
};
5547 my $statfile = "$tmpdir/qmrestore.stat";
5548 if (my $fd = IO
::File-
>new($statfile, "r")) {
5549 while (defined (my $line = <$fd>)) {
5550 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5551 $map->{$1} = $2 if $1;
5553 print STDERR
"unable to parse line in statfile - $line\n";
5559 my $confsrc = "$tmpdir/qemu-server.conf";
5561 my $srcfd = new IO
::File
($confsrc, "r") ||
5562 die "unable to open file '$confsrc'\n";
5564 my $outfd = new IO
::File
($tmpfn, "w") ||
5565 die "unable to write config for VM $vmid\n";
5567 my $cookie = { netcount
=> 0 };
5568 while (defined (my $line = <$srcfd>)) {
5569 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5581 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5588 rename $tmpfn, $conffile ||
5589 die "unable to commit configuration file '$conffile'\n";
5591 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5593 eval { rescan
($vmid, 1); };
5598 # Internal snapshots
5600 # NOTE: Snapshot create/delete involves several non-atomic
5601 # action, and can take a long time.
5602 # So we try to avoid locking the file and use 'lock' variable
5603 # inside the config file instead.
5605 my $snapshot_copy_config = sub {
5606 my ($source, $dest) = @_;
5608 foreach my $k (keys %$source) {
5609 next if $k eq 'snapshots';
5610 next if $k eq 'snapstate';
5611 next if $k eq 'snaptime';
5612 next if $k eq 'vmstate';
5613 next if $k eq 'lock';
5614 next if $k eq 'digest';
5615 next if $k eq 'description';
5616 next if $k =~ m/^unused\d+$/;
5618 $dest->{$k} = $source->{$k};
5622 my $snapshot_apply_config = sub {
5623 my ($conf, $snap) = @_;
5625 # copy snapshot list
5627 snapshots
=> $conf->{snapshots
},
5630 # keep description and list of unused disks
5631 foreach my $k (keys %$conf) {
5632 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5633 $newconf->{$k} = $conf->{$k};
5636 &$snapshot_copy_config($snap, $newconf);
5641 sub foreach_writable_storage
{
5642 my ($conf, $func) = @_;
5646 foreach my $ds (keys %$conf) {
5647 next if !valid_drivename
($ds);
5649 my $drive = parse_drive
($ds, $conf->{$ds});
5651 next if drive_is_cdrom
($drive);
5653 my $volid = $drive->{file
};
5655 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5656 $sidhash->{$sid} = $sid if $sid;
5659 foreach my $sid (sort keys %$sidhash) {
5664 my $alloc_vmstate_volid = sub {
5665 my ($storecfg, $vmid, $conf, $snapname) = @_;
5667 # Note: we try to be smart when selecting a $target storage
5671 # search shared storage first
5672 foreach_writable_storage
($conf, sub {
5674 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5675 return if !$scfg->{shared
};
5677 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5681 # now search local storage
5682 foreach_writable_storage
($conf, sub {
5684 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5685 return if $scfg->{shared
};
5687 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5691 $target = 'local' if !$target;
5693 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5694 # we abort live save after $conf->{memory}, so we need at max twice that space
5695 my $size = $conf->{memory
}*2 + $driver_state_size;
5697 my $name = "vm-$vmid-state-$snapname";
5698 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5699 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5700 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5705 my $snapshot_prepare = sub {
5706 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5710 my $updatefn = sub {
5712 my $conf = load_config
($vmid);
5714 die "you can't take a snapshot if it's a template\n"
5715 if is_template
($conf);
5719 $conf->{lock} = 'snapshot';
5721 die "snapshot name '$snapname' already used\n"
5722 if defined($conf->{snapshots
}->{$snapname});
5724 my $storecfg = PVE
::Storage
::config
();
5725 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5727 $snap = $conf->{snapshots
}->{$snapname} = {};
5729 if ($save_vmstate && check_running
($vmid)) {
5730 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5733 &$snapshot_copy_config($conf, $snap);
5735 $snap->{snapstate
} = "prepare";
5736 $snap->{snaptime
} = time();
5737 $snap->{description
} = $comment if $comment;
5739 # always overwrite machine if we save vmstate. This makes sure we
5740 # can restore it later using correct machine type
5741 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5743 update_config_nolock
($vmid, $conf, 1);
5746 lock_config
($vmid, $updatefn);
5751 my $snapshot_commit = sub {
5752 my ($vmid, $snapname) = @_;
5754 my $updatefn = sub {
5756 my $conf = load_config
($vmid);
5758 die "missing snapshot lock\n"
5759 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5761 my $has_machine_config = defined($conf->{machine
});
5763 my $snap = $conf->{snapshots
}->{$snapname};
5765 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5767 die "wrong snapshot state\n"
5768 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5770 delete $snap->{snapstate
};
5771 delete $conf->{lock};
5773 my $newconf = &$snapshot_apply_config($conf, $snap);
5775 delete $newconf->{machine
} if !$has_machine_config;
5777 $newconf->{parent
} = $snapname;
5779 update_config_nolock
($vmid, $newconf, 1);
5782 lock_config
($vmid, $updatefn);
5785 sub snapshot_rollback
{
5786 my ($vmid, $snapname) = @_;
5790 my $storecfg = PVE
::Storage
::config
();
5792 my $conf = load_config
($vmid);
5794 my $get_snapshot_config = sub {
5796 die "you can't rollback if vm is a template\n" if is_template
($conf);
5798 my $res = $conf->{snapshots
}->{$snapname};
5800 die "snapshot '$snapname' does not exist\n" if !defined($res);
5805 my $snap = &$get_snapshot_config();
5807 foreach_drive
($snap, sub {
5808 my ($ds, $drive) = @_;
5810 return if drive_is_cdrom
($drive);
5812 my $volid = $drive->{file
};
5814 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5817 my $updatefn = sub {
5819 $conf = load_config
($vmid);
5821 $snap = &$get_snapshot_config();
5823 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5824 if $snap->{snapstate
};
5828 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5831 die "unable to rollback vm $vmid: vm is running\n"
5832 if check_running
($vmid);
5835 $conf->{lock} = 'rollback';
5837 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5838 delete $conf->{lock};
5844 my $has_machine_config = defined($conf->{machine
});
5846 # copy snapshot config to current config
5847 $conf = &$snapshot_apply_config($conf, $snap);
5848 $conf->{parent
} = $snapname;
5850 # Note: old code did not store 'machine', so we try to be smart
5851 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5852 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5853 # we remove the 'machine' configuration if not explicitly specified
5854 # in the original config.
5855 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5858 update_config_nolock
($vmid, $conf, 1);
5860 if (!$prepare && $snap->{vmstate
}) {
5861 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5862 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5866 lock_config
($vmid, $updatefn);
5868 foreach_drive
($snap, sub {
5869 my ($ds, $drive) = @_;
5871 return if drive_is_cdrom
($drive);
5873 my $volid = $drive->{file
};
5874 my $device = "drive-$ds";
5876 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5880 lock_config
($vmid, $updatefn);
5883 my $savevm_wait = sub {
5887 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5888 if (!$stat->{status
}) {
5889 die "savevm not active\n";
5890 } elsif ($stat->{status
} eq 'active') {
5893 } elsif ($stat->{status
} eq 'completed') {
5896 die "query-savevm returned status '$stat->{status}'\n";
5901 sub do_snapshots_with_qemu
{
5902 my ($storecfg, $volid) = @_;
5904 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5906 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5907 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5911 if ($volid =~ m/\.(qcow2|qed)$/){
5918 sub snapshot_create
{
5919 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5921 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5923 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5925 my $config = load_config
($vmid);
5927 my $running = check_running
($vmid);
5929 my $freezefs = $running && $config->{agent
};
5930 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5935 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5936 warn "guest-fsfreeze-freeze problems - $@" if $@;
5940 # create internal snapshots of all drives
5942 my $storecfg = PVE
::Storage
::config
();
5945 if ($snap->{vmstate
}) {
5946 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5947 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5948 &$savevm_wait($vmid);
5950 vm_mon_cmd
($vmid, "savevm-start");
5954 foreach_drive
($snap, sub {
5955 my ($ds, $drive) = @_;
5957 return if drive_is_cdrom
($drive);
5959 my $volid = $drive->{file
};
5960 my $device = "drive-$ds";
5962 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5963 $drivehash->{$ds} = 1;
5969 eval { vm_mon_cmd
($vmid, "savevm-end") };
5973 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5974 warn "guest-fsfreeze-thaw problems - $@" if $@;
5977 # savevm-end is async, we need to wait
5979 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5980 if (!$stat->{bytes
}) {
5983 print "savevm not yet finished\n";
5991 warn "snapshot create failed: starting cleanup\n";
5992 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5997 &$snapshot_commit($vmid, $snapname);
6000 # Note: $drivehash is only set when called from snapshot_create.
6001 sub snapshot_delete
{
6002 my ($vmid, $snapname, $force, $drivehash) = @_;
6009 my $unlink_parent = sub {
6010 my ($confref, $new_parent) = @_;
6012 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6014 $confref->{parent
} = $new_parent;
6016 delete $confref->{parent
};
6021 my $updatefn = sub {
6022 my ($remove_drive) = @_;
6024 my $conf = load_config
($vmid);
6028 die "you can't delete a snapshot if vm is a template\n"
6029 if is_template
($conf);
6032 $snap = $conf->{snapshots
}->{$snapname};
6034 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6036 # remove parent refs
6038 &$unlink_parent($conf, $snap->{parent
});
6039 foreach my $sn (keys %{$conf->{snapshots
}}) {
6040 next if $sn eq $snapname;
6041 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6045 if ($remove_drive) {
6046 if ($remove_drive eq 'vmstate') {
6047 delete $snap->{$remove_drive};
6049 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6050 my $volid = $drive->{file
};
6051 delete $snap->{$remove_drive};
6052 add_unused_volume
($conf, $volid);
6057 $snap->{snapstate
} = 'delete';
6059 delete $conf->{snapshots
}->{$snapname};
6060 delete $conf->{lock} if $drivehash;
6061 foreach my $volid (@$unused) {
6062 add_unused_volume
($conf, $volid);
6066 update_config_nolock
($vmid, $conf, 1);
6069 lock_config
($vmid, $updatefn);
6071 # now remove vmstate file
6073 my $storecfg = PVE
::Storage
::config
();
6075 if ($snap->{vmstate
}) {
6076 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6078 die $err if !$force;
6081 # save changes (remove vmstate from snapshot)
6082 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6085 # now remove all internal snapshots
6086 foreach_drive
($snap, sub {
6087 my ($ds, $drive) = @_;
6089 return if drive_is_cdrom
($drive);
6091 my $volid = $drive->{file
};
6092 my $device = "drive-$ds";
6094 if (!$drivehash || $drivehash->{$ds}) {
6095 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6097 die $err if !$force;
6102 # save changes (remove drive fron snapshot)
6103 lock_config
($vmid, $updatefn, $ds) if !$force;
6104 push @$unused, $volid;
6107 # now cleanup config
6109 lock_config
($vmid, $updatefn);
6113 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6116 foreach_drive
($conf, sub {
6117 my ($ds, $drive) = @_;
6119 return if drive_is_cdrom
($drive);
6120 my $volid = $drive->{file
};
6121 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6124 return $err ?
0 : 1;
6127 sub template_create
{
6128 my ($vmid, $conf, $disk) = @_;
6130 my $storecfg = PVE
::Storage
::config
();
6132 foreach_drive
($conf, sub {
6133 my ($ds, $drive) = @_;
6135 return if drive_is_cdrom
($drive);
6136 return if $disk && $ds ne $disk;
6138 my $volid = $drive->{file
};
6139 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6141 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6142 $drive->{file
} = $voliddst;
6143 $conf->{$ds} = print_drive
($vmid, $drive);
6144 update_config_nolock
($vmid, $conf, 1);
6151 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6154 sub qemu_img_convert
{
6155 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6157 my $storecfg = PVE
::Storage
::config
();
6158 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6159 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6161 if ($src_storeid && $dst_storeid) {
6163 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6165 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6166 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6168 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6169 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6171 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6172 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6175 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6176 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6177 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6181 if($line =~ m/\((\S+)\/100\
%\)/){
6183 my $transferred = int($size * $percent / 100);
6184 my $remaining = $size - $transferred;
6186 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6191 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6193 die "copy failed: $err" if $err;
6197 sub qemu_img_format
{
6198 my ($scfg, $volname) = @_;
6200 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6207 sub qemu_drive_mirror
{
6208 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6210 my $storecfg = PVE
::Storage
::config
();
6211 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6213 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6215 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6217 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6219 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6220 $opts->{format
} = $format if $format;
6222 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6225 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6227 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6228 my $stat = @$stats[0];
6229 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6230 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6232 my $busy = $stat->{busy
};
6233 my $ready = $stat->{ready
};
6235 if (my $total = $stat->{len
}) {
6236 my $transferred = $stat->{offset
} || 0;
6237 my $remaining = $total - $transferred;
6238 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6240 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6244 if ($stat->{ready
} eq 'true') {
6246 last if $vmiddst != $vmid;
6248 # try to switch the disk if source and destination are on the same guest
6249 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6251 die $@ if $@ !~ m/cannot be completed/;
6260 my $cancel_job = sub {
6261 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6263 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6264 my $stat = @$stats[0];
6271 eval { &$cancel_job(); };
6272 die "mirroring error: $err";
6275 if ($vmiddst != $vmid) {
6276 # if we clone a disk for a new target vm, we don't switch the disk
6277 &$cancel_job(); # so we call block-job-cancel
6282 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6283 $newvmid, $storage, $format, $full, $newvollist) = @_;
6288 print "create linked clone of drive $drivename ($drive->{file})\n";
6289 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6290 push @$newvollist, $newvolid;
6292 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6293 $storeid = $storage if $storage;
6295 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6297 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6298 $format = qemu_img_format
($scfg, $volname);
6301 # test if requested format is supported - else use default
6302 my $supported = grep { $_ eq $format } @$validFormats;
6303 $format = $defFormat if !$supported;
6305 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6307 print "create full clone of drive $drivename ($drive->{file})\n";
6308 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6309 push @$newvollist, $newvolid;
6311 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6313 if (!$running || $snapname) {
6314 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6316 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6320 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6323 $disk->{format
} = undef;
6324 $disk->{file
} = $newvolid;
6325 $disk->{size
} = $size;
6330 # this only works if VM is running
6331 sub get_current_qemu_machine
{
6334 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6335 my $res = vm_qmp_command
($vmid, $cmd);
6337 my ($current, $default);
6338 foreach my $e (@$res) {
6339 $default = $e->{name
} if $e->{'is-default'};
6340 $current = $e->{name
} if $e->{'is-current'};
6343 # fallback to the default machine if current is not supported by qemu
6344 return $current || $default || 'pc';
6347 sub qemu_machine_feature_enabled
{
6348 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6353 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6355 $current_major = $3;
6356 $current_minor = $4;
6358 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6360 $current_major = $1;
6361 $current_minor = $2;
6364 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6369 sub qemu_machine_pxe
{
6370 my ($vmid, $conf, $machine) = @_;
6372 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6374 foreach my $opt (keys %$conf) {
6375 next if $opt !~ m/^net(\d+)$/;
6376 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6378 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6379 return $machine.".pxe" if $romfile =~ m/pxe/;
6385 sub qemu_use_old_bios_files
{
6386 my ($machine_type) = @_;
6388 return if !$machine_type;
6390 my $use_old_bios_files = undef;
6392 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6394 $use_old_bios_files = 1;
6396 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6397 # load new efi bios files on migration. So this hack is required to allow
6398 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6399 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6400 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6403 return ($use_old_bios_files, $machine_type);
6410 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6411 my (undef, $id, $function) = @_;
6412 my $res = { id
=> $id, function
=> $function};
6413 push @{$devices->{$id}}, $res;
6419 sub vm_iothreads_list
{
6422 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6425 foreach my $iothread (@$res) {
6426 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6433 my ($conf, $drive) = @_;
6437 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6439 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6445 my $controller = int($drive->{index} / $maxdev);
6446 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6448 return ($maxdev, $controller, $controller_prefix);
6451 # bash completion helper
6453 sub complete_backup_archives
{
6454 my ($cmdname, $pname, $cvalue) = @_;
6456 my $cfg = PVE
::Storage
::config
();
6460 if ($cvalue =~ m/^([^:]+):/) {
6464 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6467 foreach my $id (keys %$data) {
6468 foreach my $item (@{$data->{$id}}) {
6469 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6470 push @$res, $item->{volid
} if defined($item->{volid
});
6477 my $complete_vmid_full = sub {
6480 my $idlist = vmstatus
();
6484 foreach my $id (keys %$idlist) {
6485 my $d = $idlist->{$id};
6486 if (defined($running)) {
6487 next if $d->{template
};
6488 next if $running && $d->{status
} ne 'running';
6489 next if !$running && $d->{status
} eq 'running';
6498 return &$complete_vmid_full();
6501 sub complete_vmid_stopped
{
6502 return &$complete_vmid_full(0);
6505 sub complete_vmid_running
{
6506 return &$complete_vmid_full(1);
6509 sub complete_storage
{
6511 my $cfg = PVE
::Storage
::config
();
6512 my $ids = $cfg->{ids
};
6515 foreach my $sid (keys %$ids) {
6516 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6517 next if !$ids->{$sid}->{content
}->{images
};