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 push @$cmd, '-p', "CPUShares=$cpuunits";
2660 if ($conf->{cpulimit
}) {
2661 my $cpulimit = int($conf->{cpulimit
} * 100);
2662 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2665 push @$cmd, '/usr/bin/kvm';
2667 push @$cmd, '-id', $vmid;
2671 my $qmpsocket = qmp_socket
($vmid);
2672 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2673 push @$cmd, '-mon', "chardev=qmp,mode=control";
2675 my $socket = vnc_socket
($vmid);
2676 push @$cmd, '-vnc', "unix:$socket,x509,password";
2678 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2680 push @$cmd, '-daemonize';
2682 if ($conf->{smbios1
}) {
2683 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2687 # the q35 chipset support native usb2, so we enable usb controller
2688 # by default for this machine type
2689 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2691 $pciaddr = print_pci_addr
("piix3", $bridges);
2692 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2695 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2696 next if !$conf->{"usb$i"};
2699 # include usb device config
2700 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2703 my $vga = $conf->{vga
};
2705 my $qxlnum = vga_conf_has_spice
($vga);
2706 $vga = 'qxl' if $qxlnum;
2709 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2710 $conf->{ostype
} eq 'win7' ||
2711 $conf->{ostype
} eq 'w2k8')) {
2718 # enable absolute mouse coordinates (needed by vnc)
2720 if (defined($conf->{tablet
})) {
2721 $tablet = $conf->{tablet
};
2723 $tablet = $defaults->{tablet
};
2724 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2725 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2728 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2731 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2732 my $d = parse_hostpci
($conf->{"hostpci$i"});
2735 my $pcie = $d->{pcie
};
2737 die "q35 machine model is not enabled" if !$q35;
2738 $pciaddr = print_pcie_addr
("hostpci$i");
2740 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2743 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2744 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2745 if ($xvga && $xvga ne '') {
2746 push @$cpuFlags, 'kvm=off';
2749 my $pcidevices = $d->{pciid
};
2750 my $multifunction = 1 if @$pcidevices > 1;
2753 foreach my $pcidevice (@$pcidevices) {
2755 my $id = "hostpci$i";
2756 $id .= ".$j" if $multifunction;
2757 my $addr = $pciaddr;
2758 $addr .= ".$j" if $multifunction;
2759 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2762 $devicestr .= "$rombar$xvga";
2763 $devicestr .= ",multifunction=on" if $multifunction;
2766 push @$devices, '-device', $devicestr;
2772 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2773 my $d = parse_usb_device
($conf->{"usb$i"});
2775 if ($d->{vendorid
} && $d->{productid
}) {
2776 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2777 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2778 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2779 } elsif ($d->{spice
}) {
2780 # usb redir support for spice
2781 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2782 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2787 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2788 if (my $path = $conf->{"serial$i"}) {
2789 if ($path eq 'socket') {
2790 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2791 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2792 push @$devices, '-device', "isa-serial,chardev=serial$i";
2794 die "no such serial device\n" if ! -c
$path;
2795 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2796 push @$devices, '-device', "isa-serial,chardev=serial$i";
2802 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2803 if (my $path = $conf->{"parallel$i"}) {
2804 die "no such parallel device\n" if ! -c
$path;
2805 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2806 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2807 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2811 my $vmname = $conf->{name
} || "vm$vmid";
2813 push @$cmd, '-name', $vmname;
2816 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2817 $sockets = $conf->{sockets
} if $conf->{sockets
};
2819 my $cores = $conf->{cores
} || 1;
2821 my $maxcpus = $sockets * $cores;
2823 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2825 my $allowed_vcpus = $cpuinfo->{cpus
};
2827 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2828 if ($allowed_vcpus < $maxcpus);
2830 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2832 push @$cmd, '-nodefaults';
2834 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2836 my $bootindex_hash = {};
2838 foreach my $o (split(//, $bootorder)) {
2839 $bootindex_hash->{$o} = $i*100;
2843 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2845 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2847 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2849 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2852 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2854 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2855 my $useLocaltime = $conf->{localtime};
2857 if (my $ost = $conf->{ostype
}) {
2858 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2860 if ($ost =~ m/^w/) { # windows
2861 $useLocaltime = 1 if !defined($conf->{localtime});
2863 # use time drift fix when acpi is enabled
2864 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2865 $tdf = 1 if !defined($conf->{tdf
});
2869 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2871 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2872 push @$cmd, '-no-hpet';
2873 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2874 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2875 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2876 push @$cpuFlags , 'hv_time' if !$nokvm;
2879 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2883 if ($ost eq 'win7' || $ost eq 'win8') {
2884 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2888 push @$rtcFlags, 'driftfix=slew' if $tdf;
2891 push @$machineFlags, 'accel=tcg';
2893 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2896 if ($machine_type) {
2897 push @$machineFlags, "type=${machine_type}";
2900 if ($conf->{startdate
}) {
2901 push @$rtcFlags, "base=$conf->{startdate}";
2902 } elsif ($useLocaltime) {
2903 push @$rtcFlags, 'base=localtime';
2906 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2907 $cpu = $conf->{cpu
} if $conf->{cpu
};
2909 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2911 push @$cpuFlags , '-x2apic'
2912 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2914 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2916 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2918 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2920 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2921 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2922 push @$cpuFlags , '-kvm_steal_time' if !$nokvm;
2925 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2927 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2929 push @$cmd, '-cpu', $cpu;
2931 my $memory = $conf->{memory
} || $defaults->{memory
};
2932 my $static_memory = 0;
2933 my $dimm_memory = 0;
2935 if ($hotplug_features->{memory
}) {
2936 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2937 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2938 $static_memory = $STATICMEM;
2939 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2940 $dimm_memory = $memory - $static_memory;
2941 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2945 $static_memory = $memory;
2946 push @$cmd, '-m', $static_memory;
2949 if ($conf->{numa
}) {
2951 my $numa_totalmemory = undef;
2952 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2953 next if !$conf->{"numa$i"};
2954 my $numa = parse_numa
($conf->{"numa$i"});
2957 die "missing numa node$i memory value\n" if !$numa->{memory
};
2958 my $numa_memory = $numa->{memory
};
2959 $numa_totalmemory += $numa_memory;
2960 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2963 my $cpus_start = $numa->{cpus
}->{start
};
2964 die "missing numa node$i cpus\n" if !defined($cpus_start);
2965 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2966 my $cpus = $cpus_start;
2967 if (defined($cpus_end)) {
2968 $cpus .= "-$cpus_end";
2969 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2973 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2974 if (defined($hostnodes_start)) {
2975 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2976 my $hostnodes = $hostnodes_start;
2977 if (defined($hostnodes_end)) {
2978 $hostnodes .= "-$hostnodes_end";
2979 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2982 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2983 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2984 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2988 my $policy = $numa->{policy
};
2989 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2990 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2993 push @$cmd, '-object', $numa_object;
2994 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2997 die "total memory for NUMA nodes must be equal to vm static memory\n"
2998 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3000 #if no custom tology, we split memory and cores across numa nodes
3001 if(!$numa_totalmemory) {
3003 my $numa_memory = ($static_memory / $sockets) . "M";
3005 for (my $i = 0; $i < $sockets; $i++) {
3007 my $cpustart = ($cores * $i);
3008 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3009 my $cpus = $cpustart;
3010 $cpus .= "-$cpuend" if $cpuend;
3012 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3013 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3018 if ($hotplug_features->{memory
}) {
3019 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3020 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3021 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3022 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3024 #if dimm_memory is not aligned to dimm map
3025 if($current_size > $memory) {
3026 $conf->{memory
} = $current_size;
3027 update_config_nolock
($vmid, $conf, 1);
3032 push @$cmd, '-S' if $conf->{freeze
};
3034 # set keyboard layout
3035 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3036 push @$cmd, '-k', $kb if $kb;
3039 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3040 #push @$cmd, '-soundhw', 'es1370';
3041 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3043 if($conf->{agent
}) {
3044 my $qgasocket = qmp_socket
($vmid, 1);
3045 my $pciaddr = print_pci_addr
("qga0", $bridges);
3046 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3047 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3048 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3055 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3056 for(my $i = 1; $i < $qxlnum; $i++){
3057 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3058 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3061 # assume other OS works like Linux
3062 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3063 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3067 my $pciaddr = print_pci_addr
("spice", $bridges);
3069 my $nodename = PVE
::INotify
::nodename
();
3070 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3071 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3073 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3075 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3076 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3077 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3080 # enable balloon by default, unless explicitly disabled
3081 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3082 $pciaddr = print_pci_addr
("balloon0", $bridges);
3083 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3086 if ($conf->{watchdog
}) {
3087 my $wdopts = parse_watchdog
($conf->{watchdog
});
3088 $pciaddr = print_pci_addr
("watchdog", $bridges);
3089 my $watchdog = $wdopts->{model
} || 'i6300esb';
3090 push @$devices, '-device', "$watchdog$pciaddr";
3091 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3095 my $scsicontroller = {};
3096 my $ahcicontroller = {};
3097 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3099 # Add iscsi initiator name if available
3100 if (my $initiator = get_initiator_name
()) {
3101 push @$devices, '-iscsi', "initiator-name=$initiator";
3104 foreach_drive
($conf, sub {
3105 my ($ds, $drive) = @_;
3107 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3108 push @$vollist, $drive->{file
};
3111 $use_virtio = 1 if $ds =~ m/^virtio/;
3113 if (drive_is_cdrom
($drive)) {
3114 if ($bootindex_hash->{d
}) {
3115 $drive->{bootindex
} = $bootindex_hash->{d
};
3116 $bootindex_hash->{d
} += 1;
3119 if ($bootindex_hash->{c
}) {
3120 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3121 $bootindex_hash->{c
} += 1;
3125 if($drive->{interface
} eq 'virtio'){
3126 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3129 if ($drive->{interface
} eq 'scsi') {
3131 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3133 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3134 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3137 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3138 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3139 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3143 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3144 $queues = ",num_queues=$drive->{queues}";
3147 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3148 $scsicontroller->{$controller}=1;
3151 if ($drive->{interface
} eq 'sata') {
3152 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3153 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3154 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3155 $ahcicontroller->{$controller}=1;
3158 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3159 push @$devices, '-drive',$drive_cmd;
3160 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3163 for (my $i = 0; $i < $MAX_NETS; $i++) {
3164 next if !$conf->{"net$i"};
3165 my $d = parse_net
($conf->{"net$i"});
3168 $use_virtio = 1 if $d->{model
} eq 'virtio';
3170 if ($bootindex_hash->{n
}) {
3171 $d->{bootindex
} = $bootindex_hash->{n
};
3172 $bootindex_hash->{n
} += 1;
3175 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3176 push @$devices, '-netdev', $netdevfull;
3178 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3179 push @$devices, '-device', $netdevicefull;
3184 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3189 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3191 while (my ($k, $v) = each %$bridges) {
3192 $pciaddr = print_pci_addr
("pci.$k");
3193 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3198 if ($conf->{args
}) {
3199 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3203 push @$cmd, @$devices;
3204 push @$cmd, '-rtc', join(',', @$rtcFlags)
3205 if scalar(@$rtcFlags);
3206 push @$cmd, '-machine', join(',', @$machineFlags)
3207 if scalar(@$machineFlags);
3208 push @$cmd, '-global', join(',', @$globalFlags)
3209 if scalar(@$globalFlags);
3211 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3216 return "${var_run_tmpdir}/$vmid.vnc";
3222 my $res = vm_mon_cmd
($vmid, 'query-spice');
3224 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3228 my ($vmid, $qga) = @_;
3229 my $sockettype = $qga ?
'qga' : 'qmp';
3230 return "${var_run_tmpdir}/$vmid.$sockettype";
3235 return "${var_run_tmpdir}/$vmid.pid";
3238 sub vm_devices_list
{
3241 my $res = vm_mon_cmd
($vmid, 'query-pci');
3243 foreach my $pcibus (@$res) {
3244 foreach my $device (@{$pcibus->{devices
}}) {
3245 next if !$device->{'qdev_id'};
3246 if ($device->{'pci_bridge'}) {
3247 $devices->{$device->{'qdev_id'}} = 1;
3248 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3249 next if !$bridge_device->{'qdev_id'};
3250 $devices->{$bridge_device->{'qdev_id'}} = 1;
3251 $devices->{$device->{'qdev_id'}}++;
3254 $devices->{$device->{'qdev_id'}} = 1;
3259 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3260 foreach my $block (@$resblock) {
3261 if($block->{device
} =~ m/^drive-(\S+)/){
3266 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3267 foreach my $mice (@$resmice) {
3268 if ($mice->{name
} eq 'QEMU HID Tablet') {
3269 $devices->{tablet
} = 1;
3278 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3280 my $q35 = machine_type_is_q35
($conf);
3282 my $devices_list = vm_devices_list
($vmid);
3283 return 1 if defined($devices_list->{$deviceid});
3285 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3287 if ($deviceid eq 'tablet') {
3289 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3291 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3293 qemu_iothread_add
($vmid, $deviceid, $device);
3295 qemu_driveadd
($storecfg, $vmid, $device);
3296 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3298 qemu_deviceadd
($vmid, $devicefull);
3299 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3301 eval { qemu_drivedel
($vmid, $deviceid); };
3306 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3309 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3310 my $pciaddr = print_pci_addr
($deviceid);
3311 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3313 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3315 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3316 qemu_iothread_add
($vmid, $deviceid, $device);
3317 $devicefull .= ",iothread=iothread-$deviceid";
3320 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3321 $devicefull .= ",num_queues=$device->{queues}";
3324 qemu_deviceadd
($vmid, $devicefull);
3325 qemu_deviceaddverify
($vmid, $deviceid);
3327 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3329 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3330 qemu_driveadd
($storecfg, $vmid, $device);
3332 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3333 eval { qemu_deviceadd
($vmid, $devicefull); };
3335 eval { qemu_drivedel
($vmid, $deviceid); };
3340 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3342 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3344 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3345 my $use_old_bios_files = undef;
3346 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3348 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3349 qemu_deviceadd
($vmid, $netdevicefull);
3350 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3352 eval { qemu_netdevdel
($vmid, $deviceid); };
3357 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3360 my $pciaddr = print_pci_addr
($deviceid);
3361 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3363 qemu_deviceadd
($vmid, $devicefull);
3364 qemu_deviceaddverify
($vmid, $deviceid);
3367 die "can't hotplug device '$deviceid'\n";
3373 # fixme: this should raise exceptions on error!
3374 sub vm_deviceunplug
{
3375 my ($vmid, $conf, $deviceid) = @_;
3377 my $devices_list = vm_devices_list
($vmid);
3378 return 1 if !defined($devices_list->{$deviceid});
3380 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3382 if ($deviceid eq 'tablet') {
3384 qemu_devicedel
($vmid, $deviceid);
3386 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3388 qemu_devicedel
($vmid, $deviceid);
3389 qemu_devicedelverify
($vmid, $deviceid);
3390 qemu_drivedel
($vmid, $deviceid);
3391 qemu_iothread_del
($conf, $vmid, $deviceid);
3393 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3395 qemu_devicedel
($vmid, $deviceid);
3396 qemu_devicedelverify
($vmid, $deviceid);
3397 qemu_iothread_del
($conf, $vmid, $deviceid);
3399 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3401 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3402 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3403 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3405 qemu_devicedel
($vmid, $deviceid);
3406 qemu_drivedel
($vmid, $deviceid);
3407 qemu_deletescsihw
($conf, $vmid, $deviceid);
3409 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3411 qemu_devicedel
($vmid, $deviceid);
3412 qemu_devicedelverify
($vmid, $deviceid);
3413 qemu_netdevdel
($vmid, $deviceid);
3416 die "can't unplug device '$deviceid'\n";
3422 sub qemu_deviceadd
{
3423 my ($vmid, $devicefull) = @_;
3425 $devicefull = "driver=".$devicefull;
3426 my %options = split(/[=,]/, $devicefull);
3428 vm_mon_cmd
($vmid, "device_add" , %options);
3431 sub qemu_devicedel
{
3432 my ($vmid, $deviceid) = @_;
3434 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3437 sub qemu_iothread_add
{
3438 my($vmid, $deviceid, $device) = @_;
3440 if ($device->{iothread
}) {
3441 my $iothreads = vm_iothreads_list
($vmid);
3442 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3446 sub qemu_iothread_del
{
3447 my($conf, $vmid, $deviceid) = @_;
3449 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3450 if ($device->{iothread
}) {
3451 my $iothreads = vm_iothreads_list
($vmid);
3452 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3456 sub qemu_objectadd
{
3457 my($vmid, $objectid, $qomtype) = @_;
3459 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3464 sub qemu_objectdel
{
3465 my($vmid, $objectid) = @_;
3467 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3473 my ($storecfg, $vmid, $device) = @_;
3475 my $drive = print_drive_full
($storecfg, $vmid, $device);
3476 $drive =~ s/\\/\\\\/g;
3477 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3479 # If the command succeeds qemu prints: "OK
"
3480 return 1 if $ret =~ m/OK/s;
3482 die "adding drive failed
: $ret\n";
3486 my($vmid, $deviceid) = @_;
3488 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3491 return 1 if $ret eq "";
3493 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3494 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3496 die "deleting drive
$deviceid failed
: $ret\n";
3499 sub qemu_deviceaddverify {
3500 my ($vmid, $deviceid) = @_;
3502 for (my $i = 0; $i <= 5; $i++) {
3503 my $devices_list = vm_devices_list($vmid);
3504 return 1 if defined($devices_list->{$deviceid});
3508 die "error on hotplug device
'$deviceid'\n";
3512 sub qemu_devicedelverify {
3513 my ($vmid, $deviceid) = @_;
3515 # need to verify that the device is correctly removed as device_del
3516 # is async and empty return is not reliable
3518 for (my $i = 0; $i <= 5; $i++) {
3519 my $devices_list = vm_devices_list($vmid);
3520 return 1 if !defined($devices_list->{$deviceid});
3524 die "error on hot-unplugging device
'$deviceid'\n";
3527 sub qemu_findorcreatescsihw {
3528 my ($storecfg, $conf, $vmid, $device) = @_;
3530 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3532 my $scsihwid="$controller_prefix$controller";
3533 my $devices_list = vm_devices_list($vmid);
3535 if(!defined($devices_list->{$scsihwid})) {
3536 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3542 sub qemu_deletescsihw {
3543 my ($conf, $vmid, $opt) = @_;
3545 my $device = parse_drive($opt, $conf->{$opt});
3547 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3548 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3552 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3554 my $devices_list = vm_devices_list($vmid);
3555 foreach my $opt (keys %{$devices_list}) {
3556 if (PVE::QemuServer::valid_drivename($opt)) {
3557 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3558 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3564 my $scsihwid="scsihw
$controller";
3566 vm_deviceunplug($vmid, $conf, $scsihwid);
3571 sub qemu_add_pci_bridge {
3572 my ($storecfg, $conf, $vmid, $device) = @_;
3578 print_pci_addr($device, $bridges);
3580 while (my ($k, $v) = each %$bridges) {
3583 return 1 if !defined($bridgeid) || $bridgeid < 1;
3585 my $bridge = "pci
.$bridgeid";
3586 my $devices_list = vm_devices_list($vmid);
3588 if (!defined($devices_list->{$bridge})) {
3589 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3595 sub qemu_set_link_status {
3596 my ($vmid, $device, $up) = @_;
3598 vm_mon_cmd($vmid, "set_link
", name => $device,
3599 up => $up ? JSON::true : JSON::false);
3602 sub qemu_netdevadd {
3603 my ($vmid, $conf, $device, $deviceid) = @_;
3605 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3606 my %options = split(/[=,]/, $netdev);
3608 vm_mon_cmd($vmid, "netdev_add
", %options);
3612 sub qemu_netdevdel {
3613 my ($vmid, $deviceid) = @_;
3615 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3618 sub qemu_cpu_hotplug {
3619 my ($vmid, $conf, $vcpus) = @_;
3622 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3623 $sockets = $conf->{sockets} if $conf->{sockets};
3624 my $cores = $conf->{cores} || 1;
3625 my $maxcpus = $sockets * $cores;
3627 $vcpus = $maxcpus if !$vcpus;
3629 die "you can
't add more vcpus than maxcpus\n"
3630 if $vcpus > $maxcpus;
3632 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3633 die "online cpu unplug is not yet possible\n"
3634 if $vcpus < $currentvcpus;
3636 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3637 die "vcpus in running vm is different than configuration\n"
3638 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3640 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3641 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3645 sub qemu_memory_hotplug {
3646 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3648 return $value if !check_running($vmid);
3650 my $memory = $conf->{memory} || $defaults->{memory};
3651 $value = $defaults->{memory} if !$value;
3652 return $value if $value == $memory;
3654 my $static_memory = $STATICMEM;
3655 my $dimm_memory = $memory - $static_memory;
3657 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3658 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3662 $sockets = $conf->{sockets} if $conf->{sockets};
3664 if($value > $memory) {
3666 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3667 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3669 return if $current_size <= $conf->{memory};
3671 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3673 eval { qemu_objectdel($vmid, "mem-
$name"); };
3677 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3679 eval { qemu_objectdel($vmid, "mem-
$name"); };
3682 #update conf after each succesful module hotplug
3683 $conf->{memory} = $current_size;
3684 update_config_nolock($vmid, $conf, 1);
3689 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3690 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3692 return if $current_size >= $conf->{memory};
3693 print "try to unplug memory dimm
$name\n";
3697 eval { qemu_devicedel($vmid, $name) };
3699 my $dimm_list = qemu_dimm_list($vmid);
3700 last if !$dimm_list->{$name};
3701 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3705 #update conf after each succesful module unplug
3706 $conf->{memory} = $current_size;
3708 eval { qemu_objectdel($vmid, "mem-
$name"); };
3709 update_config_nolock($vmid, $conf, 1);
3714 sub qemu_dimm_list {
3717 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3720 foreach my $dimm (@$dimmarray) {
3722 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3723 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3724 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3725 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3726 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3731 sub qemu_block_set_io_throttle {
3732 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3734 return if !check_running($vmid) ;
3736 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));
3740 # old code, only used to shutdown old VM after update
3742 my ($fh, $timeout) = @_;
3744 my $sel = new IO::Select;
3751 while (scalar (@ready = $sel->can_read($timeout))) {
3753 if ($count = $fh->sysread($buf, 8192)) {
3754 if ($buf =~ /^(.*)\(qemu\) $/s) {
3761 if (!defined($count)) {
3768 die "monitor
read timeout
\n" if !scalar(@ready);
3773 # old code, only used to shutdown old VM after update
3774 sub vm_monitor_command {
3775 my ($vmid, $cmdstr, $nocheck) = @_;
3780 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3782 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3784 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3785 die "unable to
connect to VM
$vmid socket - $!\n";
3789 # hack: migrate sometime blocks the monitor (when migrate_downtime
3791 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3792 $timeout = 60*60; # 1 hour
3796 my $data = __read_avail($sock, $timeout);
3798 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3799 die "got unexpected qemu monitor banner
\n";
3802 my $sel = new IO::Select;
3805 if (!scalar(my @ready = $sel->can_write($timeout))) {
3806 die "monitor
write error
- timeout
";
3809 my $fullcmd = "$cmdstr\r";
3811 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3814 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3815 die "monitor
write error
- $!";
3818 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3822 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3823 $timeout = 60*60; # 1 hour
3824 } elsif ($cmdstr =~ m/^(eject|change)/) {
3825 $timeout = 60; # note: cdrom mount command is slow
3827 if ($res = __read_avail($sock, $timeout)) {
3829 my @lines = split("\r?
\n", $res);
3831 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3833 $res = join("\n", @lines);
3841 syslog("err
", "VM
$vmid monitor command failed
- $err");
3848 sub qemu_block_resize {
3849 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3851 my $running = check_running($vmid);
3853 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3855 return if !$running;
3857 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3861 sub qemu_volume_snapshot {
3862 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3864 my $running = check_running($vmid);
3866 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3867 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3869 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3873 sub qemu_volume_snapshot_delete {
3874 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3876 my $running = check_running($vmid);
3878 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3880 return if !$running;
3882 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3885 sub set_migration_caps {
3891 "auto-converge
" => 1,
3893 "x-rdma-pin-all
" => 0,
3898 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3900 for my $supported_capability (@$supported_capabilities) {
3902 capability => $supported_capability->{capability},
3903 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3907 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3910 my $fast_plug_option = {
3919 # hotplug changes in [PENDING]
3920 # $selection hash can be used to only apply specified options, for
3921 # example: { cores => 1 } (only apply changed 'cores')
3922 # $errors ref is used to return error messages
3923 sub vmconfig_hotplug_pending {
3924 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3926 my $defaults = load_defaults();
3928 # commit values which do not have any impact on running VM first
3929 # Note: those option cannot raise errors, we we do not care about
3930 # $selection and always apply them.
3932 my $add_error = sub {
3933 my ($opt, $msg) = @_;
3934 $errors->{$opt} = "hotplug problem
- $msg";
3938 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3939 if ($fast_plug_option->{$opt}) {
3940 $conf->{$opt} = $conf->{pending}->{$opt};
3941 delete $conf->{pending}->{$opt};
3947 update_config_nolock($vmid, $conf, 1);
3948 $conf = load_config($vmid); # update/reload
3951 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3953 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3954 while (my ($opt, $force) = each %$pending_delete_hash) {
3955 next if $selection && !$selection->{$opt};
3957 if ($opt eq 'hotplug') {
3958 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3959 } elsif ($opt eq 'tablet') {
3960 die "skip
\n" if !$hotplug_features->{usb};
3961 if ($defaults->{tablet}) {
3962 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3964 vm_deviceunplug($vmid, $conf, $opt);
3966 } elsif ($opt eq 'vcpus') {
3967 die "skip
\n" if !$hotplug_features->{cpu};
3968 qemu_cpu_hotplug($vmid, $conf, undef);
3969 } elsif ($opt eq 'balloon') {
3970 # enable balloon device is not hotpluggable
3971 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3972 } elsif ($fast_plug_option->{$opt}) {
3974 } elsif ($opt =~ m/^net(\d+)$/) {
3975 die "skip
\n" if !$hotplug_features->{network};
3976 vm_deviceunplug($vmid, $conf, $opt);
3977 } elsif (valid_drivename($opt)) {
3978 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3979 vm_deviceunplug($vmid, $conf, $opt);
3980 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3981 } elsif ($opt =~ m/^memory$/) {
3982 die "skip
\n" if !$hotplug_features->{memory};
3983 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3984 } elsif ($opt eq 'cpuunits') {
3985 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3986 } elsif ($opt eq 'cpulimit') {
3987 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3993 &$add_error($opt, $err) if $err ne "skip
\n";
3995 # save new config if hotplug was successful
3996 delete $conf->{$opt};
3997 vmconfig_undelete_pending_option($conf, $opt);
3998 update_config_nolock($vmid, $conf, 1);
3999 $conf = load_config($vmid); # update/reload
4003 foreach my $opt (keys %{$conf->{pending}}) {
4004 next if $selection && !$selection->{$opt};
4005 my $value = $conf->{pending}->{$opt};
4007 if ($opt eq 'hotplug') {
4008 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4009 } elsif ($opt eq 'tablet') {
4010 die "skip
\n" if !$hotplug_features->{usb};
4012 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4013 } elsif ($value == 0) {
4014 vm_deviceunplug($vmid, $conf, $opt);
4016 } elsif ($opt eq 'vcpus') {
4017 die "skip
\n" if !$hotplug_features->{cpu};
4018 qemu_cpu_hotplug($vmid, $conf, $value);
4019 } elsif ($opt eq 'balloon') {
4020 # enable/disable balloning device is not hotpluggable
4021 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4022 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4023 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4025 # allow manual ballooning if shares is set to zero
4026 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4027 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4028 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4030 } elsif ($opt =~ m/^net(\d+)$/) {
4031 # some changes can be done without hotplug
4032 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4033 $vmid, $opt, $value);
4034 } elsif (valid_drivename($opt)) {
4035 # some changes can be done without hotplug
4036 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4037 $vmid, $opt, $value, 1);
4038 } elsif ($opt =~ m/^memory$/) { #dimms
4039 die "skip
\n" if !$hotplug_features->{memory};
4040 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4041 } elsif ($opt eq 'cpuunits') {
4042 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4043 } elsif ($opt eq 'cpulimit') {
4044 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4045 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4047 die "skip
\n"; # skip non-hot-pluggable options
4051 &$add_error($opt, $err) if $err ne "skip
\n";
4053 # save new config if hotplug was successful
4054 $conf->{$opt} = $value;
4055 delete $conf->{pending}->{$opt};
4056 update_config_nolock($vmid, $conf, 1);
4057 $conf = load_config($vmid); # update/reload
4062 sub try_deallocate_drive {
4063 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4065 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4066 my $volid = $drive->{file};
4067 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4068 my $sid = PVE::Storage::parse_volume_id($volid);
4069 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4071 # check if the disk is really unused
4072 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4073 my $path = PVE::Storage::path($storecfg, $volid);
4074 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4075 if $used_paths->{$path};
4076 PVE::Storage::vdisk_free($storecfg, $volid);
4079 # If vm is not owner of this disk remove from config
4087 sub vmconfig_delete_or_detach_drive {
4088 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4090 my $drive = parse_drive($opt, $conf->{$opt});
4092 my $rpcenv = PVE::RPCEnvironment::get();
4093 my $authuser = $rpcenv->get_user();
4096 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4097 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4099 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4103 sub vmconfig_apply_pending {
4104 my ($vmid, $conf, $storecfg) = @_;
4108 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4109 while (my ($opt, $force) = each %$pending_delete_hash) {
4110 die "internal error
" if $opt =~ m/^unused/;
4111 $conf = load_config($vmid); # update/reload
4112 if (!defined($conf->{$opt})) {
4113 vmconfig_undelete_pending_option($conf, $opt);
4114 update_config_nolock($vmid, $conf, 1);
4115 } elsif (valid_drivename($opt)) {
4116 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4117 vmconfig_undelete_pending_option($conf, $opt);
4118 delete $conf->{$opt};
4119 update_config_nolock($vmid, $conf, 1);
4121 vmconfig_undelete_pending_option($conf, $opt);
4122 delete $conf->{$opt};
4123 update_config_nolock($vmid, $conf, 1);
4127 $conf = load_config($vmid); # update/reload
4129 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4130 $conf = load_config($vmid); # update/reload
4132 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4133 # skip if nothing changed
4134 } elsif (valid_drivename($opt)) {
4135 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4136 if defined($conf->{$opt});
4137 $conf->{$opt} = $conf->{pending}->{$opt};
4139 $conf->{$opt} = $conf->{pending}->{$opt};
4142 delete $conf->{pending}->{$opt};
4143 update_config_nolock($vmid, $conf, 1);
4147 my $safe_num_ne = sub {
4150 return 0 if !defined($a) && !defined($b);
4151 return 1 if !defined($a);
4152 return 1 if !defined($b);
4157 my $safe_string_ne = sub {
4160 return 0 if !defined($a) && !defined($b);
4161 return 1 if !defined($a);
4162 return 1 if !defined($b);
4167 sub vmconfig_update_net {
4168 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4170 my $newnet = parse_net($value);
4172 if ($conf->{$opt}) {
4173 my $oldnet = parse_net($conf->{$opt});
4175 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4176 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4177 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4178 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4180 # for non online change, we try to hot-unplug
4181 die "skip
\n" if !$hotplug;
4182 vm_deviceunplug($vmid, $conf, $opt);
4185 die "internal error
" if $opt !~ m/net(\d+)/;
4186 my $iface = "tap
${vmid
}i
$1";
4188 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4189 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4192 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4193 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4194 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4195 PVE::Network::tap_unplug($iface);
4196 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4199 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4200 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4208 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4214 sub vmconfig_update_disk {
4215 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4217 # fixme: do we need force?
4219 my $drive = parse_drive($opt, $value);
4221 if ($conf->{$opt}) {
4223 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4225 my $media = $drive->{media} || 'disk';
4226 my $oldmedia = $old_drive->{media} || 'disk';
4227 die "unable to change media type
\n" if $media ne $oldmedia;
4229 if (!drive_is_cdrom($old_drive)) {
4231 if ($drive->{file} ne $old_drive->{file}) {
4233 die "skip
\n" if !$hotplug;
4235 # unplug and register as unused
4236 vm_deviceunplug($vmid, $conf, $opt);
4237 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4240 # update existing disk
4242 # skip non hotpluggable value
4243 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4244 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4245 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4246 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4251 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4252 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4253 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4254 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4255 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4256 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4257 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4258 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4259 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4260 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4261 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4262 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4264 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4265 ($drive->{mbps} || 0)*1024*1024,
4266 ($drive->{mbps_rd} || 0)*1024*1024,
4267 ($drive->{mbps_wr} || 0)*1024*1024,
4268 $drive->{iops} || 0,
4269 $drive->{iops_rd} || 0,
4270 $drive->{iops_wr} || 0,
4271 ($drive->{mbps_max} || 0)*1024*1024,
4272 ($drive->{mbps_rd_max} || 0)*1024*1024,
4273 ($drive->{mbps_wr_max} || 0)*1024*1024,
4274 $drive->{iops_max} || 0,
4275 $drive->{iops_rd_max} || 0,
4276 $drive->{iops_wr_max} || 0);
4285 if ($drive->{file} eq 'none') {
4286 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4288 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4289 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4290 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4298 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4300 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4304 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4305 $forcemachine, $spice_ticket) = @_;
4307 lock_config($vmid, sub {
4308 my $conf = load_config($vmid, $migratedfrom);
4310 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4312 check_lock($conf) if !$skiplock;
4314 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4316 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4317 vmconfig_apply_pending($vmid, $conf, $storecfg);
4318 $conf = load_config($vmid); # update/reload
4321 my $defaults = load_defaults();
4323 # set environment variable useful inside network script
4324 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4326 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4328 my $migrate_port = 0;
4331 if ($statefile eq 'tcp') {
4332 my $localip = "localhost
";
4333 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4334 my $nodename = PVE::INotify::nodename();
4335 if ($datacenterconf->{migration_unsecure}) {
4336 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4337 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4339 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4340 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4341 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4342 push @$cmd, '-incoming', $migrate_uri;
4345 push @$cmd, '-loadstate', $statefile;
4352 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4353 my $d = parse_hostpci($conf->{"hostpci
$i"});
4355 my $pcidevices = $d->{pciid};
4356 foreach my $pcidevice (@$pcidevices) {
4357 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4359 my $info = pci_device_info("0000:$pciid");
4360 die "IOMMU
not present
\n" if !check_iommu_support();
4361 die "no pci device info
for device
'$pciid'\n" if !$info;
4362 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4363 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4367 PVE::Storage::activate_volumes($storecfg, $vollist);
4369 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4372 die "start failed
: $err" if $err;
4374 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4376 if ($statefile && $statefile ne 'tcp') {
4377 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4381 if ($migratedfrom) {
4384 set_migration_caps($vmid);
4389 print "spice listens on port
$spice_port\n";
4390 if ($spice_ticket) {
4391 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4392 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4398 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4399 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4400 if $conf->{balloon};
4403 foreach my $opt (keys %$conf) {
4404 next if $opt !~ m/^net\d+$/;
4405 my $nicconf = parse_net($conf->{$opt});
4406 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4410 vm_mon_cmd_nocheck($vmid, 'qom-set',
4411 path => "machine
/peripheral/balloon0
",
4412 property => "guest-stats-polling-interval
",
4413 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4419 my ($vmid, $execute, %params) = @_;
4421 my $cmd = { execute => $execute, arguments => \%params };
4422 vm_qmp_command($vmid, $cmd);
4425 sub vm_mon_cmd_nocheck {
4426 my ($vmid, $execute, %params) = @_;
4428 my $cmd = { execute => $execute, arguments => \%params };
4429 vm_qmp_command($vmid, $cmd, 1);
4432 sub vm_qmp_command {
4433 my ($vmid, $cmd, $nocheck) = @_;
4438 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4439 $timeout = $cmd->{arguments}->{timeout};
4440 delete $cmd->{arguments}->{timeout};
4444 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4445 my $sname = qmp_socket($vmid);
4446 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4447 my $qmpclient = PVE::QMPClient->new();
4449 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4450 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4451 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4452 if scalar(%{$cmd->{arguments}});
4453 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4455 die "unable to open monitor socket\n";
4459 syslog("err", "VM $vmid qmp command failed - $err");
4466 sub vm_human_monitor_command {
4467 my ($vmid, $cmdline) = @_;
4472 execute => 'human-monitor-command
',
4473 arguments => { 'command-line
' => $cmdline},
4476 return vm_qmp_command($vmid, $cmd);
4479 sub vm_commandline {
4480 my ($storecfg, $vmid) = @_;
4482 my $conf = load_config($vmid);
4484 my $defaults = load_defaults();
4486 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4488 return join(' ', @$cmd);
4492 my ($vmid, $skiplock) = @_;
4494 lock_config($vmid, sub {
4496 my $conf = load_config($vmid);
4498 check_lock($conf) if !$skiplock;
4500 vm_mon_cmd($vmid, "system_reset");
4504 sub get_vm_volumes {
4508 foreach_volid($conf, sub {
4509 my ($volid, $is_cdrom) = @_;
4511 return if $volid =~ m|^/|;
4513 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4516 push @$vollist, $volid;
4522 sub vm_stop_cleanup {
4523 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4528 my $vollist = get_vm_volumes($conf);
4529 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4532 foreach my $ext (qw(mon qmp pid vnc qga)) {
4533 unlink "/var/run/qemu-server/${vmid}.$ext";
4536 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4538 warn $@ if $@; # avoid errors - just warn
4541 # Note: use $nockeck to skip tests if VM configuration file exists.
4542 # We need that when migration VMs to other nodes (files already moved)
4543 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4545 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4547 $force = 1 if !defined($force) && !$shutdown;
4550 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4551 kill 15, $pid if $pid;
4552 my $conf = load_config
($vmid, $migratedfrom);
4553 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4557 lock_config
($vmid, sub {
4559 my $pid = check_running
($vmid, $nocheck);
4564 $conf = load_config
($vmid);
4565 check_lock
($conf) if !$skiplock;
4566 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4567 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4568 $timeout = $opts->{down
} if $opts->{down
};
4572 $timeout = 60 if !defined($timeout);
4576 if (defined($conf) && $conf->{agent
}) {
4577 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4579 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4582 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4589 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4594 if ($count >= $timeout) {
4596 warn "VM still running - terminating now with SIGTERM\n";
4599 die "VM quit/powerdown failed - got timeout\n";
4602 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4607 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4610 die "VM quit/powerdown failed\n";
4618 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4623 if ($count >= $timeout) {
4624 warn "VM still running - terminating now with SIGKILL\n";
4629 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4634 my ($vmid, $skiplock) = @_;
4636 lock_config
($vmid, sub {
4638 my $conf = load_config
($vmid);
4640 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4642 vm_mon_cmd
($vmid, "stop");
4647 my ($vmid, $skiplock, $nocheck) = @_;
4649 lock_config
($vmid, sub {
4653 my $conf = load_config
($vmid);
4655 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4657 vm_mon_cmd
($vmid, "cont");
4660 vm_mon_cmd_nocheck
($vmid, "cont");
4666 my ($vmid, $skiplock, $key) = @_;
4668 lock_config
($vmid, sub {
4670 my $conf = load_config
($vmid);
4672 # there is no qmp command, so we use the human monitor command
4673 vm_human_monitor_command
($vmid, "sendkey $key");
4678 my ($storecfg, $vmid, $skiplock) = @_;
4680 lock_config
($vmid, sub {
4682 my $conf = load_config
($vmid);
4684 check_lock
($conf) if !$skiplock;
4686 if (!check_running
($vmid)) {
4687 destroy_vm
($storecfg, $vmid);
4689 die "VM $vmid is running - destroy failed\n";
4697 my ($filename, $buf) = @_;
4699 my $fh = IO
::File-
>new($filename, "w");
4700 return undef if !$fh;
4702 my $res = print $fh $buf;
4709 sub pci_device_info
{
4714 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4715 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4717 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4718 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4720 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4721 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4723 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4724 return undef if !defined($product) || $product !~ s/^0x//;
4729 product
=> $product,
4735 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4744 my $name = $dev->{name
};
4746 my $fn = "$pcisysfs/devices/$name/reset";
4748 return file_write
($fn, "1");
4751 sub pci_dev_bind_to_vfio
{
4754 my $name = $dev->{name
};
4756 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4758 if (!-d
$vfio_basedir) {
4759 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4761 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4763 my $testdir = "$vfio_basedir/$name";
4764 return 1 if -d
$testdir;
4766 my $data = "$dev->{vendor} $dev->{product}";
4767 return undef if !file_write
("$vfio_basedir/new_id", $data);
4769 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4770 if (!file_write
($fn, $name)) {
4771 return undef if -f
$fn;
4774 $fn = "$vfio_basedir/bind";
4775 if (! -d
$testdir) {
4776 return undef if !file_write
($fn, $name);
4782 sub pci_dev_group_bind_to_vfio
{
4785 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4787 if (!-d
$vfio_basedir) {
4788 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4790 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4792 # get IOMMU group devices
4793 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4794 my @devs = grep /^0000:/, readdir($D);
4797 foreach my $pciid (@devs) {
4798 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4800 # pci bridges, switches or root ports are not supported
4801 # they have a pci_bus subdirectory so skip them
4802 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4804 my $info = pci_device_info
($1);
4805 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4811 sub print_pci_addr
{
4812 my ($id, $bridges) = @_;
4816 piix3
=> { bus
=> 0, addr
=> 1 },
4817 #addr2 : first videocard
4818 balloon0
=> { bus
=> 0, addr
=> 3 },
4819 watchdog
=> { bus
=> 0, addr
=> 4 },
4820 scsihw0
=> { bus
=> 0, addr
=> 5 },
4821 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4822 scsihw1
=> { bus
=> 0, addr
=> 6 },
4823 ahci0
=> { bus
=> 0, addr
=> 7 },
4824 qga0
=> { bus
=> 0, addr
=> 8 },
4825 spice
=> { bus
=> 0, addr
=> 9 },
4826 virtio0
=> { bus
=> 0, addr
=> 10 },
4827 virtio1
=> { bus
=> 0, addr
=> 11 },
4828 virtio2
=> { bus
=> 0, addr
=> 12 },
4829 virtio3
=> { bus
=> 0, addr
=> 13 },
4830 virtio4
=> { bus
=> 0, addr
=> 14 },
4831 virtio5
=> { bus
=> 0, addr
=> 15 },
4832 hostpci0
=> { bus
=> 0, addr
=> 16 },
4833 hostpci1
=> { bus
=> 0, addr
=> 17 },
4834 net0
=> { bus
=> 0, addr
=> 18 },
4835 net1
=> { bus
=> 0, addr
=> 19 },
4836 net2
=> { bus
=> 0, addr
=> 20 },
4837 net3
=> { bus
=> 0, addr
=> 21 },
4838 net4
=> { bus
=> 0, addr
=> 22 },
4839 net5
=> { bus
=> 0, addr
=> 23 },
4840 vga1
=> { bus
=> 0, addr
=> 24 },
4841 vga2
=> { bus
=> 0, addr
=> 25 },
4842 vga3
=> { bus
=> 0, addr
=> 26 },
4843 hostpci2
=> { bus
=> 0, addr
=> 27 },
4844 hostpci3
=> { bus
=> 0, addr
=> 28 },
4845 #addr29 : usb-host (pve-usb.cfg)
4846 'pci.1' => { bus
=> 0, addr
=> 30 },
4847 'pci.2' => { bus
=> 0, addr
=> 31 },
4848 'net6' => { bus
=> 1, addr
=> 1 },
4849 'net7' => { bus
=> 1, addr
=> 2 },
4850 'net8' => { bus
=> 1, addr
=> 3 },
4851 'net9' => { bus
=> 1, addr
=> 4 },
4852 'net10' => { bus
=> 1, addr
=> 5 },
4853 'net11' => { bus
=> 1, addr
=> 6 },
4854 'net12' => { bus
=> 1, addr
=> 7 },
4855 'net13' => { bus
=> 1, addr
=> 8 },
4856 'net14' => { bus
=> 1, addr
=> 9 },
4857 'net15' => { bus
=> 1, addr
=> 10 },
4858 'net16' => { bus
=> 1, addr
=> 11 },
4859 'net17' => { bus
=> 1, addr
=> 12 },
4860 'net18' => { bus
=> 1, addr
=> 13 },
4861 'net19' => { bus
=> 1, addr
=> 14 },
4862 'net20' => { bus
=> 1, addr
=> 15 },
4863 'net21' => { bus
=> 1, addr
=> 16 },
4864 'net22' => { bus
=> 1, addr
=> 17 },
4865 'net23' => { bus
=> 1, addr
=> 18 },
4866 'net24' => { bus
=> 1, addr
=> 19 },
4867 'net25' => { bus
=> 1, addr
=> 20 },
4868 'net26' => { bus
=> 1, addr
=> 21 },
4869 'net27' => { bus
=> 1, addr
=> 22 },
4870 'net28' => { bus
=> 1, addr
=> 23 },
4871 'net29' => { bus
=> 1, addr
=> 24 },
4872 'net30' => { bus
=> 1, addr
=> 25 },
4873 'net31' => { bus
=> 1, addr
=> 26 },
4874 'virtio6' => { bus
=> 2, addr
=> 1 },
4875 'virtio7' => { bus
=> 2, addr
=> 2 },
4876 'virtio8' => { bus
=> 2, addr
=> 3 },
4877 'virtio9' => { bus
=> 2, addr
=> 4 },
4878 'virtio10' => { bus
=> 2, addr
=> 5 },
4879 'virtio11' => { bus
=> 2, addr
=> 6 },
4880 'virtio12' => { bus
=> 2, addr
=> 7 },
4881 'virtio13' => { bus
=> 2, addr
=> 8 },
4882 'virtio14' => { bus
=> 2, addr
=> 9 },
4883 'virtio15' => { bus
=> 2, addr
=> 10 },
4884 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4885 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4886 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4887 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4888 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4889 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4890 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4891 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4892 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4893 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4894 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4895 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4896 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4897 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4898 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4899 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4900 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4901 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4902 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4903 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4904 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4905 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4906 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4907 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4908 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4909 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4910 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4911 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4912 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4913 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4914 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4918 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4919 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4920 my $bus = $devices->{$id}->{bus
};
4921 $res = ",bus=pci.$bus,addr=$addr";
4922 $bridges->{$bus} = 1 if $bridges;
4928 sub print_pcie_addr
{
4933 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4934 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4935 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4936 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4939 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4940 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4941 my $bus = $devices->{$id}->{bus
};
4942 $res = ",bus=$bus,addr=$addr";
4948 # vzdump restore implementaion
4950 sub tar_archive_read_firstfile
{
4951 my $archive = shift;
4953 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4955 # try to detect archive type first
4956 my $pid = open (TMP
, "tar tf '$archive'|") ||
4957 die "unable to open file '$archive'\n";
4958 my $firstfile = <TMP
>;
4962 die "ERROR: archive contaions no data\n" if !$firstfile;
4968 sub tar_restore_cleanup
{
4969 my ($storecfg, $statfile) = @_;
4971 print STDERR
"starting cleanup\n";
4973 if (my $fd = IO
::File-
>new($statfile, "r")) {
4974 while (defined(my $line = <$fd>)) {
4975 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4978 if ($volid =~ m
|^/|) {
4979 unlink $volid || die 'unlink failed\n';
4981 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4983 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4985 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4987 print STDERR
"unable to parse line in statfile - $line";
4994 sub restore_archive
{
4995 my ($archive, $vmid, $user, $opts) = @_;
4997 my $format = $opts->{format
};
5000 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5001 $format = 'tar' if !$format;
5003 } elsif ($archive =~ m/\.tar$/) {
5004 $format = 'tar' if !$format;
5005 } elsif ($archive =~ m/.tar.lzo$/) {
5006 $format = 'tar' if !$format;
5008 } elsif ($archive =~ m/\.vma$/) {
5009 $format = 'vma' if !$format;
5010 } elsif ($archive =~ m/\.vma\.gz$/) {
5011 $format = 'vma' if !$format;
5013 } elsif ($archive =~ m/\.vma\.lzo$/) {
5014 $format = 'vma' if !$format;
5017 $format = 'vma' if !$format; # default
5020 # try to detect archive format
5021 if ($format eq 'tar') {
5022 return restore_tar_archive
($archive, $vmid, $user, $opts);
5024 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5028 sub restore_update_config_line
{
5029 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5031 return if $line =~ m/^\#qmdump\#/;
5032 return if $line =~ m/^\#vzdump\#/;
5033 return if $line =~ m/^lock:/;
5034 return if $line =~ m/^unused\d+:/;
5035 return if $line =~ m/^parent:/;
5036 return if $line =~ m/^template:/; # restored VM is never a template
5038 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5039 # try to convert old 1.X settings
5040 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5041 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5042 my ($model, $macaddr) = split(/\=/, $devconfig);
5043 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5046 bridge
=> "vmbr$ind",
5047 macaddr
=> $macaddr,
5049 my $netstr = print_net
($net);
5051 print $outfd "net$cookie->{netcount}: $netstr\n";
5052 $cookie->{netcount
}++;
5054 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5055 my ($id, $netstr) = ($1, $2);
5056 my $net = parse_net
($netstr);
5057 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5058 $netstr = print_net
($net);
5059 print $outfd "$id: $netstr\n";
5060 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5063 if ($line =~ m/backup=no/) {
5064 print $outfd "#$line";
5065 } elsif ($virtdev && $map->{$virtdev}) {
5066 my $di = parse_drive
($virtdev, $value);
5067 delete $di->{format
}; # format can change on restore
5068 $di->{file
} = $map->{$virtdev};
5069 $value = print_drive
($vmid, $di);
5070 print $outfd "$virtdev: $value\n";
5080 my ($cfg, $vmid) = @_;
5082 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5084 my $volid_hash = {};
5085 foreach my $storeid (keys %$info) {
5086 foreach my $item (@{$info->{$storeid}}) {
5087 next if !($item->{volid
} && $item->{size
});
5088 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5089 $volid_hash->{$item->{volid
}} = $item;
5096 sub get_used_paths
{
5097 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5101 my $scan_config = sub {
5102 my ($cref, $snapname) = @_;
5104 foreach my $key (keys %$cref) {
5105 my $value = $cref->{$key};
5106 if (valid_drivename
($key)) {
5107 next if $skip_drive && $key eq $skip_drive;
5108 my $drive = parse_drive
($key, $value);
5109 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5110 if ($drive->{file
} =~ m!^/!) {
5111 $used_path->{$drive->{file
}}++; # = 1;
5113 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5115 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5117 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5118 $used_path->{$path}++; # = 1;
5124 &$scan_config($conf);
5128 if ($scan_snapshots) {
5129 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5130 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5137 sub update_disksize
{
5138 my ($vmid, $conf, $volid_hash) = @_;
5144 # Note: it is allowed to define multiple storages with same path (alias), so
5145 # we need to check both 'volid' and real 'path' (two different volid can point
5146 # to the same path).
5151 foreach my $opt (keys %$conf) {
5152 if (valid_drivename
($opt)) {
5153 my $drive = parse_drive
($opt, $conf->{$opt});
5154 my $volid = $drive->{file
};
5157 $used->{$volid} = 1;
5158 if ($volid_hash->{$volid} &&
5159 (my $path = $volid_hash->{$volid}->{path
})) {
5160 $usedpath->{$path} = 1;
5163 next if drive_is_cdrom
($drive);
5164 next if !$volid_hash->{$volid};
5166 $drive->{size
} = $volid_hash->{$volid}->{size
};
5167 my $new = print_drive
($vmid, $drive);
5168 if ($new ne $conf->{$opt}) {
5170 $conf->{$opt} = $new;
5175 # remove 'unusedX' entry if volume is used
5176 foreach my $opt (keys %$conf) {
5177 next if $opt !~ m/^unused\d+$/;
5178 my $volid = $conf->{$opt};
5179 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5180 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5182 delete $conf->{$opt};
5186 foreach my $volid (sort keys %$volid_hash) {
5187 next if $volid =~ m/vm-$vmid-state-/;
5188 next if $used->{$volid};
5189 my $path = $volid_hash->{$volid}->{path
};
5190 next if !$path; # just to be sure
5191 next if $usedpath->{$path};
5193 add_unused_volume
($conf, $volid);
5194 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5201 my ($vmid, $nolock) = @_;
5203 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5205 my $volid_hash = scan_volids
($cfg, $vmid);
5207 my $updatefn = sub {
5210 my $conf = load_config
($vmid);
5215 foreach my $volid (keys %$volid_hash) {
5216 my $info = $volid_hash->{$volid};
5217 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5220 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5222 update_config_nolock
($vmid, $conf, 1) if $changes;
5225 if (defined($vmid)) {
5229 lock_config
($vmid, $updatefn, $vmid);
5232 my $vmlist = config_list
();
5233 foreach my $vmid (keys %$vmlist) {
5237 lock_config
($vmid, $updatefn, $vmid);
5243 sub restore_vma_archive
{
5244 my ($archive, $vmid, $user, $opts, $comp) = @_;
5246 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5247 my $readfrom = $archive;
5252 my $qarchive = PVE
::Tools
::shellquote
($archive);
5253 if ($comp eq 'gzip') {
5254 $uncomp = "zcat $qarchive|";
5255 } elsif ($comp eq 'lzop') {
5256 $uncomp = "lzop -d -c $qarchive|";
5258 die "unknown compression method '$comp'\n";
5263 my $tmpdir = "/var/tmp/vzdumptmp$$";
5266 # disable interrupts (always do cleanups)
5267 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5268 warn "got interrupt - ignored\n";
5271 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5272 POSIX
::mkfifo
($mapfifo, 0600);
5275 my $openfifo = sub {
5276 open($fifofh, '>', $mapfifo) || die $!;
5279 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5286 my $rpcenv = PVE
::RPCEnvironment
::get
();
5288 my $conffile = config_file
($vmid);
5289 my $tmpfn = "$conffile.$$.tmp";
5291 # Note: $oldconf is undef if VM does not exists
5292 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5294 my $print_devmap = sub {
5295 my $virtdev_hash = {};
5297 my $cfgfn = "$tmpdir/qemu-server.conf";
5299 # we can read the config - that is already extracted
5300 my $fh = IO
::File-
>new($cfgfn, "r") ||
5301 "unable to read qemu-server.conf - $!\n";
5303 while (defined(my $line = <$fh>)) {
5304 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5305 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5306 die "archive does not contain data for drive '$virtdev'\n"
5307 if !$devinfo->{$devname};
5308 if (defined($opts->{storage
})) {
5309 $storeid = $opts->{storage
} || 'local';
5310 } elsif (!$storeid) {
5313 $format = 'raw' if !$format;
5314 $devinfo->{$devname}->{devname
} = $devname;
5315 $devinfo->{$devname}->{virtdev
} = $virtdev;
5316 $devinfo->{$devname}->{format
} = $format;
5317 $devinfo->{$devname}->{storeid
} = $storeid;
5319 # check permission on storage
5320 my $pool = $opts->{pool
}; # todo: do we need that?
5321 if ($user ne 'root@pam') {
5322 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5325 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5329 foreach my $devname (keys %$devinfo) {
5330 die "found no device mapping information for device '$devname'\n"
5331 if !$devinfo->{$devname}->{virtdev
};
5334 my $cfg = cfs_read_file
('storage.cfg');
5336 # create empty/temp config
5338 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5339 foreach_drive
($oldconf, sub {
5340 my ($ds, $drive) = @_;
5342 return if drive_is_cdrom
($drive);
5344 my $volid = $drive->{file
};
5346 return if !$volid || $volid =~ m
|^/|;
5348 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5349 return if !$path || !$owner || ($owner != $vmid);
5351 # Note: only delete disk we want to restore
5352 # other volumes will become unused
5353 if ($virtdev_hash->{$ds}) {
5354 PVE
::Storage
::vdisk_free
($cfg, $volid);
5360 foreach my $virtdev (sort keys %$virtdev_hash) {
5361 my $d = $virtdev_hash->{$virtdev};
5362 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5363 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5365 # test if requested format is supported
5366 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5367 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5368 $d->{format
} = $defFormat if !$supported;
5370 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5371 $d->{format
}, undef, $alloc_size);
5372 print STDERR
"new volume ID is '$volid'\n";
5373 $d->{volid
} = $volid;
5374 my $path = PVE
::Storage
::path
($cfg, $volid);
5376 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5378 my $write_zeros = 1;
5379 # fixme: what other storages types initialize volumes with zero?
5380 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5381 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5385 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5387 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5388 $map->{$virtdev} = $volid;
5391 $fh->seek(0, 0) || die "seek failed - $!\n";
5393 my $outfd = new IO
::File
($tmpfn, "w") ||
5394 die "unable to write config for VM $vmid\n";
5396 my $cookie = { netcount
=> 0 };
5397 while (defined(my $line = <$fh>)) {
5398 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5407 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5408 die "interrupted by signal\n";
5410 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5412 $oldtimeout = alarm($timeout);
5419 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5420 my ($dev_id, $size, $devname) = ($1, $2, $3);
5421 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5422 } elsif ($line =~ m/^CTIME: /) {
5423 # we correctly received the vma config, so we can disable
5424 # the timeout now for disk allocation (set to 10 minutes, so
5425 # that we always timeout if something goes wrong)
5428 print $fifofh "done\n";
5429 my $tmp = $oldtimeout || 0;
5430 $oldtimeout = undef;
5436 print "restore vma archive: $cmd\n";
5437 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5441 alarm($oldtimeout) if $oldtimeout;
5444 foreach my $devname (keys %$devinfo) {
5445 my $volid = $devinfo->{$devname}->{volid
};
5446 push @$vollist, $volid if $volid;
5449 my $cfg = cfs_read_file
('storage.cfg');
5450 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5458 foreach my $devname (keys %$devinfo) {
5459 my $volid = $devinfo->{$devname}->{volid
};
5462 if ($volid =~ m
|^/|) {
5463 unlink $volid || die 'unlink failed\n';
5465 PVE
::Storage
::vdisk_free
($cfg, $volid);
5467 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5469 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5476 rename($tmpfn, $conffile) ||
5477 die "unable to commit configuration file '$conffile'\n";
5479 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5481 eval { rescan
($vmid, 1); };
5485 sub restore_tar_archive
{
5486 my ($archive, $vmid, $user, $opts) = @_;
5488 if ($archive ne '-') {
5489 my $firstfile = tar_archive_read_firstfile
($archive);
5490 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5491 if $firstfile ne 'qemu-server.conf';
5494 my $storecfg = cfs_read_file
('storage.cfg');
5496 # destroy existing data - keep empty config
5497 my $vmcfgfn = config_file
($vmid);
5498 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5500 my $tocmd = "/usr/lib/qemu-server/qmextract";
5502 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5503 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5504 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5505 $tocmd .= ' --info' if $opts->{info
};
5507 # tar option "xf" does not autodetect compression when read from STDIN,
5508 # so we pipe to zcat
5509 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5510 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5512 my $tmpdir = "/var/tmp/vzdumptmp$$";
5515 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5516 local $ENV{VZDUMP_VMID
} = $vmid;
5517 local $ENV{VZDUMP_USER
} = $user;
5519 my $conffile = config_file
($vmid);
5520 my $tmpfn = "$conffile.$$.tmp";
5522 # disable interrupts (always do cleanups)
5523 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5524 print STDERR
"got interrupt - ignored\n";
5529 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5530 die "interrupted by signal\n";
5533 if ($archive eq '-') {
5534 print "extracting archive from STDIN\n";
5535 run_command
($cmd, input
=> "<&STDIN");
5537 print "extracting archive '$archive'\n";
5541 return if $opts->{info
};
5545 my $statfile = "$tmpdir/qmrestore.stat";
5546 if (my $fd = IO
::File-
>new($statfile, "r")) {
5547 while (defined (my $line = <$fd>)) {
5548 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5549 $map->{$1} = $2 if $1;
5551 print STDERR
"unable to parse line in statfile - $line\n";
5557 my $confsrc = "$tmpdir/qemu-server.conf";
5559 my $srcfd = new IO
::File
($confsrc, "r") ||
5560 die "unable to open file '$confsrc'\n";
5562 my $outfd = new IO
::File
($tmpfn, "w") ||
5563 die "unable to write config for VM $vmid\n";
5565 my $cookie = { netcount
=> 0 };
5566 while (defined (my $line = <$srcfd>)) {
5567 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5579 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5586 rename $tmpfn, $conffile ||
5587 die "unable to commit configuration file '$conffile'\n";
5589 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5591 eval { rescan
($vmid, 1); };
5596 # Internal snapshots
5598 # NOTE: Snapshot create/delete involves several non-atomic
5599 # action, and can take a long time.
5600 # So we try to avoid locking the file and use 'lock' variable
5601 # inside the config file instead.
5603 my $snapshot_copy_config = sub {
5604 my ($source, $dest) = @_;
5606 foreach my $k (keys %$source) {
5607 next if $k eq 'snapshots';
5608 next if $k eq 'snapstate';
5609 next if $k eq 'snaptime';
5610 next if $k eq 'vmstate';
5611 next if $k eq 'lock';
5612 next if $k eq 'digest';
5613 next if $k eq 'description';
5614 next if $k =~ m/^unused\d+$/;
5616 $dest->{$k} = $source->{$k};
5620 my $snapshot_apply_config = sub {
5621 my ($conf, $snap) = @_;
5623 # copy snapshot list
5625 snapshots
=> $conf->{snapshots
},
5628 # keep description and list of unused disks
5629 foreach my $k (keys %$conf) {
5630 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5631 $newconf->{$k} = $conf->{$k};
5634 &$snapshot_copy_config($snap, $newconf);
5639 sub foreach_writable_storage
{
5640 my ($conf, $func) = @_;
5644 foreach my $ds (keys %$conf) {
5645 next if !valid_drivename
($ds);
5647 my $drive = parse_drive
($ds, $conf->{$ds});
5649 next if drive_is_cdrom
($drive);
5651 my $volid = $drive->{file
};
5653 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5654 $sidhash->{$sid} = $sid if $sid;
5657 foreach my $sid (sort keys %$sidhash) {
5662 my $alloc_vmstate_volid = sub {
5663 my ($storecfg, $vmid, $conf, $snapname) = @_;
5665 # Note: we try to be smart when selecting a $target storage
5669 # search shared storage first
5670 foreach_writable_storage
($conf, sub {
5672 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5673 return if !$scfg->{shared
};
5675 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5679 # now search local storage
5680 foreach_writable_storage
($conf, sub {
5682 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5683 return if $scfg->{shared
};
5685 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5689 $target = 'local' if !$target;
5691 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5692 # we abort live save after $conf->{memory}, so we need at max twice that space
5693 my $size = $conf->{memory
}*2 + $driver_state_size;
5695 my $name = "vm-$vmid-state-$snapname";
5696 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5697 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5698 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5703 my $snapshot_prepare = sub {
5704 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5708 my $updatefn = sub {
5710 my $conf = load_config
($vmid);
5712 die "you can't take a snapshot if it's a template\n"
5713 if is_template
($conf);
5717 $conf->{lock} = 'snapshot';
5719 die "snapshot name '$snapname' already used\n"
5720 if defined($conf->{snapshots
}->{$snapname});
5722 my $storecfg = PVE
::Storage
::config
();
5723 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5725 $snap = $conf->{snapshots
}->{$snapname} = {};
5727 if ($save_vmstate && check_running
($vmid)) {
5728 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5731 &$snapshot_copy_config($conf, $snap);
5733 $snap->{snapstate
} = "prepare";
5734 $snap->{snaptime
} = time();
5735 $snap->{description
} = $comment if $comment;
5737 # always overwrite machine if we save vmstate. This makes sure we
5738 # can restore it later using correct machine type
5739 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5741 update_config_nolock
($vmid, $conf, 1);
5744 lock_config
($vmid, $updatefn);
5749 my $snapshot_commit = sub {
5750 my ($vmid, $snapname) = @_;
5752 my $updatefn = sub {
5754 my $conf = load_config
($vmid);
5756 die "missing snapshot lock\n"
5757 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5759 my $has_machine_config = defined($conf->{machine
});
5761 my $snap = $conf->{snapshots
}->{$snapname};
5763 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5765 die "wrong snapshot state\n"
5766 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5768 delete $snap->{snapstate
};
5769 delete $conf->{lock};
5771 my $newconf = &$snapshot_apply_config($conf, $snap);
5773 delete $newconf->{machine
} if !$has_machine_config;
5775 $newconf->{parent
} = $snapname;
5777 update_config_nolock
($vmid, $newconf, 1);
5780 lock_config
($vmid, $updatefn);
5783 sub snapshot_rollback
{
5784 my ($vmid, $snapname) = @_;
5788 my $storecfg = PVE
::Storage
::config
();
5790 my $conf = load_config
($vmid);
5792 my $get_snapshot_config = sub {
5794 die "you can't rollback if vm is a template\n" if is_template
($conf);
5796 my $res = $conf->{snapshots
}->{$snapname};
5798 die "snapshot '$snapname' does not exist\n" if !defined($res);
5803 my $snap = &$get_snapshot_config();
5805 foreach_drive
($snap, sub {
5806 my ($ds, $drive) = @_;
5808 return if drive_is_cdrom
($drive);
5810 my $volid = $drive->{file
};
5812 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5815 my $updatefn = sub {
5817 $conf = load_config
($vmid);
5819 $snap = &$get_snapshot_config();
5821 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5822 if $snap->{snapstate
};
5826 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5829 die "unable to rollback vm $vmid: vm is running\n"
5830 if check_running
($vmid);
5833 $conf->{lock} = 'rollback';
5835 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5836 delete $conf->{lock};
5842 my $has_machine_config = defined($conf->{machine
});
5844 # copy snapshot config to current config
5845 $conf = &$snapshot_apply_config($conf, $snap);
5846 $conf->{parent
} = $snapname;
5848 # Note: old code did not store 'machine', so we try to be smart
5849 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5850 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5851 # we remove the 'machine' configuration if not explicitly specified
5852 # in the original config.
5853 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5856 update_config_nolock
($vmid, $conf, 1);
5858 if (!$prepare && $snap->{vmstate
}) {
5859 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5860 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5864 lock_config
($vmid, $updatefn);
5866 foreach_drive
($snap, sub {
5867 my ($ds, $drive) = @_;
5869 return if drive_is_cdrom
($drive);
5871 my $volid = $drive->{file
};
5872 my $device = "drive-$ds";
5874 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5878 lock_config
($vmid, $updatefn);
5881 my $savevm_wait = sub {
5885 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5886 if (!$stat->{status
}) {
5887 die "savevm not active\n";
5888 } elsif ($stat->{status
} eq 'active') {
5891 } elsif ($stat->{status
} eq 'completed') {
5894 die "query-savevm returned status '$stat->{status}'\n";
5899 sub do_snapshots_with_qemu
{
5900 my ($storecfg, $volid) = @_;
5902 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5904 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5905 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5909 if ($volid =~ m/\.(qcow2|qed)$/){
5916 sub snapshot_create
{
5917 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5919 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5921 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5923 my $config = load_config
($vmid);
5925 my $running = check_running
($vmid);
5927 my $freezefs = $running && $config->{agent
};
5928 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5933 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5934 warn "guest-fsfreeze-freeze problems - $@" if $@;
5938 # create internal snapshots of all drives
5940 my $storecfg = PVE
::Storage
::config
();
5943 if ($snap->{vmstate
}) {
5944 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5945 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5946 &$savevm_wait($vmid);
5948 vm_mon_cmd
($vmid, "savevm-start");
5952 foreach_drive
($snap, sub {
5953 my ($ds, $drive) = @_;
5955 return if drive_is_cdrom
($drive);
5957 my $volid = $drive->{file
};
5958 my $device = "drive-$ds";
5960 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5961 $drivehash->{$ds} = 1;
5967 eval { vm_mon_cmd
($vmid, "savevm-end") };
5971 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5972 warn "guest-fsfreeze-thaw problems - $@" if $@;
5975 # savevm-end is async, we need to wait
5977 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5978 if (!$stat->{bytes
}) {
5981 print "savevm not yet finished\n";
5989 warn "snapshot create failed: starting cleanup\n";
5990 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5995 &$snapshot_commit($vmid, $snapname);
5998 # Note: $drivehash is only set when called from snapshot_create.
5999 sub snapshot_delete
{
6000 my ($vmid, $snapname, $force, $drivehash) = @_;
6007 my $unlink_parent = sub {
6008 my ($confref, $new_parent) = @_;
6010 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6012 $confref->{parent
} = $new_parent;
6014 delete $confref->{parent
};
6019 my $updatefn = sub {
6020 my ($remove_drive) = @_;
6022 my $conf = load_config
($vmid);
6026 die "you can't delete a snapshot if vm is a template\n"
6027 if is_template
($conf);
6030 $snap = $conf->{snapshots
}->{$snapname};
6032 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6034 # remove parent refs
6036 &$unlink_parent($conf, $snap->{parent
});
6037 foreach my $sn (keys %{$conf->{snapshots
}}) {
6038 next if $sn eq $snapname;
6039 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6043 if ($remove_drive) {
6044 if ($remove_drive eq 'vmstate') {
6045 delete $snap->{$remove_drive};
6047 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6048 my $volid = $drive->{file
};
6049 delete $snap->{$remove_drive};
6050 add_unused_volume
($conf, $volid);
6055 $snap->{snapstate
} = 'delete';
6057 delete $conf->{snapshots
}->{$snapname};
6058 delete $conf->{lock} if $drivehash;
6059 foreach my $volid (@$unused) {
6060 add_unused_volume
($conf, $volid);
6064 update_config_nolock
($vmid, $conf, 1);
6067 lock_config
($vmid, $updatefn);
6069 # now remove vmstate file
6071 my $storecfg = PVE
::Storage
::config
();
6073 if ($snap->{vmstate
}) {
6074 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6076 die $err if !$force;
6079 # save changes (remove vmstate from snapshot)
6080 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6083 # now remove all internal snapshots
6084 foreach_drive
($snap, sub {
6085 my ($ds, $drive) = @_;
6087 return if drive_is_cdrom
($drive);
6089 my $volid = $drive->{file
};
6090 my $device = "drive-$ds";
6092 if (!$drivehash || $drivehash->{$ds}) {
6093 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6095 die $err if !$force;
6100 # save changes (remove drive fron snapshot)
6101 lock_config
($vmid, $updatefn, $ds) if !$force;
6102 push @$unused, $volid;
6105 # now cleanup config
6107 lock_config
($vmid, $updatefn);
6111 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6114 foreach_drive
($conf, sub {
6115 my ($ds, $drive) = @_;
6117 return if drive_is_cdrom
($drive);
6118 my $volid = $drive->{file
};
6119 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6122 return $err ?
0 : 1;
6125 sub template_create
{
6126 my ($vmid, $conf, $disk) = @_;
6128 my $storecfg = PVE
::Storage
::config
();
6130 foreach_drive
($conf, sub {
6131 my ($ds, $drive) = @_;
6133 return if drive_is_cdrom
($drive);
6134 return if $disk && $ds ne $disk;
6136 my $volid = $drive->{file
};
6137 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6139 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6140 $drive->{file
} = $voliddst;
6141 $conf->{$ds} = print_drive
($vmid, $drive);
6142 update_config_nolock
($vmid, $conf, 1);
6149 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6152 sub qemu_img_convert
{
6153 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6155 my $storecfg = PVE
::Storage
::config
();
6156 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6157 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6159 if ($src_storeid && $dst_storeid) {
6161 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6163 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6164 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6166 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6167 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6169 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6170 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6173 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6174 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6175 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6179 if($line =~ m/\((\S+)\/100\
%\)/){
6181 my $transferred = int($size * $percent / 100);
6182 my $remaining = $size - $transferred;
6184 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6189 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6191 die "copy failed: $err" if $err;
6195 sub qemu_img_format
{
6196 my ($scfg, $volname) = @_;
6198 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6205 sub qemu_drive_mirror
{
6206 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6208 my $storecfg = PVE
::Storage
::config
();
6209 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6211 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6213 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6215 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6217 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6218 $opts->{format
} = $format if $format;
6220 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6223 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6225 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6226 my $stat = @$stats[0];
6227 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6228 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6230 my $busy = $stat->{busy
};
6231 my $ready = $stat->{ready
};
6233 if (my $total = $stat->{len
}) {
6234 my $transferred = $stat->{offset
} || 0;
6235 my $remaining = $total - $transferred;
6236 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6238 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6242 if ($stat->{ready
} eq 'true') {
6244 last if $vmiddst != $vmid;
6246 # try to switch the disk if source and destination are on the same guest
6247 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6249 die $@ if $@ !~ m/cannot be completed/;
6258 my $cancel_job = sub {
6259 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6261 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6262 my $stat = @$stats[0];
6269 eval { &$cancel_job(); };
6270 die "mirroring error: $err";
6273 if ($vmiddst != $vmid) {
6274 # if we clone a disk for a new target vm, we don't switch the disk
6275 &$cancel_job(); # so we call block-job-cancel
6280 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6281 $newvmid, $storage, $format, $full, $newvollist) = @_;
6286 print "create linked clone of drive $drivename ($drive->{file})\n";
6287 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6288 push @$newvollist, $newvolid;
6290 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6291 $storeid = $storage if $storage;
6293 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6295 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6296 $format = qemu_img_format
($scfg, $volname);
6299 # test if requested format is supported - else use default
6300 my $supported = grep { $_ eq $format } @$validFormats;
6301 $format = $defFormat if !$supported;
6303 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6305 print "create full clone of drive $drivename ($drive->{file})\n";
6306 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6307 push @$newvollist, $newvolid;
6309 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6311 if (!$running || $snapname) {
6312 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6314 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6318 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6321 $disk->{format
} = undef;
6322 $disk->{file
} = $newvolid;
6323 $disk->{size
} = $size;
6328 # this only works if VM is running
6329 sub get_current_qemu_machine
{
6332 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6333 my $res = vm_qmp_command
($vmid, $cmd);
6335 my ($current, $default);
6336 foreach my $e (@$res) {
6337 $default = $e->{name
} if $e->{'is-default'};
6338 $current = $e->{name
} if $e->{'is-current'};
6341 # fallback to the default machine if current is not supported by qemu
6342 return $current || $default || 'pc';
6345 sub qemu_machine_feature_enabled
{
6346 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6351 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6353 $current_major = $3;
6354 $current_minor = $4;
6356 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6358 $current_major = $1;
6359 $current_minor = $2;
6362 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6367 sub qemu_machine_pxe
{
6368 my ($vmid, $conf, $machine) = @_;
6370 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6372 foreach my $opt (keys %$conf) {
6373 next if $opt !~ m/^net(\d+)$/;
6374 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6376 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6377 return $machine.".pxe" if $romfile =~ m/pxe/;
6383 sub qemu_use_old_bios_files
{
6384 my ($machine_type) = @_;
6386 return if !$machine_type;
6388 my $use_old_bios_files = undef;
6390 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6392 $use_old_bios_files = 1;
6394 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6395 # load new efi bios files on migration. So this hack is required to allow
6396 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6397 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6398 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6401 return ($use_old_bios_files, $machine_type);
6408 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6409 my (undef, $id, $function) = @_;
6410 my $res = { id
=> $id, function
=> $function};
6411 push @{$devices->{$id}}, $res;
6417 sub vm_iothreads_list
{
6420 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6423 foreach my $iothread (@$res) {
6424 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6431 my ($conf, $drive) = @_;
6435 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6437 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6443 my $controller = int($drive->{index} / $maxdev);
6444 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6446 return ($maxdev, $controller, $controller_prefix);
6449 # bash completion helper
6451 sub complete_backup_archives
{
6452 my ($cmdname, $pname, $cvalue) = @_;
6454 my $cfg = PVE
::Storage
::config
();
6458 if ($cvalue =~ m/^([^:]+):/) {
6462 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6465 foreach my $id (keys %$data) {
6466 foreach my $item (@{$data->{$id}}) {
6467 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6468 push @$res, $item->{volid
} if defined($item->{volid
});
6475 my $complete_vmid_full = sub {
6478 my $idlist = vmstatus
();
6482 foreach my $id (keys %$idlist) {
6483 my $d = $idlist->{$id};
6484 if (defined($running)) {
6485 next if $d->{template
};
6486 next if $running && $d->{status
} ne 'running';
6487 next if !$running && $d->{status
} eq 'running';
6496 return &$complete_vmid_full();
6499 sub complete_vmid_stopped
{
6500 return &$complete_vmid_full(0);
6503 sub complete_vmid_running
{
6504 return &$complete_vmid_full(1);
6507 sub complete_storage
{
6509 my $cfg = PVE
::Storage
::config
();
6510 my $ids = $cfg->{ids
};
6513 foreach my $sid (keys %$ids) {
6514 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6515 next if !$ids->{$sid}->{content
}->{images
};