1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
36 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
38 # Note about locking: we use flock on the config file protect
39 # against concurent actions.
40 # Aditionaly, we have a 'lock' setting in the config file. This
41 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
42 # allowed when such lock is set. But you can ignore this kind of
43 # lock with the --skiplock flag.
45 cfs_register_file
('/qemu-server/',
49 PVE
::JSONSchema
::register_standard_option
('skiplock', {
50 description
=> "Ignore locks - only root is allowed to use this option.",
55 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
56 description
=> "Some command save/restore state from this location.",
62 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
63 description
=> "The name of the snapshot.",
64 type
=> 'string', format
=> 'pve-configid',
68 #no warnings 'redefine';
71 my ($controller, $vmid, $option, $value) = @_;
73 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
74 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
78 my $nodename = PVE
::INotify
::nodename
();
80 mkdir "/etc/pve/nodes/$nodename";
81 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
84 my $var_run_tmpdir = "/var/run/qemu-server";
85 mkdir $var_run_tmpdir;
87 my $lock_dir = "/var/lock/qemu-server";
90 my $pcisysfs = "/sys/bus/pci";
96 description
=> "Specifies whether a VM will be started during system bootup.",
102 description
=> "Automatic restart after crash (currently ignored).",
107 type
=> 'string', format
=> 'pve-hotplug-features',
108 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
109 default => 'network,disk,usb',
114 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
120 description
=> "Lock/unlock the VM.",
121 enum
=> [qw(migrate backup snapshot rollback)],
126 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
134 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
142 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
149 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
155 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
163 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
164 enum
=> PVE
::Tools
::kvmkeymaplist
(),
169 type
=> 'string', format
=> 'dns-name',
170 description
=> "Set a name for the VM. Only used on the configuration web interface.",
175 description
=> "scsi controller model",
176 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
182 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
187 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
188 description
=> <<EODESC,
189 Used to enable special optimization/features for specific
192 other => unspecified OS
193 wxp => Microsoft Windows XP
194 w2k => Microsoft Windows 2000
195 w2k3 => Microsoft Windows 2003
196 w2k8 => Microsoft Windows 2008
197 wvista => Microsoft Windows Vista
198 win7 => Microsoft Windows 7
199 win8 => Microsoft Windows 8/2012
200 l24 => Linux 2.4 Kernel
201 l26 => Linux 2.6/3.X Kernel
202 solaris => solaris/opensolaris/openindiania kernel
204 other|l24|l26|solaris ... no special behaviour
205 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
211 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
212 pattern
=> '[acdn]{1,4}',
217 type
=> 'string', format
=> 'pve-qm-bootdisk',
218 description
=> "Enable booting from specified disk.",
219 pattern
=> '(ide|sata|scsi|virtio)\d+',
224 description
=> "The number of CPUs. Please use option -sockets instead.",
231 description
=> "The number of CPU sockets.",
238 description
=> "The number of cores per socket.",
245 description
=> "Enable/disable Numa.",
251 description
=> "Number of hotplugged vcpus.",
258 description
=> "Enable/disable ACPI.",
264 description
=> "Enable/disable Qemu GuestAgent.",
270 description
=> "Enable/disable KVM hardware virtualization.",
276 description
=> "Enable/disable time drift fix.",
282 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
287 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
292 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
293 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
297 type
=> 'string', format
=> 'pve-qm-watchdog',
298 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
299 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
304 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
305 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
306 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
309 startup
=> get_standard_option
('pve-startup-order'),
313 description
=> "Enable/disable Template.",
319 description
=> <<EODESCR,
320 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
322 args: -no-reboot -no-hpet
329 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
334 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
338 migrate_downtime
=> {
341 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
347 type
=> 'string', format
=> 'pve-qm-drive',
348 typetext
=> 'volume',
349 description
=> "This is an alias for option -ide2",
353 description
=> "Emulated CPU type.",
355 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
358 parent
=> get_standard_option
('pve-snapshot-name', {
360 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
364 description
=> "Timestamp for snapshots.",
370 type
=> 'string', format
=> 'pve-volume-id',
371 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
374 description
=> "Specific the Qemu machine type.",
376 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
381 description
=> "Specify SMBIOS type 1 fields.",
382 type
=> 'string', format
=> 'pve-qm-smbios1',
383 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
390 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
395 # what about other qemu settings ?
397 #machine => 'string',
410 ##soundhw => 'string',
412 while (my ($k, $v) = each %$confdesc) {
413 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
416 my $MAX_IDE_DISKS = 4;
417 my $MAX_SCSI_DISKS = 14;
418 my $MAX_VIRTIO_DISKS = 16;
419 my $MAX_SATA_DISKS = 6;
420 my $MAX_USB_DEVICES = 5;
422 my $MAX_UNUSED_DISKS = 8;
423 my $MAX_HOSTPCI_DEVICES = 4;
424 my $MAX_SERIAL_PORTS = 4;
425 my $MAX_PARALLEL_PORTS = 3;
427 my $MAX_MEM = 4194304;
428 my $STATICMEM = 1024;
432 type
=> 'string', format
=> 'pve-qm-numanode',
433 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
434 description
=> "numa topology",
436 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
438 for (my $i = 0; $i < $MAX_NUMA; $i++) {
439 $confdesc->{"numa$i"} = $numadesc;
442 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
443 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
444 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
445 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
449 type
=> 'string', format
=> 'pve-qm-net',
450 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
451 description
=> <<EODESCR,
452 Specify network devices.
454 MODEL is one of: $nic_model_list_txt
456 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
457 automatically generated if not specified.
459 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
461 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
463 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
469 The DHCP server assign addresses to the guest starting from 10.0.2.15.
473 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
475 for (my $i = 0; $i < $MAX_NETS; $i++) {
476 $confdesc->{"net$i"} = $netdesc;
483 type
=> 'string', format
=> 'pve-qm-drive',
484 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,serial=serial][,model=model]',
485 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
487 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
491 type
=> 'string', format
=> 'pve-qm-drive',
492 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,queues=<nbqueues>] [,serial=serial]',
493 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
499 type
=> 'string', format
=> 'pve-qm-drive',
500 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,serial=serial]',
501 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
503 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
507 type
=> 'string', format
=> 'pve-qm-drive',
508 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,serial=serial]',
509 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
511 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
515 type
=> 'string', format
=> 'pve-qm-usb-device',
516 typetext
=> 'host=HOSTUSBDEVICE|spice',
517 description
=> <<EODESCR,
518 Configure an USB device (n is 0 to 4). This can be used to
519 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
521 'bus-port(.port)*' (decimal numbers) or
522 'vendor_id:product_id' (hexadeciaml numbers)
524 You can use the 'lsusb -t' command to list existing usb devices.
526 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
528 The value 'spice' can be used to add a usb redirection devices for spice.
532 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
536 type
=> 'string', format
=> 'pve-qm-hostpci',
537 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
538 description
=> <<EODESCR,
539 Map host pci devices. HOSTPCIDEVICE syntax is:
541 'bus:dev.func' (hexadecimal numbers)
543 You can us the 'lspci' command to list existing pci devices.
545 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
547 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
549 Experimental: user reported problems with this option.
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
557 pattern
=> '(/dev/.+|socket)',
558 description
=> <<EODESCR,
559 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
561 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
563 Experimental: user reported problems with this option.
570 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
571 description
=> <<EODESCR,
572 Map host parallel devices (n is 0 to 2).
574 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
576 Experimental: user reported problems with this option.
580 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
581 $confdesc->{"parallel$i"} = $paralleldesc;
584 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
585 $confdesc->{"serial$i"} = $serialdesc;
588 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
589 $confdesc->{"hostpci$i"} = $hostpcidesc;
592 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
593 $drivename_hash->{"ide$i"} = 1;
594 $confdesc->{"ide$i"} = $idedesc;
597 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
598 $drivename_hash->{"sata$i"} = 1;
599 $confdesc->{"sata$i"} = $satadesc;
602 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
603 $drivename_hash->{"scsi$i"} = 1;
604 $confdesc->{"scsi$i"} = $scsidesc ;
607 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
608 $drivename_hash->{"virtio$i"} = 1;
609 $confdesc->{"virtio$i"} = $virtiodesc;
612 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
613 $confdesc->{"usb$i"} = $usbdesc;
618 type
=> 'string', format
=> 'pve-volume-id',
619 description
=> "Reference to unused volumes.",
622 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
623 $confdesc->{"unused$i"} = $unuseddesc;
626 my $kvm_api_version = 0;
630 return $kvm_api_version if $kvm_api_version;
632 my $fh = IO
::File-
>new("</dev/kvm") ||
635 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
636 $kvm_api_version = $v;
641 return $kvm_api_version;
644 my $kvm_user_version;
646 sub kvm_user_version
{
648 return $kvm_user_version if $kvm_user_version;
650 $kvm_user_version = 'unknown';
652 my $tmp = `kvm -help 2>/dev/null`;
654 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
655 $kvm_user_version = $2;
658 return $kvm_user_version;
662 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
665 # order is important - used to autoselect boot disk
666 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
667 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
668 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
669 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
672 sub valid_drivename
{
675 return defined($drivename_hash->{$dev});
680 return defined($confdesc->{$key});
684 return $nic_model_list;
687 sub os_list_description
{
692 w2k
=> 'Windows 2000',
693 w2k3
=>, 'Windows 2003',
694 w2k8
=> 'Windows 2008',
695 wvista
=> 'Windows Vista',
697 win8
=> 'Windows 8/2012',
707 return $cdrom_path if $cdrom_path;
709 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
710 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
711 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
715 my ($storecfg, $vmid, $cdrom) = @_;
717 if ($cdrom eq 'cdrom') {
718 return get_cdrom_path
();
719 } elsif ($cdrom eq 'none') {
721 } elsif ($cdrom =~ m
|^/|) {
724 return PVE
::Storage
::path
($storecfg, $cdrom);
728 # try to convert old style file names to volume IDs
729 sub filename_to_volume_id
{
730 my ($vmid, $file, $media) = @_;
732 if (!($file eq 'none' || $file eq 'cdrom' ||
733 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
735 return undef if $file =~ m
|/|;
737 if ($media && $media eq 'cdrom') {
738 $file = "local:iso/$file";
740 $file = "local:$vmid/$file";
747 sub verify_media_type
{
748 my ($opt, $vtype, $media) = @_;
753 if ($media eq 'disk') {
755 } elsif ($media eq 'cdrom') {
758 die "internal error";
761 return if ($vtype eq $etype);
763 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
766 sub cleanup_drive_path
{
767 my ($opt, $storecfg, $drive) = @_;
769 # try to convert filesystem paths to volume IDs
771 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
772 ($drive->{file
} !~ m
|^/dev/.+|) &&
773 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
774 ($drive->{file
} !~ m/^\d+$/)) {
775 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
776 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
777 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
778 verify_media_type
($opt, $vtype, $drive->{media
});
779 $drive->{file
} = $volid;
782 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
785 sub create_conf_nolock
{
786 my ($vmid, $settings) = @_;
788 my $filename = config_file
($vmid);
790 die "configuration file '$filename' already exists\n" if -f
$filename;
792 my $defaults = load_defaults
();
794 $settings->{name
} = "vm$vmid" if !$settings->{name
};
795 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
798 foreach my $opt (keys %$settings) {
799 next if !$confdesc->{$opt};
801 my $value = $settings->{$opt};
804 $data .= "$opt: $value\n";
807 PVE
::Tools
::file_set_contents
($filename, $data);
810 sub parse_hotplug_features
{
815 return $res if $data eq '0';
817 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
819 foreach my $feature (PVE
::Tools
::split_list
($data)) {
820 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
823 warn "ignoring unknown hotplug feature '$feature'\n";
829 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
830 sub pve_verify_hotplug_features
{
831 my ($value, $noerr) = @_;
833 return $value if parse_hotplug_features
($value);
835 return undef if $noerr;
837 die "unable to parse hotplug option\n";
840 my $parse_size = sub {
843 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
844 my ($size, $unit) = ($1, $3);
847 $size = $size * 1024;
848 } elsif ($unit eq 'M') {
849 $size = $size * 1024 * 1024;
850 } elsif ($unit eq 'G') {
851 $size = $size * 1024 * 1024 * 1024;
857 my $format_size = sub {
862 my $kb = int($size/1024);
863 return $size if $kb*1024 != $size;
865 my $mb = int($kb/1024);
866 return "${kb}K" if $mb*1024 != $kb;
868 my $gb = int($mb/1024);
869 return "${mb}M" if $gb*1024 != $mb;
874 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
875 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
876 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
877 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
878 # [,serial=serial][,model=model]
881 my ($key, $data) = @_;
885 # $key may be undefined - used to verify JSON parameters
886 if (!defined($key)) {
887 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
889 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
890 $res->{interface
} = $1;
896 foreach my $p (split (/,/, $data)) {
897 next if $p =~ m/^\s*$/;
899 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues|serial|model)=(.+)$/) {
900 my ($k, $v) = ($1, $2);
902 $k = 'file' if $k eq 'volume';
904 return undef if defined $res->{$k};
906 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
907 return undef if !$v || $v !~ m/^\d+/;
909 $v = sprintf("%.3f", $v / (1024*1024));
913 if (!$res->{file
} && $p !~ m/=/) {
921 return undef if !$res->{file
};
923 return undef if $res->{cache
} &&
924 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
925 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
926 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
927 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
928 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
929 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
930 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
931 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
932 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
933 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
934 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
935 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
936 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
937 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
938 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
940 return undef if $res->{mbps_rd
} && $res->{mbps
};
941 return undef if $res->{mbps_wr
} && $res->{mbps
};
943 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
944 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
945 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
946 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
947 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{iops_rd
} && $res->{iops
};
951 return undef if $res->{iops_wr
} && $res->{iops
};
954 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
955 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
956 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
957 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
958 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
959 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
962 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
965 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
966 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
967 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
968 return undef if $res->{interface
} eq 'virtio';
971 # rerror does not work with scsi drives
972 if ($res->{rerror
}) {
973 return undef if $res->{interface
} eq 'scsi';
979 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
982 my ($vmid, $drive) = @_;
985 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
986 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
989 if ($drive->{size
}) {
990 $opts .= ",size=" . &$format_size($drive->{size
});
993 if (my $model = $drive->{model
}) {
994 $opts .= ",model=$model";
997 return "$drive->{file}$opts";
1001 my($fh, $noerr) = @_;
1004 my $SG_GET_VERSION_NUM = 0x2282;
1006 my $versionbuf = "\x00" x
8;
1007 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1009 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1012 my $version = unpack("I", $versionbuf);
1013 if ($version < 30000) {
1014 die "scsi generic interface too old\n" if !$noerr;
1018 my $buf = "\x00" x
36;
1019 my $sensebuf = "\x00" x
8;
1020 my $cmd = pack("C x3 C x1", 0x12, 36);
1022 # see /usr/include/scsi/sg.h
1023 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1025 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1026 length($sensebuf), 0, length($buf), $buf,
1027 $cmd, $sensebuf, 6000);
1029 $ret = ioctl($fh, $SG_IO, $packet);
1031 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1035 my @res = unpack($sg_io_hdr_t, $packet);
1036 if ($res[17] || $res[18]) {
1037 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1042 (my $byte0, my $byte1, $res->{vendor
},
1043 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1045 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1046 $res->{type
} = $byte0 & 31;
1054 my $fh = IO
::File-
>new("+<$path") || return undef;
1055 my $res = scsi_inquiry
($fh, 1);
1061 sub machine_type_is_q35
{
1064 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1067 sub print_tabletdevice_full
{
1070 my $q35 = machine_type_is_q35
($conf);
1072 # we use uhci for old VMs because tablet driver was buggy in older qemu
1073 my $usbbus = $q35 ?
"ehci" : "uhci";
1075 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1078 sub print_drivedevice_full
{
1079 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1084 if ($drive->{interface
} eq 'virtio') {
1085 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1086 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1087 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1088 } elsif ($drive->{interface
} eq 'scsi') {
1090 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1091 my $unit = $drive->{index} % $maxdev;
1092 my $devicetype = 'hd';
1094 if (drive_is_cdrom
($drive)) {
1097 if ($drive->{file
} =~ m
|^/|) {
1098 $path = $drive->{file
};
1100 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1103 if($path =~ m/^iscsi\:\/\
//){
1104 $devicetype = 'generic';
1106 if (my $info = path_is_scsi
($path)) {
1107 if ($info->{type
} == 0) {
1108 $devicetype = 'block';
1109 } elsif ($info->{type
} == 1) { # tape
1110 $devicetype = 'generic';
1116 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1117 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1122 } elsif ($drive->{interface
} eq 'ide'){
1124 my $controller = int($drive->{index} / $maxdev);
1125 my $unit = $drive->{index} % $maxdev;
1126 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1128 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1129 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1130 $device .= ",model=$model";
1132 } elsif ($drive->{interface
} eq 'sata'){
1133 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1134 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1135 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1136 } elsif ($drive->{interface
} eq 'usb') {
1138 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1140 die "unsupported interface type";
1143 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1148 sub get_initiator_name
{
1151 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1152 while (defined(my $line = <$fh>)) {
1153 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1162 sub print_drive_full
{
1163 my ($storecfg, $vmid, $drive) = @_;
1166 my $volid = $drive->{file
};
1169 if (drive_is_cdrom
($drive)) {
1170 $path = get_iso_path
($storecfg, $vmid, $volid);
1172 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1174 $path = PVE
::Storage
::path
($storecfg, $volid);
1175 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1176 $format = qemu_img_format
($scfg, $volname);
1183 foreach my $o (@qemu_drive_options) {
1184 next if $o eq 'bootindex';
1185 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1188 $opts .= ",format=$format" if $format && !$drive->{format
};
1190 foreach my $o (qw(bps bps_rd bps_wr)) {
1191 my $v = $drive->{"m$o"};
1192 $opts .= ",$o=" . int($v*1024*1024) if $v;
1195 my $cache_direct = 0;
1197 if (my $cache = $drive->{cache
}) {
1198 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1199 } elsif (!drive_is_cdrom
($drive)) {
1200 $opts .= ",cache=none";
1204 # aio native works only with O_DIRECT
1205 if (!$drive->{aio
}) {
1207 $opts .= ",aio=native";
1209 $opts .= ",aio=threads";
1213 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1214 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1216 my $pathinfo = $path ?
"file=$path," : '';
1218 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1221 sub print_netdevice_full
{
1222 my ($vmid, $conf, $net, $netid, $bridges) = @_;
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
} ;
1242 sub print_netdev_full
{
1243 my ($vmid, $conf, $net, $netid) = @_;
1246 if ($netid =~ m/^net(\d+)$/) {
1250 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1252 my $ifname = "tap${vmid}i$i";
1254 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1255 die "interface name '$ifname' is too long (max 15 character)\n"
1256 if length($ifname) >= 16;
1258 my $vhostparam = '';
1259 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1261 my $vmname = $conf->{name
} || "vm$vmid";
1265 if ($net->{bridge
}) {
1266 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1268 $netdev = "type=user,id=$netid,hostname=$vmname";
1271 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1276 sub drive_is_cdrom
{
1279 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1288 foreach my $kvp (split(/,/, $data)) {
1290 if ($kvp =~ m/^memory=(\S+)$/) {
1291 $res->{memory
} = $1;
1292 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1293 $res->{policy
} = $1;
1294 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1295 $res->{cpus
}->{start
} = $1;
1296 $res->{cpus
}->{end
} = $3;
1297 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1298 $res->{hostnodes
}->{start
} = $1;
1299 $res->{hostnodes
}->{end
} = $3;
1311 return undef if !$value;
1314 my @list = split(/,/, $value);
1318 foreach my $kv (@list) {
1320 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1323 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1326 my $pcidevices = lspci
($2);
1327 $res->{pciid
} = $pcidevices->{$2};
1329 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1330 $res->{rombar
} = $1;
1331 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1332 $res->{'x-vga'} = $1;
1333 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1334 $res->{pcie
} = 1 if $1 == 1;
1336 warn "unknown hostpci setting '$kv'\n";
1340 return undef if !$found;
1345 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1351 foreach my $kvp (split(/,/, $data)) {
1353 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) {
1355 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1356 $res->{model
} = $model;
1357 $res->{macaddr
} = $mac;
1358 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1359 $res->{bridge
} = $1;
1360 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1361 $res->{queues
} = $1;
1362 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1364 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1366 } elsif ($kvp =~ m/^firewall=([01])$/) {
1367 $res->{firewall
} = $1;
1368 } elsif ($kvp =~ m/^link_down=([01])$/) {
1369 $res->{link_down
} = $1;
1376 return undef if !$res->{model
};
1384 my $res = "$net->{model}";
1385 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1386 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1387 $res .= ",rate=$net->{rate}" if $net->{rate
};
1388 $res .= ",tag=$net->{tag}" if $net->{tag
};
1389 $res .= ",firewall=1" if $net->{firewall
};
1390 $res .= ",link_down=1" if $net->{link_down
};
1391 $res .= ",queues=$net->{queues}" if $net->{queues
};
1396 sub add_random_macs
{
1397 my ($settings) = @_;
1399 foreach my $opt (keys %$settings) {
1400 next if $opt !~ m/^net(\d+)$/;
1401 my $net = parse_net
($settings->{$opt});
1403 $settings->{$opt} = print_net
($net);
1407 sub add_unused_volume
{
1408 my ($config, $volid) = @_;
1411 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1412 my $test = "unused$ind";
1413 if (my $vid = $config->{$test}) {
1414 return if $vid eq $volid; # do not add duplicates
1420 die "To many unused volume - please delete them first.\n" if !$key;
1422 $config->{$key} = $volid;
1427 sub vm_is_volid_owner
{
1428 my ($storecfg, $vmid, $volid) = @_;
1430 if ($volid !~ m
|^/|) {
1432 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1433 if ($owner && ($owner == $vmid)) {
1441 sub split_flagged_list
{
1442 my $text = shift || '';
1443 $text =~ s/[,;]/ /g;
1445 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1448 sub join_flagged_list
{
1449 my ($how, $lst) = @_;
1450 join $how, map { $lst->{$_} . $_ } keys %$lst;
1453 sub vmconfig_delete_pending_option
{
1454 my ($conf, $key, $force) = @_;
1456 delete $conf->{pending
}->{$key};
1457 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1458 $pending_delete_hash->{$key} = $force ?
'!' : '';
1459 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1462 sub vmconfig_undelete_pending_option
{
1463 my ($conf, $key) = @_;
1465 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1466 delete $pending_delete_hash->{$key};
1468 if (%$pending_delete_hash) {
1469 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1471 delete $conf->{pending
}->{delete};
1475 sub vmconfig_register_unused_drive
{
1476 my ($storecfg, $vmid, $conf, $drive) = @_;
1478 if (!drive_is_cdrom
($drive)) {
1479 my $volid = $drive->{file
};
1480 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1481 add_unused_volume
($conf, $volid, $vmid);
1486 sub vmconfig_cleanup_pending
{
1489 # remove pending changes when nothing changed
1491 foreach my $opt (keys %{$conf->{pending
}}) {
1492 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1494 delete $conf->{pending
}->{$opt};
1498 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1499 my $pending_delete_hash = {};
1500 while (my ($opt, $force) = each %$current_delete_hash) {
1501 if (defined($conf->{$opt})) {
1502 $pending_delete_hash->{$opt} = $force;
1508 if (%$pending_delete_hash) {
1509 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1511 delete $conf->{pending
}->{delete};
1517 my $valid_smbios1_options = {
1518 manufacturer
=> '\S+',
1522 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1527 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1533 foreach my $kvp (split(/,/, $data)) {
1534 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1535 my ($k, $v) = split(/=/, $kvp);
1536 return undef if !defined($k) || !defined($v);
1537 return undef if !$valid_smbios1_options->{$k};
1538 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1549 foreach my $k (keys %$smbios1) {
1550 next if !defined($smbios1->{$k});
1551 next if !$valid_smbios1_options->{$k};
1552 $data .= ',' if $data;
1553 $data .= "$k=$smbios1->{$k}";
1558 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1559 sub verify_smbios1
{
1560 my ($value, $noerr) = @_;
1562 return $value if parse_smbios1
($value);
1564 return undef if $noerr;
1566 die "unable to parse smbios (type 1) options\n";
1569 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1570 sub verify_bootdisk
{
1571 my ($value, $noerr) = @_;
1573 return $value if valid_drivename
($value);
1575 return undef if $noerr;
1577 die "invalid boot disk '$value'\n";
1580 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1582 my ($value, $noerr) = @_;
1584 return $value if parse_numa
($value);
1586 return undef if $noerr;
1588 die "unable to parse numa options\n";
1591 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1593 my ($value, $noerr) = @_;
1595 return $value if parse_net
($value);
1597 return undef if $noerr;
1599 die "unable to parse network options\n";
1602 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1604 my ($value, $noerr) = @_;
1606 return $value if parse_drive
(undef, $value);
1608 return undef if $noerr;
1610 die "unable to parse drive options\n";
1613 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1614 sub verify_hostpci
{
1615 my ($value, $noerr) = @_;
1617 return $value if parse_hostpci
($value);
1619 return undef if $noerr;
1621 die "unable to parse pci id\n";
1624 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1625 sub verify_watchdog
{
1626 my ($value, $noerr) = @_;
1628 return $value if parse_watchdog
($value);
1630 return undef if $noerr;
1632 die "unable to parse watchdog options\n";
1635 sub parse_watchdog
{
1638 return undef if !$value;
1642 foreach my $p (split(/,/, $value)) {
1643 next if $p =~ m/^\s*$/;
1645 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1647 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1648 $res->{action
} = $2;
1657 sub parse_usb_device
{
1660 return undef if !$value;
1662 my @dl = split(/,/, $value);
1666 foreach my $v (@dl) {
1667 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1669 $res->{vendorid
} = $2;
1670 $res->{productid
} = $4;
1671 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1673 $res->{hostbus
} = $1;
1674 $res->{hostport
} = $2;
1675 } elsif ($v =~ m/^spice$/) {
1682 return undef if !$found;
1687 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1688 sub verify_usb_device
{
1689 my ($value, $noerr) = @_;
1691 return $value if parse_usb_device
($value);
1693 return undef if $noerr;
1695 die "unable to parse usb device\n";
1698 # add JSON properties for create and set function
1699 sub json_config_properties
{
1702 foreach my $opt (keys %$confdesc) {
1703 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1704 $prop->{$opt} = $confdesc->{$opt};
1711 my ($key, $value) = @_;
1713 die "unknown setting '$key'\n" if !$confdesc->{$key};
1715 my $type = $confdesc->{$key}->{type
};
1717 if (!defined($value)) {
1718 die "got undefined value\n";
1721 if ($value =~ m/[\n\r]/) {
1722 die "property contains a line feed\n";
1725 if ($type eq 'boolean') {
1726 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1727 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1728 die "type check ('boolean') failed - got '$value'\n";
1729 } elsif ($type eq 'integer') {
1730 return int($1) if $value =~ m/^(\d+)$/;
1731 die "type check ('integer') failed - got '$value'\n";
1732 } elsif ($type eq 'number') {
1733 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1734 die "type check ('number') failed - got '$value'\n";
1735 } elsif ($type eq 'string') {
1736 if (my $fmt = $confdesc->{$key}->{format
}) {
1737 if ($fmt eq 'pve-qm-drive') {
1738 # special case - we need to pass $key to parse_drive()
1739 my $drive = parse_drive
($key, $value);
1740 return $value if $drive;
1741 die "unable to parse drive options\n";
1743 PVE
::JSONSchema
::check_format
($fmt, $value);
1746 $value =~ s/^\"(.*)\"$/$1/;
1749 die "internal error"
1753 sub lock_config_full
{
1754 my ($vmid, $timeout, $code, @param) = @_;
1756 my $filename = config_file_lock
($vmid);
1758 my $res = lock_file
($filename, $timeout, $code, @param);
1765 sub lock_config_mode
{
1766 my ($vmid, $timeout, $shared, $code, @param) = @_;
1768 my $filename = config_file_lock
($vmid);
1770 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1778 my ($vmid, $code, @param) = @_;
1780 return lock_config_full
($vmid, 10, $code, @param);
1783 sub cfs_config_path
{
1784 my ($vmid, $node) = @_;
1786 $node = $nodename if !$node;
1787 return "nodes/$node/qemu-server/$vmid.conf";
1790 sub check_iommu_support
{
1791 #fixme : need to check IOMMU support
1792 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1800 my ($vmid, $node) = @_;
1802 my $cfspath = cfs_config_path
($vmid, $node);
1803 return "/etc/pve/$cfspath";
1806 sub config_file_lock
{
1809 return "$lock_dir/lock-$vmid.conf";
1815 my $conf = config_file
($vmid);
1816 utime undef, undef, $conf;
1820 my ($storecfg, $vmid, $keep_empty_config) = @_;
1822 my $conffile = config_file
($vmid);
1824 my $conf = load_config
($vmid);
1828 # only remove disks owned by this VM
1829 foreach_drive
($conf, sub {
1830 my ($ds, $drive) = @_;
1832 return if drive_is_cdrom
($drive);
1834 my $volid = $drive->{file
};
1836 return if !$volid || $volid =~ m
|^/|;
1838 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1839 return if !$path || !$owner || ($owner != $vmid);
1841 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1844 if ($keep_empty_config) {
1845 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1850 # also remove unused disk
1852 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1855 PVE
::Storage
::foreach_volid
($dl, sub {
1856 my ($volid, $sid, $volname, $d) = @_;
1857 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1867 my ($vmid, $node) = @_;
1869 my $cfspath = cfs_config_path
($vmid, $node);
1871 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1873 die "no such VM ('$vmid')\n" if !defined($conf);
1878 sub parse_vm_config
{
1879 my ($filename, $raw) = @_;
1881 return undef if !defined($raw);
1884 digest
=> Digest
::SHA
::sha1_hex
($raw),
1889 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1890 || die "got strange filename '$filename'";
1898 my @lines = split(/\n/, $raw);
1899 foreach my $line (@lines) {
1900 next if $line =~ m/^\s*$/;
1902 if ($line =~ m/^\[PENDING\]\s*$/i) {
1903 $section = 'pending';
1904 if (defined($descr)) {
1906 $conf->{description
} = $descr;
1909 $conf = $res->{$section} = {};
1912 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1914 if (defined($descr)) {
1916 $conf->{description
} = $descr;
1919 $conf = $res->{snapshots
}->{$section} = {};
1923 if ($line =~ m/^\#(.*)\s*$/) {
1924 $descr = '' if !defined($descr);
1925 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1929 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1930 $descr = '' if !defined($descr);
1931 $descr .= PVE
::Tools
::decode_text
($2);
1932 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1933 $conf->{snapstate
} = $1;
1934 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1937 $conf->{$key} = $value;
1938 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1940 if ($section eq 'pending') {
1941 $conf->{delete} = $value; # we parse this later
1943 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1945 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1948 eval { $value = check_type
($key, $value); };
1950 warn "vm $vmid - unable to parse value of '$key' - $@";
1952 my $fmt = $confdesc->{$key}->{format
};
1953 if ($fmt && $fmt eq 'pve-qm-drive') {
1954 my $v = parse_drive
($key, $value);
1955 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1956 $v->{file
} = $volid;
1957 $value = print_drive
($vmid, $v);
1959 warn "vm $vmid - unable to parse value of '$key'\n";
1964 if ($key eq 'cdrom') {
1965 $conf->{ide2
} = $value;
1967 $conf->{$key} = $value;
1973 if (defined($descr)) {
1975 $conf->{description
} = $descr;
1977 delete $res->{snapstate
}; # just to be sure
1982 sub write_vm_config
{
1983 my ($filename, $conf) = @_;
1985 delete $conf->{snapstate
}; # just to be sure
1987 if ($conf->{cdrom
}) {
1988 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1989 $conf->{ide2
} = $conf->{cdrom
};
1990 delete $conf->{cdrom
};
1993 # we do not use 'smp' any longer
1994 if ($conf->{sockets
}) {
1995 delete $conf->{smp
};
1996 } elsif ($conf->{smp
}) {
1997 $conf->{sockets
} = $conf->{smp
};
1998 delete $conf->{cores
};
1999 delete $conf->{smp
};
2002 my $used_volids = {};
2004 my $cleanup_config = sub {
2005 my ($cref, $pending, $snapname) = @_;
2007 foreach my $key (keys %$cref) {
2008 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2009 $key eq 'snapstate' || $key eq 'pending';
2010 my $value = $cref->{$key};
2011 if ($key eq 'delete') {
2012 die "propertry 'delete' is only allowed in [PENDING]\n"
2014 # fixme: check syntax?
2017 eval { $value = check_type
($key, $value); };
2018 die "unable to parse value of '$key' - $@" if $@;
2020 $cref->{$key} = $value;
2022 if (!$snapname && valid_drivename
($key)) {
2023 my $drive = parse_drive
($key, $value);
2024 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2029 &$cleanup_config($conf);
2031 &$cleanup_config($conf->{pending
}, 1);
2033 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2034 die "internal error" if $snapname eq 'pending';
2035 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2038 # remove 'unusedX' settings if we re-add a volume
2039 foreach my $key (keys %$conf) {
2040 my $value = $conf->{$key};
2041 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2042 delete $conf->{$key};
2046 my $generate_raw_config = sub {
2047 my ($conf, $pending) = @_;
2051 # add description as comment to top of file
2052 if (defined(my $descr = $conf->{description
})) {
2054 foreach my $cl (split(/\n/, $descr)) {
2055 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2058 $raw .= "#\n" if $pending;
2062 foreach my $key (sort keys %$conf) {
2063 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2064 $raw .= "$key: $conf->{$key}\n";
2069 my $raw = &$generate_raw_config($conf);
2071 if (scalar(keys %{$conf->{pending
}})){
2072 $raw .= "\n[PENDING]\n";
2073 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2076 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2077 $raw .= "\n[$snapname]\n";
2078 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2084 sub update_config_nolock
{
2085 my ($vmid, $conf, $skiplock) = @_;
2087 check_lock
($conf) if !$skiplock;
2089 my $cfspath = cfs_config_path
($vmid);
2091 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2095 my ($vmid, $conf, $skiplock) = @_;
2097 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2104 # we use static defaults from our JSON schema configuration
2105 foreach my $key (keys %$confdesc) {
2106 if (defined(my $default = $confdesc->{$key}->{default})) {
2107 $res->{$key} = $default;
2111 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2112 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2118 my $vmlist = PVE
::Cluster
::get_vmlist
();
2120 return $res if !$vmlist || !$vmlist->{ids
};
2121 my $ids = $vmlist->{ids
};
2123 foreach my $vmid (keys %$ids) {
2124 my $d = $ids->{$vmid};
2125 next if !$d->{node
} || $d->{node
} ne $nodename;
2126 next if !$d->{type
} || $d->{type
} ne 'qemu';
2127 $res->{$vmid}->{exists} = 1;
2132 # test if VM uses local resources (to prevent migration)
2133 sub check_local_resources
{
2134 my ($conf, $noerr) = @_;
2138 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2139 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2141 foreach my $k (keys %$conf) {
2142 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2143 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2146 die "VM uses local resources\n" if $loc_res && !$noerr;
2151 # check if used storages are available on all nodes (use by migrate)
2152 sub check_storage_availability
{
2153 my ($storecfg, $conf, $node) = @_;
2155 foreach_drive
($conf, sub {
2156 my ($ds, $drive) = @_;
2158 my $volid = $drive->{file
};
2161 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2164 # check if storage is available on both nodes
2165 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2166 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2170 # list nodes where all VM images are available (used by has_feature API)
2172 my ($conf, $storecfg) = @_;
2174 my $nodelist = PVE
::Cluster
::get_nodelist
();
2175 my $nodehash = { map { $_ => 1 } @$nodelist };
2176 my $nodename = PVE
::INotify
::nodename
();
2178 foreach_drive
($conf, sub {
2179 my ($ds, $drive) = @_;
2181 my $volid = $drive->{file
};
2184 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2186 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2187 if ($scfg->{disable
}) {
2189 } elsif (my $avail = $scfg->{nodes
}) {
2190 foreach my $node (keys %$nodehash) {
2191 delete $nodehash->{$node} if !$avail->{$node};
2193 } elsif (!$scfg->{shared
}) {
2194 foreach my $node (keys %$nodehash) {
2195 delete $nodehash->{$node} if $node ne $nodename
2207 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2211 my ($pidfile, $pid) = @_;
2213 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2217 return undef if !$line;
2218 my @param = split(/\0/, $line);
2220 my $cmd = $param[0];
2221 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2223 for (my $i = 0; $i < scalar (@param); $i++) {
2226 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2227 my $p = $param[$i+1];
2228 return 1 if $p && ($p eq $pidfile);
2237 my ($vmid, $nocheck, $node) = @_;
2239 my $filename = config_file
($vmid, $node);
2241 die "unable to find configuration file for VM $vmid - no such machine\n"
2242 if !$nocheck && ! -f
$filename;
2244 my $pidfile = pidfile_name
($vmid);
2246 if (my $fd = IO
::File-
>new("<$pidfile")) {
2251 my $mtime = $st->mtime;
2252 if ($mtime > time()) {
2253 warn "file '$filename' modified in future\n";
2256 if ($line =~ m/^(\d+)$/) {
2258 if (check_cmdline
($pidfile, $pid)) {
2259 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2271 my $vzlist = config_list
();
2273 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2275 while (defined(my $de = $fd->read)) {
2276 next if $de !~ m/^(\d+)\.pid$/;
2278 next if !defined($vzlist->{$vmid});
2279 if (my $pid = check_running
($vmid)) {
2280 $vzlist->{$vmid}->{pid
} = $pid;
2288 my ($storecfg, $conf) = @_;
2290 my $bootdisk = $conf->{bootdisk
};
2291 return undef if !$bootdisk;
2292 return undef if !valid_drivename
($bootdisk);
2294 return undef if !$conf->{$bootdisk};
2296 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2297 return undef if !defined($drive);
2299 return undef if drive_is_cdrom
($drive);
2301 my $volid = $drive->{file
};
2302 return undef if !$volid;
2304 return $drive->{size
};
2307 my $last_proc_pid_stat;
2309 # get VM status information
2310 # This must be fast and should not block ($full == false)
2311 # We only query KVM using QMP if $full == true (this can be slow)
2313 my ($opt_vmid, $full) = @_;
2317 my $storecfg = PVE
::Storage
::config
();
2319 my $list = vzlist
();
2320 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2322 my $cpucount = $cpuinfo->{cpus
} || 1;
2324 foreach my $vmid (keys %$list) {
2325 next if $opt_vmid && ($vmid ne $opt_vmid);
2327 my $cfspath = cfs_config_path
($vmid);
2328 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2331 $d->{pid
} = $list->{$vmid}->{pid
};
2333 # fixme: better status?
2334 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2336 my $size = disksize
($storecfg, $conf);
2337 if (defined($size)) {
2338 $d->{disk
} = 0; # no info available
2339 $d->{maxdisk
} = $size;
2345 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2346 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2347 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2349 $d->{name
} = $conf->{name
} || "VM $vmid";
2350 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2352 if ($conf->{balloon
}) {
2353 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2354 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2365 $d->{diskwrite
} = 0;
2367 $d->{template
} = is_template
($conf);
2372 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2373 foreach my $dev (keys %$netdev) {
2374 next if $dev !~ m/^tap([1-9]\d*)i/;
2376 my $d = $res->{$vmid};
2379 $d->{netout
} += $netdev->{$dev}->{receive
};
2380 $d->{netin
} += $netdev->{$dev}->{transmit
};
2383 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2384 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2389 my $ctime = gettimeofday
;
2391 foreach my $vmid (keys %$list) {
2393 my $d = $res->{$vmid};
2394 my $pid = $d->{pid
};
2397 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2398 next if !$pstat; # not running
2400 my $used = $pstat->{utime} + $pstat->{stime
};
2402 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2404 if ($pstat->{vsize
}) {
2405 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2408 my $old = $last_proc_pid_stat->{$pid};
2410 $last_proc_pid_stat->{$pid} = {
2418 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2420 if ($dtime > 1000) {
2421 my $dutime = $used - $old->{used
};
2423 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2424 $last_proc_pid_stat->{$pid} = {
2430 $d->{cpu
} = $old->{cpu
};
2434 return $res if !$full;
2436 my $qmpclient = PVE
::QMPClient-
>new();
2438 my $ballooncb = sub {
2439 my ($vmid, $resp) = @_;
2441 my $info = $resp->{'return'};
2442 return if !$info->{max_mem
};
2444 my $d = $res->{$vmid};
2446 # use memory assigned to VM
2447 $d->{maxmem
} = $info->{max_mem
};
2448 $d->{balloon
} = $info->{actual
};
2450 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2451 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2452 $d->{freemem
} = $info->{free_mem
};
2455 $d->{ballooninfo
} = $info;
2458 my $blockstatscb = sub {
2459 my ($vmid, $resp) = @_;
2460 my $data = $resp->{'return'} || [];
2461 my $totalrdbytes = 0;
2462 my $totalwrbytes = 0;
2464 for my $blockstat (@$data) {
2465 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2466 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2468 $blockstat->{device
} =~ s/drive-//;
2469 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2471 $res->{$vmid}->{diskread
} = $totalrdbytes;
2472 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2475 my $statuscb = sub {
2476 my ($vmid, $resp) = @_;
2478 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2479 # this fails if ballon driver is not loaded, so this must be
2480 # the last commnand (following command are aborted if this fails).
2481 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2483 my $status = 'unknown';
2484 if (!defined($status = $resp->{'return'}->{status
})) {
2485 warn "unable to get VM status\n";
2489 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2492 foreach my $vmid (keys %$list) {
2493 next if $opt_vmid && ($vmid ne $opt_vmid);
2494 next if !$res->{$vmid}->{pid
}; # not running
2495 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2498 $qmpclient->queue_execute(undef, 1);
2500 foreach my $vmid (keys %$list) {
2501 next if $opt_vmid && ($vmid ne $opt_vmid);
2502 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2509 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2512 my $current_size = 1024;
2513 my $dimm_size = 512;
2514 return if $current_size == $memory;
2516 for (my $j = 0; $j < 8; $j++) {
2517 for (my $i = 0; $i < 32; $i++) {
2518 my $name = "dimm${dimm_id}";
2520 my $numanode = $i % $sockets;
2521 $current_size += $dimm_size;
2522 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2523 return $current_size if $current_size >= $memory;
2529 sub foreach_reverse_dimm
{
2530 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2533 my $current_size = 4177920;
2534 my $dimm_size = 65536;
2535 return if $current_size == $memory;
2537 for (my $j = 0; $j < 8; $j++) {
2538 for (my $i = 0; $i < 32; $i++) {
2539 my $name = "dimm${dimm_id}";
2541 my $numanode = $i % $sockets;
2542 $current_size -= $dimm_size;
2543 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2544 return $current_size if $current_size <= $memory;
2551 my ($conf, $func) = @_;
2553 foreach my $ds (keys %$conf) {
2554 next if !valid_drivename
($ds);
2556 my $drive = parse_drive
($ds, $conf->{$ds});
2559 &$func($ds, $drive);
2564 my ($conf, $func) = @_;
2568 my $test_volid = sub {
2569 my ($volid, $is_cdrom) = @_;
2573 $volhash->{$volid} = $is_cdrom || 0;
2576 foreach_drive
($conf, sub {
2577 my ($ds, $drive) = @_;
2578 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2581 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2582 my $snap = $conf->{snapshots
}->{$snapname};
2583 &$test_volid($snap->{vmstate
}, 0);
2584 foreach_drive
($snap, sub {
2585 my ($ds, $drive) = @_;
2586 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2590 foreach my $volid (keys %$volhash) {
2591 &$func($volid, $volhash->{$volid});
2595 sub vga_conf_has_spice
{
2598 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2603 sub config_to_command
{
2604 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2607 my $globalFlags = [];
2608 my $machineFlags = [];
2614 my $kvmver = kvm_user_version
();
2615 my $vernum = 0; # unknown
2616 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2617 $vernum = $1*1000000+$2*1000;
2618 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2619 $vernum = $1*1000000+$2*1000+$3;
2622 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2624 my $have_ovz = -f
'/proc/vz/vestat';
2626 my $q35 = machine_type_is_q35
($conf);
2627 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2628 my $machine_type = $forcemachine || $conf->{machine
};
2630 my $cpuunits = defined($conf->{cpuunits
}) ?
2631 $conf->{cpuunits
} : $defaults->{cpuunits
};
2633 push @$cmd, '/usr/bin/systemd-run';
2634 push @$cmd, '--scope';
2635 push @$cmd, '--slice', "qemu";
2636 push @$cmd, '--unit', $vmid;
2637 push @$cmd, '-p', "CPUShares=$cpuunits";
2638 if ($conf->{cpulimit
}) {
2639 my $cpulimit = int($conf->{cpulimit
} * 100);
2640 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2643 push @$cmd, '/usr/bin/kvm';
2645 push @$cmd, '-id', $vmid;
2649 my $qmpsocket = qmp_socket
($vmid);
2650 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2651 push @$cmd, '-mon', "chardev=qmp,mode=control";
2653 my $socket = vnc_socket
($vmid);
2654 push @$cmd, '-vnc', "unix:$socket,x509,password";
2656 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2658 push @$cmd, '-daemonize';
2660 if ($conf->{smbios1
}) {
2661 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2665 # the q35 chipset support native usb2, so we enable usb controller
2666 # by default for this machine type
2667 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2669 $pciaddr = print_pci_addr
("piix3", $bridges);
2670 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2673 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2674 next if !$conf->{"usb$i"};
2677 # include usb device config
2678 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2681 my $vga = $conf->{vga
};
2683 my $qxlnum = vga_conf_has_spice
($vga);
2684 $vga = 'qxl' if $qxlnum;
2687 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2688 $conf->{ostype
} eq 'win7' ||
2689 $conf->{ostype
} eq 'w2k8')) {
2696 # enable absolute mouse coordinates (needed by vnc)
2698 if (defined($conf->{tablet
})) {
2699 $tablet = $conf->{tablet
};
2701 $tablet = $defaults->{tablet
};
2702 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2703 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2706 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2709 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2710 my $d = parse_hostpci
($conf->{"hostpci$i"});
2713 my $pcie = $d->{pcie
};
2715 die "q35 machine model is not enabled" if !$q35;
2716 $pciaddr = print_pcie_addr
("hostpci$i");
2718 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2721 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2722 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2723 if ($xvga && $xvga ne '') {
2724 push @$cpuFlags, 'kvm=off';
2727 my $pcidevices = $d->{pciid
};
2728 my $multifunction = 1 if @$pcidevices > 1;
2731 foreach my $pcidevice (@$pcidevices) {
2733 my $id = "hostpci$i";
2734 $id .= ".$j" if $multifunction;
2735 my $addr = $pciaddr;
2736 $addr .= ".$j" if $multifunction;
2737 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2740 $devicestr .= "$rombar$xvga";
2741 $devicestr .= ",multifunction=on" if $multifunction;
2744 push @$devices, '-device', $devicestr;
2750 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2751 my $d = parse_usb_device
($conf->{"usb$i"});
2753 if ($d->{vendorid
} && $d->{productid
}) {
2754 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2755 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2756 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2757 } elsif ($d->{spice
}) {
2758 # usb redir support for spice
2759 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2760 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2765 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2766 if (my $path = $conf->{"serial$i"}) {
2767 if ($path eq 'socket') {
2768 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2769 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2770 push @$devices, '-device', "isa-serial,chardev=serial$i";
2772 die "no such serial device\n" if ! -c
$path;
2773 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2774 push @$devices, '-device', "isa-serial,chardev=serial$i";
2780 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2781 if (my $path = $conf->{"parallel$i"}) {
2782 die "no such parallel device\n" if ! -c
$path;
2783 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2784 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2785 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2789 my $vmname = $conf->{name
} || "vm$vmid";
2791 push @$cmd, '-name', $vmname;
2794 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2795 $sockets = $conf->{sockets
} if $conf->{sockets
};
2797 my $cores = $conf->{cores
} || 1;
2799 my $maxcpus = $sockets * $cores;
2801 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2803 my $allowed_vcpus = $cpuinfo->{cpus
};
2805 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2806 if ($allowed_vcpus < $maxcpus);
2808 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2810 push @$cmd, '-nodefaults';
2812 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2814 my $bootindex_hash = {};
2816 foreach my $o (split(//, $bootorder)) {
2817 $bootindex_hash->{$o} = $i*100;
2821 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2823 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2825 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2827 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2830 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2832 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2833 my $useLocaltime = $conf->{localtime};
2835 if (my $ost = $conf->{ostype
}) {
2836 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2838 if ($ost =~ m/^w/) { # windows
2839 $useLocaltime = 1 if !defined($conf->{localtime});
2841 # use time drift fix when acpi is enabled
2842 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2843 $tdf = 1 if !defined($conf->{tdf
});
2847 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2849 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2850 push @$cmd, '-no-hpet';
2851 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2852 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2853 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2854 push @$cpuFlags , 'hv_time' if !$nokvm;
2857 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2861 if ($ost eq 'win7' || $ost eq 'win8') {
2862 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2866 push @$rtcFlags, 'driftfix=slew' if $tdf;
2869 push @$machineFlags, 'accel=tcg';
2871 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2874 if ($machine_type) {
2875 push @$machineFlags, "type=${machine_type}";
2878 if ($conf->{startdate
}) {
2879 push @$rtcFlags, "base=$conf->{startdate}";
2880 } elsif ($useLocaltime) {
2881 push @$rtcFlags, 'base=localtime';
2884 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2885 $cpu = $conf->{cpu
} if $conf->{cpu
};
2887 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2889 push @$cpuFlags , '-x2apic'
2890 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2892 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2894 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2896 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2898 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2899 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2900 push @$cpuFlags , '-kvm_steal_time' if !$nokvm;
2903 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2905 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2907 push @$cmd, '-cpu', $cpu;
2909 my $memory = $conf->{memory
} || $defaults->{memory
};
2910 my $static_memory = 0;
2911 my $dimm_memory = 0;
2913 if ($hotplug_features->{memory
}) {
2914 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2915 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2916 $static_memory = $STATICMEM;
2917 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2918 $dimm_memory = $memory - $static_memory;
2919 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2923 $static_memory = $memory;
2924 push @$cmd, '-m', $static_memory;
2927 if ($conf->{numa
}) {
2929 my $numa_totalmemory = undef;
2930 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2931 next if !$conf->{"numa$i"};
2932 my $numa = parse_numa
($conf->{"numa$i"});
2935 die "missing numa node$i memory value\n" if !$numa->{memory
};
2936 my $numa_memory = $numa->{memory
};
2937 $numa_totalmemory += $numa_memory;
2938 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2941 my $cpus_start = $numa->{cpus
}->{start
};
2942 die "missing numa node$i cpus\n" if !defined($cpus_start);
2943 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2944 my $cpus = $cpus_start;
2945 if (defined($cpus_end)) {
2946 $cpus .= "-$cpus_end";
2947 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2951 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2952 if (defined($hostnodes_start)) {
2953 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2954 my $hostnodes = $hostnodes_start;
2955 if (defined($hostnodes_end)) {
2956 $hostnodes .= "-$hostnodes_end";
2957 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2960 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2961 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2962 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2966 my $policy = $numa->{policy
};
2967 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2968 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2971 push @$cmd, '-object', $numa_object;
2972 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2975 die "total memory for NUMA nodes must be equal to vm static memory\n"
2976 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2978 #if no custom tology, we split memory and cores across numa nodes
2979 if(!$numa_totalmemory) {
2981 my $numa_memory = ($static_memory / $sockets) . "M";
2983 for (my $i = 0; $i < $sockets; $i++) {
2985 my $cpustart = ($cores * $i);
2986 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2987 my $cpus = $cpustart;
2988 $cpus .= "-$cpuend" if $cpuend;
2990 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2991 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2996 if ($hotplug_features->{memory
}) {
2997 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2998 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2999 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3000 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3002 #if dimm_memory is not aligned to dimm map
3003 if($current_size > $memory) {
3004 $conf->{memory
} = $current_size;
3005 update_config_nolock
($vmid, $conf, 1);
3010 push @$cmd, '-S' if $conf->{freeze
};
3012 # set keyboard layout
3013 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3014 push @$cmd, '-k', $kb if $kb;
3017 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3018 #push @$cmd, '-soundhw', 'es1370';
3019 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3021 if($conf->{agent
}) {
3022 my $qgasocket = qmp_socket
($vmid, 1);
3023 my $pciaddr = print_pci_addr
("qga0", $bridges);
3024 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3025 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3026 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3033 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3034 for(my $i = 1; $i < $qxlnum; $i++){
3035 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3036 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3039 # assume other OS works like Linux
3040 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3041 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3045 my $pciaddr = print_pci_addr
("spice", $bridges);
3047 my $nodename = PVE
::INotify
::nodename
();
3048 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3049 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3051 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3053 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3054 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3055 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3058 # enable balloon by default, unless explicitly disabled
3059 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3060 $pciaddr = print_pci_addr
("balloon0", $bridges);
3061 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3064 if ($conf->{watchdog
}) {
3065 my $wdopts = parse_watchdog
($conf->{watchdog
});
3066 $pciaddr = print_pci_addr
("watchdog", $bridges);
3067 my $watchdog = $wdopts->{model
} || 'i6300esb';
3068 push @$devices, '-device', "$watchdog$pciaddr";
3069 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3073 my $scsicontroller = {};
3074 my $ahcicontroller = {};
3075 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3077 # Add iscsi initiator name if available
3078 if (my $initiator = get_initiator_name
()) {
3079 push @$devices, '-iscsi', "initiator-name=$initiator";
3082 foreach_drive
($conf, sub {
3083 my ($ds, $drive) = @_;
3085 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3086 push @$vollist, $drive->{file
};
3089 $use_virtio = 1 if $ds =~ m/^virtio/;
3091 if (drive_is_cdrom
($drive)) {
3092 if ($bootindex_hash->{d
}) {
3093 $drive->{bootindex
} = $bootindex_hash->{d
};
3094 $bootindex_hash->{d
} += 1;
3097 if ($bootindex_hash->{c
}) {
3098 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3099 $bootindex_hash->{c
} += 1;
3103 if($drive->{interface
} eq 'virtio'){
3104 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3107 if ($drive->{interface
} eq 'scsi') {
3109 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3111 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3112 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3115 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3116 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3117 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3121 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3122 $queues = ",num_queues=$drive->{queues}";
3125 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3126 $scsicontroller->{$controller}=1;
3129 if ($drive->{interface
} eq 'sata') {
3130 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3131 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3132 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3133 $ahcicontroller->{$controller}=1;
3136 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3137 push @$devices, '-drive',$drive_cmd;
3138 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3141 for (my $i = 0; $i < $MAX_NETS; $i++) {
3142 next if !$conf->{"net$i"};
3143 my $d = parse_net
($conf->{"net$i"});
3146 $use_virtio = 1 if $d->{model
} eq 'virtio';
3148 if ($bootindex_hash->{n
}) {
3149 $d->{bootindex
} = $bootindex_hash->{n
};
3150 $bootindex_hash->{n
} += 1;
3153 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3154 push @$devices, '-netdev', $netdevfull;
3156 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3157 push @$devices, '-device', $netdevicefull;
3162 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3167 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3169 while (my ($k, $v) = each %$bridges) {
3170 $pciaddr = print_pci_addr
("pci.$k");
3171 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3176 if ($conf->{args
}) {
3177 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3181 push @$cmd, @$devices;
3182 push @$cmd, '-rtc', join(',', @$rtcFlags)
3183 if scalar(@$rtcFlags);
3184 push @$cmd, '-machine', join(',', @$machineFlags)
3185 if scalar(@$machineFlags);
3186 push @$cmd, '-global', join(',', @$globalFlags)
3187 if scalar(@$globalFlags);
3189 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3194 return "${var_run_tmpdir}/$vmid.vnc";
3200 my $res = vm_mon_cmd
($vmid, 'query-spice');
3202 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3206 my ($vmid, $qga) = @_;
3207 my $sockettype = $qga ?
'qga' : 'qmp';
3208 return "${var_run_tmpdir}/$vmid.$sockettype";
3213 return "${var_run_tmpdir}/$vmid.pid";
3216 sub vm_devices_list
{
3219 my $res = vm_mon_cmd
($vmid, 'query-pci');
3221 foreach my $pcibus (@$res) {
3222 foreach my $device (@{$pcibus->{devices
}}) {
3223 next if !$device->{'qdev_id'};
3224 if ($device->{'pci_bridge'}) {
3225 $devices->{$device->{'qdev_id'}} = 1;
3226 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3227 next if !$bridge_device->{'qdev_id'};
3228 $devices->{$bridge_device->{'qdev_id'}} = 1;
3229 $devices->{$device->{'qdev_id'}}++;
3232 $devices->{$device->{'qdev_id'}} = 1;
3237 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3238 foreach my $block (@$resblock) {
3239 if($block->{device
} =~ m/^drive-(\S+)/){
3244 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3245 foreach my $mice (@$resmice) {
3246 if ($mice->{name
} eq 'QEMU HID Tablet') {
3247 $devices->{tablet
} = 1;
3256 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3258 my $q35 = machine_type_is_q35
($conf);
3260 my $devices_list = vm_devices_list
($vmid);
3261 return 1 if defined($devices_list->{$deviceid});
3263 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3265 if ($deviceid eq 'tablet') {
3267 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3269 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3271 qemu_iothread_add
($vmid, $deviceid, $device);
3273 qemu_driveadd
($storecfg, $vmid, $device);
3274 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3276 qemu_deviceadd
($vmid, $devicefull);
3277 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3279 eval { qemu_drivedel
($vmid, $deviceid); };
3284 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3287 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3288 my $pciaddr = print_pci_addr
($deviceid);
3289 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3291 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3293 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3294 qemu_iothread_add
($vmid, $deviceid, $device);
3295 $devicefull .= ",iothread=iothread-$deviceid";
3298 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3299 $devicefull .= ",num_queues=$device->{queues}";
3302 qemu_deviceadd
($vmid, $devicefull);
3303 qemu_deviceaddverify
($vmid, $deviceid);
3305 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3307 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3308 qemu_driveadd
($storecfg, $vmid, $device);
3310 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3311 eval { qemu_deviceadd
($vmid, $devicefull); };
3313 eval { qemu_drivedel
($vmid, $deviceid); };
3318 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3320 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3321 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3322 qemu_deviceadd
($vmid, $netdevicefull);
3323 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3325 eval { qemu_netdevdel
($vmid, $deviceid); };
3330 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3333 my $pciaddr = print_pci_addr
($deviceid);
3334 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3336 qemu_deviceadd
($vmid, $devicefull);
3337 qemu_deviceaddverify
($vmid, $deviceid);
3340 die "can't hotplug device '$deviceid'\n";
3346 # fixme: this should raise exceptions on error!
3347 sub vm_deviceunplug
{
3348 my ($vmid, $conf, $deviceid) = @_;
3350 my $devices_list = vm_devices_list
($vmid);
3351 return 1 if !defined($devices_list->{$deviceid});
3353 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3355 if ($deviceid eq 'tablet') {
3357 qemu_devicedel
($vmid, $deviceid);
3359 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3361 qemu_devicedel
($vmid, $deviceid);
3362 qemu_devicedelverify
($vmid, $deviceid);
3363 qemu_drivedel
($vmid, $deviceid);
3364 qemu_iothread_del
($conf, $vmid, $deviceid);
3366 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3368 qemu_devicedel
($vmid, $deviceid);
3369 qemu_devicedelverify
($vmid, $deviceid);
3370 qemu_iothread_del
($conf, $vmid, $deviceid);
3372 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3374 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3375 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3376 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3378 qemu_devicedel
($vmid, $deviceid);
3379 qemu_drivedel
($vmid, $deviceid);
3380 qemu_deletescsihw
($conf, $vmid, $deviceid);
3382 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3384 qemu_devicedel
($vmid, $deviceid);
3385 qemu_devicedelverify
($vmid, $deviceid);
3386 qemu_netdevdel
($vmid, $deviceid);
3389 die "can't unplug device '$deviceid'\n";
3395 sub qemu_deviceadd
{
3396 my ($vmid, $devicefull) = @_;
3398 $devicefull = "driver=".$devicefull;
3399 my %options = split(/[=,]/, $devicefull);
3401 vm_mon_cmd
($vmid, "device_add" , %options);
3404 sub qemu_devicedel
{
3405 my ($vmid, $deviceid) = @_;
3407 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3410 sub qemu_iothread_add
{
3411 my($vmid, $deviceid, $device) = @_;
3413 if ($device->{iothread
}) {
3414 my $iothreads = vm_iothreads_list
($vmid);
3415 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3419 sub qemu_iothread_del
{
3420 my($conf, $vmid, $deviceid) = @_;
3422 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3423 if ($device->{iothread
}) {
3424 my $iothreads = vm_iothreads_list
($vmid);
3425 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3429 sub qemu_objectadd
{
3430 my($vmid, $objectid, $qomtype) = @_;
3432 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3437 sub qemu_objectdel
{
3438 my($vmid, $objectid) = @_;
3440 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3446 my ($storecfg, $vmid, $device) = @_;
3448 my $drive = print_drive_full
($storecfg, $vmid, $device);
3449 $drive =~ s/\\/\\\\/g;
3450 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3452 # If the command succeeds qemu prints: "OK
"
3453 return 1 if $ret =~ m/OK/s;
3455 die "adding drive failed
: $ret\n";
3459 my($vmid, $deviceid) = @_;
3461 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3464 return 1 if $ret eq "";
3466 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3467 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3469 die "deleting drive
$deviceid failed
: $ret\n";
3472 sub qemu_deviceaddverify {
3473 my ($vmid, $deviceid) = @_;
3475 for (my $i = 0; $i <= 5; $i++) {
3476 my $devices_list = vm_devices_list($vmid);
3477 return 1 if defined($devices_list->{$deviceid});
3481 die "error on hotplug device
'$deviceid'\n";
3485 sub qemu_devicedelverify {
3486 my ($vmid, $deviceid) = @_;
3488 # need to verify that the device is correctly removed as device_del
3489 # is async and empty return is not reliable
3491 for (my $i = 0; $i <= 5; $i++) {
3492 my $devices_list = vm_devices_list($vmid);
3493 return 1 if !defined($devices_list->{$deviceid});
3497 die "error on hot-unplugging device
'$deviceid'\n";
3500 sub qemu_findorcreatescsihw {
3501 my ($storecfg, $conf, $vmid, $device) = @_;
3503 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3505 my $scsihwid="$controller_prefix$controller";
3506 my $devices_list = vm_devices_list($vmid);
3508 if(!defined($devices_list->{$scsihwid})) {
3509 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3515 sub qemu_deletescsihw {
3516 my ($conf, $vmid, $opt) = @_;
3518 my $device = parse_drive($opt, $conf->{$opt});
3520 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3521 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3525 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3527 my $devices_list = vm_devices_list($vmid);
3528 foreach my $opt (keys %{$devices_list}) {
3529 if (PVE::QemuServer::valid_drivename($opt)) {
3530 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3531 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3537 my $scsihwid="scsihw
$controller";
3539 vm_deviceunplug($vmid, $conf, $scsihwid);
3544 sub qemu_add_pci_bridge {
3545 my ($storecfg, $conf, $vmid, $device) = @_;
3551 print_pci_addr($device, $bridges);
3553 while (my ($k, $v) = each %$bridges) {
3556 return 1 if !defined($bridgeid) || $bridgeid < 1;
3558 my $bridge = "pci
.$bridgeid";
3559 my $devices_list = vm_devices_list($vmid);
3561 if (!defined($devices_list->{$bridge})) {
3562 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3568 sub qemu_set_link_status {
3569 my ($vmid, $device, $up) = @_;
3571 vm_mon_cmd($vmid, "set_link
", name => $device,
3572 up => $up ? JSON::true : JSON::false);
3575 sub qemu_netdevadd {
3576 my ($vmid, $conf, $device, $deviceid) = @_;
3578 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3579 my %options = split(/[=,]/, $netdev);
3581 vm_mon_cmd($vmid, "netdev_add
", %options);
3585 sub qemu_netdevdel {
3586 my ($vmid, $deviceid) = @_;
3588 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3591 sub qemu_cpu_hotplug {
3592 my ($vmid, $conf, $vcpus) = @_;
3595 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3596 $sockets = $conf->{sockets} if $conf->{sockets};
3597 my $cores = $conf->{cores} || 1;
3598 my $maxcpus = $sockets * $cores;
3600 $vcpus = $maxcpus if !$vcpus;
3602 die "you can
't add more vcpus than maxcpus\n"
3603 if $vcpus > $maxcpus;
3605 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3606 die "online cpu unplug is not yet possible\n"
3607 if $vcpus < $currentvcpus;
3609 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3610 die "vcpus in running vm is different than configuration\n"
3611 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3613 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3614 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3618 sub qemu_memory_hotplug {
3619 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3621 return $value if !check_running($vmid);
3623 my $memory = $conf->{memory} || $defaults->{memory};
3624 $value = $defaults->{memory} if !$value;
3625 return $value if $value == $memory;
3627 my $static_memory = $STATICMEM;
3628 my $dimm_memory = $memory - $static_memory;
3630 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3631 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3635 $sockets = $conf->{sockets} if $conf->{sockets};
3637 if($value > $memory) {
3639 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3640 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3642 return if $current_size <= $conf->{memory};
3644 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3646 eval { qemu_objectdel($vmid, "mem-
$name"); };
3650 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3652 eval { qemu_objectdel($vmid, "mem-
$name"); };
3655 #update conf after each succesful module hotplug
3656 $conf->{memory} = $current_size;
3657 update_config_nolock($vmid, $conf, 1);
3662 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3663 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3665 return if $current_size >= $conf->{memory};
3666 print "try to unplug memory dimm
$name\n";
3670 eval { qemu_devicedel($vmid, $name) };
3672 my $dimm_list = qemu_dimm_list($vmid);
3673 last if !$dimm_list->{$name};
3674 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3678 #update conf after each succesful module unplug
3679 $conf->{memory} = $current_size;
3681 eval { qemu_objectdel($vmid, "mem-
$name"); };
3682 update_config_nolock($vmid, $conf, 1);
3687 sub qemu_dimm_list {
3690 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3693 foreach my $dimm (@$dimmarray) {
3695 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3696 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3697 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3698 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3699 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3704 sub qemu_block_set_io_throttle {
3705 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3707 return if !check_running($vmid) ;
3709 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));
3713 # old code, only used to shutdown old VM after update
3715 my ($fh, $timeout) = @_;
3717 my $sel = new IO::Select;
3724 while (scalar (@ready = $sel->can_read($timeout))) {
3726 if ($count = $fh->sysread($buf, 8192)) {
3727 if ($buf =~ /^(.*)\(qemu\) $/s) {
3734 if (!defined($count)) {
3741 die "monitor
read timeout
\n" if !scalar(@ready);
3746 # old code, only used to shutdown old VM after update
3747 sub vm_monitor_command {
3748 my ($vmid, $cmdstr, $nocheck) = @_;
3753 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3755 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3757 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3758 die "unable to
connect to VM
$vmid socket - $!\n";
3762 # hack: migrate sometime blocks the monitor (when migrate_downtime
3764 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3765 $timeout = 60*60; # 1 hour
3769 my $data = __read_avail($sock, $timeout);
3771 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3772 die "got unexpected qemu monitor banner
\n";
3775 my $sel = new IO::Select;
3778 if (!scalar(my @ready = $sel->can_write($timeout))) {
3779 die "monitor
write error
- timeout
";
3782 my $fullcmd = "$cmdstr\r";
3784 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3787 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3788 die "monitor
write error
- $!";
3791 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3795 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3796 $timeout = 60*60; # 1 hour
3797 } elsif ($cmdstr =~ m/^(eject|change)/) {
3798 $timeout = 60; # note: cdrom mount command is slow
3800 if ($res = __read_avail($sock, $timeout)) {
3802 my @lines = split("\r?
\n", $res);
3804 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3806 $res = join("\n", @lines);
3814 syslog("err
", "VM
$vmid monitor command failed
- $err");
3821 sub qemu_block_resize {
3822 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3824 my $running = check_running($vmid);
3826 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3828 return if !$running;
3830 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3834 sub qemu_volume_snapshot {
3835 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3837 my $running = check_running($vmid);
3839 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3840 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3842 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3846 sub qemu_volume_snapshot_delete {
3847 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3849 my $running = check_running($vmid);
3851 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3853 return if !$running;
3855 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3858 sub set_migration_caps {
3864 "auto-converge
" => 1,
3866 "x-rdma-pin-all
" => 0,
3871 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3873 for my $supported_capability (@$supported_capabilities) {
3875 capability => $supported_capability->{capability},
3876 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3880 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3883 my $fast_plug_option = {
3892 # hotplug changes in [PENDING]
3893 # $selection hash can be used to only apply specified options, for
3894 # example: { cores => 1 } (only apply changed 'cores')
3895 # $errors ref is used to return error messages
3896 sub vmconfig_hotplug_pending {
3897 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3899 my $defaults = load_defaults();
3901 # commit values which do not have any impact on running VM first
3902 # Note: those option cannot raise errors, we we do not care about
3903 # $selection and always apply them.
3905 my $add_error = sub {
3906 my ($opt, $msg) = @_;
3907 $errors->{$opt} = "hotplug problem
- $msg";
3911 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3912 if ($fast_plug_option->{$opt}) {
3913 $conf->{$opt} = $conf->{pending}->{$opt};
3914 delete $conf->{pending}->{$opt};
3920 update_config_nolock($vmid, $conf, 1);
3921 $conf = load_config($vmid); # update/reload
3924 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3926 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3927 while (my ($opt, $force) = each %$pending_delete_hash) {
3928 next if $selection && !$selection->{$opt};
3930 if ($opt eq 'hotplug') {
3931 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3932 } elsif ($opt eq 'tablet') {
3933 die "skip
\n" if !$hotplug_features->{usb};
3934 if ($defaults->{tablet}) {
3935 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3937 vm_deviceunplug($vmid, $conf, $opt);
3939 } elsif ($opt eq 'vcpus') {
3940 die "skip
\n" if !$hotplug_features->{cpu};
3941 qemu_cpu_hotplug($vmid, $conf, undef);
3942 } elsif ($opt eq 'balloon') {
3943 # enable balloon device is not hotpluggable
3944 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3945 } elsif ($fast_plug_option->{$opt}) {
3947 } elsif ($opt =~ m/^net(\d+)$/) {
3948 die "skip
\n" if !$hotplug_features->{network};
3949 vm_deviceunplug($vmid, $conf, $opt);
3950 } elsif (valid_drivename($opt)) {
3951 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3952 vm_deviceunplug($vmid, $conf, $opt);
3953 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3954 } elsif ($opt =~ m/^memory$/) {
3955 die "skip
\n" if !$hotplug_features->{memory};
3956 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3957 } elsif ($opt eq 'cpuunits') {
3958 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3959 } elsif ($opt eq 'cpulimit') {
3960 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3966 &$add_error($opt, $err) if $err ne "skip
\n";
3968 # save new config if hotplug was successful
3969 delete $conf->{$opt};
3970 vmconfig_undelete_pending_option($conf, $opt);
3971 update_config_nolock($vmid, $conf, 1);
3972 $conf = load_config($vmid); # update/reload
3976 foreach my $opt (keys %{$conf->{pending}}) {
3977 next if $selection && !$selection->{$opt};
3978 my $value = $conf->{pending}->{$opt};
3980 if ($opt eq 'hotplug') {
3981 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3982 } elsif ($opt eq 'tablet') {
3983 die "skip
\n" if !$hotplug_features->{usb};
3985 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3986 } elsif ($value == 0) {
3987 vm_deviceunplug($vmid, $conf, $opt);
3989 } elsif ($opt eq 'vcpus') {
3990 die "skip
\n" if !$hotplug_features->{cpu};
3991 qemu_cpu_hotplug($vmid, $conf, $value);
3992 } elsif ($opt eq 'balloon') {
3993 # enable/disable balloning device is not hotpluggable
3994 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3995 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3996 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3998 # allow manual ballooning if shares is set to zero
3999 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4000 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4001 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4003 } elsif ($opt =~ m/^net(\d+)$/) {
4004 # some changes can be done without hotplug
4005 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4006 $vmid, $opt, $value);
4007 } elsif (valid_drivename($opt)) {
4008 # some changes can be done without hotplug
4009 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4010 $vmid, $opt, $value, 1);
4011 } elsif ($opt =~ m/^memory$/) { #dimms
4012 die "skip
\n" if !$hotplug_features->{memory};
4013 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4014 } elsif ($opt eq 'cpuunits') {
4015 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4016 } elsif ($opt eq 'cpulimit') {
4017 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4018 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4020 die "skip
\n"; # skip non-hot-pluggable options
4024 &$add_error($opt, $err) if $err ne "skip
\n";
4026 # save new config if hotplug was successful
4027 $conf->{$opt} = $value;
4028 delete $conf->{pending}->{$opt};
4029 update_config_nolock($vmid, $conf, 1);
4030 $conf = load_config($vmid); # update/reload
4035 sub try_deallocate_drive {
4036 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4038 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4039 my $volid = $drive->{file};
4040 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4041 my $sid = PVE::Storage::parse_volume_id($volid);
4042 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4044 # check if the disk is really unused
4045 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4046 my $path = PVE::Storage::path($storecfg, $volid);
4047 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4048 if $used_paths->{$path};
4049 PVE::Storage::vdisk_free($storecfg, $volid);
4052 # If vm is not owner of this disk remove from config
4060 sub vmconfig_delete_or_detach_drive {
4061 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4063 my $drive = parse_drive($opt, $conf->{$opt});
4065 my $rpcenv = PVE::RPCEnvironment::get();
4066 my $authuser = $rpcenv->get_user();
4069 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4070 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4072 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4076 sub vmconfig_apply_pending {
4077 my ($vmid, $conf, $storecfg) = @_;
4081 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4082 while (my ($opt, $force) = each %$pending_delete_hash) {
4083 die "internal error
" if $opt =~ m/^unused/;
4084 $conf = load_config($vmid); # update/reload
4085 if (!defined($conf->{$opt})) {
4086 vmconfig_undelete_pending_option($conf, $opt);
4087 update_config_nolock($vmid, $conf, 1);
4088 } elsif (valid_drivename($opt)) {
4089 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4090 vmconfig_undelete_pending_option($conf, $opt);
4091 delete $conf->{$opt};
4092 update_config_nolock($vmid, $conf, 1);
4094 vmconfig_undelete_pending_option($conf, $opt);
4095 delete $conf->{$opt};
4096 update_config_nolock($vmid, $conf, 1);
4100 $conf = load_config($vmid); # update/reload
4102 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4103 $conf = load_config($vmid); # update/reload
4105 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4106 # skip if nothing changed
4107 } elsif (valid_drivename($opt)) {
4108 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4109 if defined($conf->{$opt});
4110 $conf->{$opt} = $conf->{pending}->{$opt};
4112 $conf->{$opt} = $conf->{pending}->{$opt};
4115 delete $conf->{pending}->{$opt};
4116 update_config_nolock($vmid, $conf, 1);
4120 my $safe_num_ne = sub {
4123 return 0 if !defined($a) && !defined($b);
4124 return 1 if !defined($a);
4125 return 1 if !defined($b);
4130 my $safe_string_ne = sub {
4133 return 0 if !defined($a) && !defined($b);
4134 return 1 if !defined($a);
4135 return 1 if !defined($b);
4140 sub vmconfig_update_net {
4141 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4143 my $newnet = parse_net($value);
4145 if ($conf->{$opt}) {
4146 my $oldnet = parse_net($conf->{$opt});
4148 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4149 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4150 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4151 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4153 # for non online change, we try to hot-unplug
4154 die "skip
\n" if !$hotplug;
4155 vm_deviceunplug($vmid, $conf, $opt);
4158 die "internal error
" if $opt !~ m/net(\d+)/;
4159 my $iface = "tap
${vmid
}i
$1";
4161 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4162 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4165 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4166 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4167 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4168 PVE::Network::tap_unplug($iface);
4169 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4172 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4173 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4181 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4187 sub vmconfig_update_disk {
4188 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4190 # fixme: do we need force?
4192 my $drive = parse_drive($opt, $value);
4194 if ($conf->{$opt}) {
4196 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4198 my $media = $drive->{media} || 'disk';
4199 my $oldmedia = $old_drive->{media} || 'disk';
4200 die "unable to change media type
\n" if $media ne $oldmedia;
4202 if (!drive_is_cdrom($old_drive)) {
4204 if ($drive->{file} ne $old_drive->{file}) {
4206 die "skip
\n" if !$hotplug;
4208 # unplug and register as unused
4209 vm_deviceunplug($vmid, $conf, $opt);
4210 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4213 # update existing disk
4215 # skip non hotpluggable value
4216 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4217 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4218 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4219 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4224 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4225 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4226 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4227 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4228 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4229 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4230 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4231 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4232 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4233 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4234 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4235 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4237 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4238 ($drive->{mbps} || 0)*1024*1024,
4239 ($drive->{mbps_rd} || 0)*1024*1024,
4240 ($drive->{mbps_wr} || 0)*1024*1024,
4241 $drive->{iops} || 0,
4242 $drive->{iops_rd} || 0,
4243 $drive->{iops_wr} || 0,
4244 ($drive->{mbps_max} || 0)*1024*1024,
4245 ($drive->{mbps_rd_max} || 0)*1024*1024,
4246 ($drive->{mbps_wr_max} || 0)*1024*1024,
4247 $drive->{iops_max} || 0,
4248 $drive->{iops_rd_max} || 0,
4249 $drive->{iops_wr_max} || 0);
4258 if ($drive->{file} eq 'none') {
4259 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4261 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4262 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4263 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4271 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4273 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4277 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4279 lock_config($vmid, sub {
4280 my $conf = load_config($vmid, $migratedfrom);
4282 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4284 check_lock($conf) if !$skiplock;
4286 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4288 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4289 vmconfig_apply_pending($vmid, $conf, $storecfg);
4290 $conf = load_config($vmid); # update/reload
4293 my $defaults = load_defaults();
4295 # set environment variable useful inside network script
4296 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4298 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4300 my $migrate_port = 0;
4303 if ($statefile eq 'tcp') {
4304 my $localip = "localhost
";
4305 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4306 my $nodename = PVE::INotify::nodename();
4307 if ($datacenterconf->{migration_unsecure}) {
4308 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4310 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4311 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4312 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4313 push @$cmd, '-incoming', $migrate_uri;
4316 push @$cmd, '-loadstate', $statefile;
4323 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4324 my $d = parse_hostpci($conf->{"hostpci
$i"});
4326 my $pcidevices = $d->{pciid};
4327 foreach my $pcidevice (@$pcidevices) {
4328 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4330 my $info = pci_device_info("0000:$pciid");
4331 die "IOMMU
not present
\n" if !check_iommu_support();
4332 die "no pci device info
for device
'$pciid'\n" if !$info;
4333 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4334 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4338 PVE::Storage::activate_volumes($storecfg, $vollist);
4340 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4343 die "start failed
: $err" if $err;
4345 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4347 if ($statefile && $statefile ne 'tcp') {
4348 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4352 if ($migratedfrom) {
4355 set_migration_caps($vmid);
4360 print "spice listens on port
$spice_port\n";
4361 if ($spice_ticket) {
4362 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4363 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4369 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4370 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4371 if $conf->{balloon};
4374 foreach my $opt (keys %$conf) {
4375 next if $opt !~ m/^net\d+$/;
4376 my $nicconf = parse_net($conf->{$opt});
4377 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4381 vm_mon_cmd_nocheck($vmid, 'qom-set',
4382 path => "machine
/peripheral/balloon0
",
4383 property => "guest-stats-polling-interval
",
4384 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4390 my ($vmid, $execute, %params) = @_;
4392 my $cmd = { execute => $execute, arguments => \%params };
4393 vm_qmp_command($vmid, $cmd);
4396 sub vm_mon_cmd_nocheck {
4397 my ($vmid, $execute, %params) = @_;
4399 my $cmd = { execute => $execute, arguments => \%params };
4400 vm_qmp_command($vmid, $cmd, 1);
4403 sub vm_qmp_command {
4404 my ($vmid, $cmd, $nocheck) = @_;
4409 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4410 $timeout = $cmd->{arguments}->{timeout};
4411 delete $cmd->{arguments}->{timeout};
4415 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4416 my $sname = qmp_socket($vmid);
4417 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4418 my $qmpclient = PVE::QMPClient->new();
4420 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4421 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4422 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4423 if scalar(%{$cmd->{arguments}});
4424 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4426 die "unable to open monitor socket\n";
4430 syslog("err", "VM $vmid qmp command failed - $err");
4437 sub vm_human_monitor_command {
4438 my ($vmid, $cmdline) = @_;
4443 execute => 'human-monitor-command
',
4444 arguments => { 'command-line
' => $cmdline},
4447 return vm_qmp_command($vmid, $cmd);
4450 sub vm_commandline {
4451 my ($storecfg, $vmid) = @_;
4453 my $conf = load_config($vmid);
4455 my $defaults = load_defaults();
4457 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4459 return join(' ', @$cmd);
4463 my ($vmid, $skiplock) = @_;
4465 lock_config($vmid, sub {
4467 my $conf = load_config($vmid);
4469 check_lock($conf) if !$skiplock;
4471 vm_mon_cmd($vmid, "system_reset");
4475 sub get_vm_volumes {
4479 foreach_volid($conf, sub {
4480 my ($volid, $is_cdrom) = @_;
4482 return if $volid =~ m|^/|;
4484 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4487 push @$vollist, $volid;
4493 sub vm_stop_cleanup {
4494 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4499 my $vollist = get_vm_volumes($conf);
4500 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4503 foreach my $ext (qw(mon qmp pid vnc qga)) {
4504 unlink "/var/run/qemu-server/${vmid}.$ext";
4507 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4509 warn $@ if $@; # avoid errors - just warn
4512 # Note: use $nockeck to skip tests if VM configuration file exists.
4513 # We need that when migration VMs to other nodes (files already moved)
4514 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4516 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4518 $force = 1 if !defined($force) && !$shutdown;
4521 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4522 kill 15, $pid if $pid;
4523 my $conf = load_config
($vmid, $migratedfrom);
4524 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4528 lock_config
($vmid, sub {
4530 my $pid = check_running
($vmid, $nocheck);
4535 $conf = load_config
($vmid);
4536 check_lock
($conf) if !$skiplock;
4537 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4538 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4539 $timeout = $opts->{down
} if $opts->{down
};
4543 $timeout = 60 if !defined($timeout);
4547 if (defined($conf) && $conf->{agent
}) {
4548 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4550 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4553 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4560 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4565 if ($count >= $timeout) {
4567 warn "VM still running - terminating now with SIGTERM\n";
4570 die "VM quit/powerdown failed - got timeout\n";
4573 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4578 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4581 die "VM quit/powerdown failed\n";
4589 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4594 if ($count >= $timeout) {
4595 warn "VM still running - terminating now with SIGKILL\n";
4600 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4605 my ($vmid, $skiplock) = @_;
4607 lock_config
($vmid, sub {
4609 my $conf = load_config
($vmid);
4611 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4613 vm_mon_cmd
($vmid, "stop");
4618 my ($vmid, $skiplock) = @_;
4620 lock_config
($vmid, sub {
4622 my $conf = load_config
($vmid);
4624 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4626 vm_mon_cmd
($vmid, "cont");
4631 my ($vmid, $skiplock, $key) = @_;
4633 lock_config
($vmid, sub {
4635 my $conf = load_config
($vmid);
4637 # there is no qmp command, so we use the human monitor command
4638 vm_human_monitor_command
($vmid, "sendkey $key");
4643 my ($storecfg, $vmid, $skiplock) = @_;
4645 lock_config
($vmid, sub {
4647 my $conf = load_config
($vmid);
4649 check_lock
($conf) if !$skiplock;
4651 if (!check_running
($vmid)) {
4652 destroy_vm
($storecfg, $vmid);
4654 die "VM $vmid is running - destroy failed\n";
4662 my ($filename, $buf) = @_;
4664 my $fh = IO
::File-
>new($filename, "w");
4665 return undef if !$fh;
4667 my $res = print $fh $buf;
4674 sub pci_device_info
{
4679 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4680 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4682 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4683 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4685 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4686 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4688 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4689 return undef if !defined($product) || $product !~ s/^0x//;
4694 product
=> $product,
4700 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4709 my $name = $dev->{name
};
4711 my $fn = "$pcisysfs/devices/$name/reset";
4713 return file_write
($fn, "1");
4716 sub pci_dev_bind_to_vfio
{
4719 my $name = $dev->{name
};
4721 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4723 if (!-d
$vfio_basedir) {
4724 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4726 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4728 my $testdir = "$vfio_basedir/$name";
4729 return 1 if -d
$testdir;
4731 my $data = "$dev->{vendor} $dev->{product}";
4732 return undef if !file_write
("$vfio_basedir/new_id", $data);
4734 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4735 if (!file_write
($fn, $name)) {
4736 return undef if -f
$fn;
4739 $fn = "$vfio_basedir/bind";
4740 if (! -d
$testdir) {
4741 return undef if !file_write
($fn, $name);
4747 sub pci_dev_group_bind_to_vfio
{
4750 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4752 if (!-d
$vfio_basedir) {
4753 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4755 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4757 # get IOMMU group devices
4758 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4759 my @devs = grep /^0000:/, readdir($D);
4762 foreach my $pciid (@devs) {
4763 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4765 # pci bridges, switches or root ports are not supported
4766 # they have a pci_bus subdirectory so skip them
4767 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4769 my $info = pci_device_info
($1);
4770 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4776 sub print_pci_addr
{
4777 my ($id, $bridges) = @_;
4781 piix3
=> { bus
=> 0, addr
=> 1 },
4782 #addr2 : first videocard
4783 balloon0
=> { bus
=> 0, addr
=> 3 },
4784 watchdog
=> { bus
=> 0, addr
=> 4 },
4785 scsihw0
=> { bus
=> 0, addr
=> 5 },
4786 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4787 scsihw1
=> { bus
=> 0, addr
=> 6 },
4788 ahci0
=> { bus
=> 0, addr
=> 7 },
4789 qga0
=> { bus
=> 0, addr
=> 8 },
4790 spice
=> { bus
=> 0, addr
=> 9 },
4791 virtio0
=> { bus
=> 0, addr
=> 10 },
4792 virtio1
=> { bus
=> 0, addr
=> 11 },
4793 virtio2
=> { bus
=> 0, addr
=> 12 },
4794 virtio3
=> { bus
=> 0, addr
=> 13 },
4795 virtio4
=> { bus
=> 0, addr
=> 14 },
4796 virtio5
=> { bus
=> 0, addr
=> 15 },
4797 hostpci0
=> { bus
=> 0, addr
=> 16 },
4798 hostpci1
=> { bus
=> 0, addr
=> 17 },
4799 net0
=> { bus
=> 0, addr
=> 18 },
4800 net1
=> { bus
=> 0, addr
=> 19 },
4801 net2
=> { bus
=> 0, addr
=> 20 },
4802 net3
=> { bus
=> 0, addr
=> 21 },
4803 net4
=> { bus
=> 0, addr
=> 22 },
4804 net5
=> { bus
=> 0, addr
=> 23 },
4805 vga1
=> { bus
=> 0, addr
=> 24 },
4806 vga2
=> { bus
=> 0, addr
=> 25 },
4807 vga3
=> { bus
=> 0, addr
=> 26 },
4808 hostpci2
=> { bus
=> 0, addr
=> 27 },
4809 hostpci3
=> { bus
=> 0, addr
=> 28 },
4810 #addr29 : usb-host (pve-usb.cfg)
4811 'pci.1' => { bus
=> 0, addr
=> 30 },
4812 'pci.2' => { bus
=> 0, addr
=> 31 },
4813 'net6' => { bus
=> 1, addr
=> 1 },
4814 'net7' => { bus
=> 1, addr
=> 2 },
4815 'net8' => { bus
=> 1, addr
=> 3 },
4816 'net9' => { bus
=> 1, addr
=> 4 },
4817 'net10' => { bus
=> 1, addr
=> 5 },
4818 'net11' => { bus
=> 1, addr
=> 6 },
4819 'net12' => { bus
=> 1, addr
=> 7 },
4820 'net13' => { bus
=> 1, addr
=> 8 },
4821 'net14' => { bus
=> 1, addr
=> 9 },
4822 'net15' => { bus
=> 1, addr
=> 10 },
4823 'net16' => { bus
=> 1, addr
=> 11 },
4824 'net17' => { bus
=> 1, addr
=> 12 },
4825 'net18' => { bus
=> 1, addr
=> 13 },
4826 'net19' => { bus
=> 1, addr
=> 14 },
4827 'net20' => { bus
=> 1, addr
=> 15 },
4828 'net21' => { bus
=> 1, addr
=> 16 },
4829 'net22' => { bus
=> 1, addr
=> 17 },
4830 'net23' => { bus
=> 1, addr
=> 18 },
4831 'net24' => { bus
=> 1, addr
=> 19 },
4832 'net25' => { bus
=> 1, addr
=> 20 },
4833 'net26' => { bus
=> 1, addr
=> 21 },
4834 'net27' => { bus
=> 1, addr
=> 22 },
4835 'net28' => { bus
=> 1, addr
=> 23 },
4836 'net29' => { bus
=> 1, addr
=> 24 },
4837 'net30' => { bus
=> 1, addr
=> 25 },
4838 'net31' => { bus
=> 1, addr
=> 26 },
4839 'virtio6' => { bus
=> 2, addr
=> 1 },
4840 'virtio7' => { bus
=> 2, addr
=> 2 },
4841 'virtio8' => { bus
=> 2, addr
=> 3 },
4842 'virtio9' => { bus
=> 2, addr
=> 4 },
4843 'virtio10' => { bus
=> 2, addr
=> 5 },
4844 'virtio11' => { bus
=> 2, addr
=> 6 },
4845 'virtio12' => { bus
=> 2, addr
=> 7 },
4846 'virtio13' => { bus
=> 2, addr
=> 8 },
4847 'virtio14' => { bus
=> 2, addr
=> 9 },
4848 'virtio15' => { bus
=> 2, addr
=> 10 },
4849 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4850 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4851 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4852 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4853 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4854 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4855 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4856 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4857 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4858 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4859 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4860 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4861 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4862 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4863 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4864 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4865 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4866 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4867 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4868 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4869 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4870 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4871 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4872 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4873 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4874 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4875 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4876 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4877 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4878 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4879 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4883 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4884 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4885 my $bus = $devices->{$id}->{bus
};
4886 $res = ",bus=pci.$bus,addr=$addr";
4887 $bridges->{$bus} = 1 if $bridges;
4893 sub print_pcie_addr
{
4898 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4899 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4900 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4901 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4904 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4905 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4906 my $bus = $devices->{$id}->{bus
};
4907 $res = ",bus=$bus,addr=$addr";
4913 # vzdump restore implementaion
4915 sub tar_archive_read_firstfile
{
4916 my $archive = shift;
4918 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4920 # try to detect archive type first
4921 my $pid = open (TMP
, "tar tf '$archive'|") ||
4922 die "unable to open file '$archive'\n";
4923 my $firstfile = <TMP
>;
4927 die "ERROR: archive contaions no data\n" if !$firstfile;
4933 sub tar_restore_cleanup
{
4934 my ($storecfg, $statfile) = @_;
4936 print STDERR
"starting cleanup\n";
4938 if (my $fd = IO
::File-
>new($statfile, "r")) {
4939 while (defined(my $line = <$fd>)) {
4940 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4943 if ($volid =~ m
|^/|) {
4944 unlink $volid || die 'unlink failed\n';
4946 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4948 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4950 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4952 print STDERR
"unable to parse line in statfile - $line";
4959 sub restore_archive
{
4960 my ($archive, $vmid, $user, $opts) = @_;
4962 my $format = $opts->{format
};
4965 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4966 $format = 'tar' if !$format;
4968 } elsif ($archive =~ m/\.tar$/) {
4969 $format = 'tar' if !$format;
4970 } elsif ($archive =~ m/.tar.lzo$/) {
4971 $format = 'tar' if !$format;
4973 } elsif ($archive =~ m/\.vma$/) {
4974 $format = 'vma' if !$format;
4975 } elsif ($archive =~ m/\.vma\.gz$/) {
4976 $format = 'vma' if !$format;
4978 } elsif ($archive =~ m/\.vma\.lzo$/) {
4979 $format = 'vma' if !$format;
4982 $format = 'vma' if !$format; # default
4985 # try to detect archive format
4986 if ($format eq 'tar') {
4987 return restore_tar_archive
($archive, $vmid, $user, $opts);
4989 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4993 sub restore_update_config_line
{
4994 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4996 return if $line =~ m/^\#qmdump\#/;
4997 return if $line =~ m/^\#vzdump\#/;
4998 return if $line =~ m/^lock:/;
4999 return if $line =~ m/^unused\d+:/;
5000 return if $line =~ m/^parent:/;
5001 return if $line =~ m/^template:/; # restored VM is never a template
5003 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5004 # try to convert old 1.X settings
5005 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5006 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5007 my ($model, $macaddr) = split(/\=/, $devconfig);
5008 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5011 bridge
=> "vmbr$ind",
5012 macaddr
=> $macaddr,
5014 my $netstr = print_net
($net);
5016 print $outfd "net$cookie->{netcount}: $netstr\n";
5017 $cookie->{netcount
}++;
5019 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5020 my ($id, $netstr) = ($1, $2);
5021 my $net = parse_net
($netstr);
5022 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5023 $netstr = print_net
($net);
5024 print $outfd "$id: $netstr\n";
5025 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5028 if ($line =~ m/backup=no/) {
5029 print $outfd "#$line";
5030 } elsif ($virtdev && $map->{$virtdev}) {
5031 my $di = parse_drive
($virtdev, $value);
5032 delete $di->{format
}; # format can change on restore
5033 $di->{file
} = $map->{$virtdev};
5034 $value = print_drive
($vmid, $di);
5035 print $outfd "$virtdev: $value\n";
5045 my ($cfg, $vmid) = @_;
5047 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5049 my $volid_hash = {};
5050 foreach my $storeid (keys %$info) {
5051 foreach my $item (@{$info->{$storeid}}) {
5052 next if !($item->{volid
} && $item->{size
});
5053 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5054 $volid_hash->{$item->{volid
}} = $item;
5061 sub get_used_paths
{
5062 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5066 my $scan_config = sub {
5067 my ($cref, $snapname) = @_;
5069 foreach my $key (keys %$cref) {
5070 my $value = $cref->{$key};
5071 if (valid_drivename
($key)) {
5072 next if $skip_drive && $key eq $skip_drive;
5073 my $drive = parse_drive
($key, $value);
5074 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5075 if ($drive->{file
} =~ m!^/!) {
5076 $used_path->{$drive->{file
}}++; # = 1;
5078 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5080 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5082 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5083 $used_path->{$path}++; # = 1;
5089 &$scan_config($conf);
5093 if ($scan_snapshots) {
5094 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5095 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5102 sub update_disksize
{
5103 my ($vmid, $conf, $volid_hash) = @_;
5109 # Note: it is allowed to define multiple storages with same path (alias), so
5110 # we need to check both 'volid' and real 'path' (two different volid can point
5111 # to the same path).
5116 foreach my $opt (keys %$conf) {
5117 if (valid_drivename
($opt)) {
5118 my $drive = parse_drive
($opt, $conf->{$opt});
5119 my $volid = $drive->{file
};
5122 $used->{$volid} = 1;
5123 if ($volid_hash->{$volid} &&
5124 (my $path = $volid_hash->{$volid}->{path
})) {
5125 $usedpath->{$path} = 1;
5128 next if drive_is_cdrom
($drive);
5129 next if !$volid_hash->{$volid};
5131 $drive->{size
} = $volid_hash->{$volid}->{size
};
5132 my $new = print_drive
($vmid, $drive);
5133 if ($new ne $conf->{$opt}) {
5135 $conf->{$opt} = $new;
5140 # remove 'unusedX' entry if volume is used
5141 foreach my $opt (keys %$conf) {
5142 next if $opt !~ m/^unused\d+$/;
5143 my $volid = $conf->{$opt};
5144 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5145 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5147 delete $conf->{$opt};
5151 foreach my $volid (sort keys %$volid_hash) {
5152 next if $volid =~ m/vm-$vmid-state-/;
5153 next if $used->{$volid};
5154 my $path = $volid_hash->{$volid}->{path
};
5155 next if !$path; # just to be sure
5156 next if $usedpath->{$path};
5158 add_unused_volume
($conf, $volid);
5159 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5166 my ($vmid, $nolock) = @_;
5168 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5170 my $volid_hash = scan_volids
($cfg, $vmid);
5172 my $updatefn = sub {
5175 my $conf = load_config
($vmid);
5180 foreach my $volid (keys %$volid_hash) {
5181 my $info = $volid_hash->{$volid};
5182 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5185 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5187 update_config_nolock
($vmid, $conf, 1) if $changes;
5190 if (defined($vmid)) {
5194 lock_config
($vmid, $updatefn, $vmid);
5197 my $vmlist = config_list
();
5198 foreach my $vmid (keys %$vmlist) {
5202 lock_config
($vmid, $updatefn, $vmid);
5208 sub restore_vma_archive
{
5209 my ($archive, $vmid, $user, $opts, $comp) = @_;
5211 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5212 my $readfrom = $archive;
5217 my $qarchive = PVE
::Tools
::shellquote
($archive);
5218 if ($comp eq 'gzip') {
5219 $uncomp = "zcat $qarchive|";
5220 } elsif ($comp eq 'lzop') {
5221 $uncomp = "lzop -d -c $qarchive|";
5223 die "unknown compression method '$comp'\n";
5228 my $tmpdir = "/var/tmp/vzdumptmp$$";
5231 # disable interrupts (always do cleanups)
5232 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5233 warn "got interrupt - ignored\n";
5236 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5237 POSIX
::mkfifo
($mapfifo, 0600);
5240 my $openfifo = sub {
5241 open($fifofh, '>', $mapfifo) || die $!;
5244 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5251 my $rpcenv = PVE
::RPCEnvironment
::get
();
5253 my $conffile = config_file
($vmid);
5254 my $tmpfn = "$conffile.$$.tmp";
5256 # Note: $oldconf is undef if VM does not exists
5257 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5259 my $print_devmap = sub {
5260 my $virtdev_hash = {};
5262 my $cfgfn = "$tmpdir/qemu-server.conf";
5264 # we can read the config - that is already extracted
5265 my $fh = IO
::File-
>new($cfgfn, "r") ||
5266 "unable to read qemu-server.conf - $!\n";
5268 while (defined(my $line = <$fh>)) {
5269 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5270 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5271 die "archive does not contain data for drive '$virtdev'\n"
5272 if !$devinfo->{$devname};
5273 if (defined($opts->{storage
})) {
5274 $storeid = $opts->{storage
} || 'local';
5275 } elsif (!$storeid) {
5278 $format = 'raw' if !$format;
5279 $devinfo->{$devname}->{devname
} = $devname;
5280 $devinfo->{$devname}->{virtdev
} = $virtdev;
5281 $devinfo->{$devname}->{format
} = $format;
5282 $devinfo->{$devname}->{storeid
} = $storeid;
5284 # check permission on storage
5285 my $pool = $opts->{pool
}; # todo: do we need that?
5286 if ($user ne 'root@pam') {
5287 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5290 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5294 foreach my $devname (keys %$devinfo) {
5295 die "found no device mapping information for device '$devname'\n"
5296 if !$devinfo->{$devname}->{virtdev
};
5299 my $cfg = cfs_read_file
('storage.cfg');
5301 # create empty/temp config
5303 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5304 foreach_drive
($oldconf, sub {
5305 my ($ds, $drive) = @_;
5307 return if drive_is_cdrom
($drive);
5309 my $volid = $drive->{file
};
5311 return if !$volid || $volid =~ m
|^/|;
5313 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5314 return if !$path || !$owner || ($owner != $vmid);
5316 # Note: only delete disk we want to restore
5317 # other volumes will become unused
5318 if ($virtdev_hash->{$ds}) {
5319 PVE
::Storage
::vdisk_free
($cfg, $volid);
5325 foreach my $virtdev (sort keys %$virtdev_hash) {
5326 my $d = $virtdev_hash->{$virtdev};
5327 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5328 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5330 # test if requested format is supported
5331 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5332 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5333 $d->{format
} = $defFormat if !$supported;
5335 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5336 $d->{format
}, undef, $alloc_size);
5337 print STDERR
"new volume ID is '$volid'\n";
5338 $d->{volid
} = $volid;
5339 my $path = PVE
::Storage
::path
($cfg, $volid);
5341 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5343 my $write_zeros = 1;
5344 # fixme: what other storages types initialize volumes with zero?
5345 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5346 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5350 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5352 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5353 $map->{$virtdev} = $volid;
5356 $fh->seek(0, 0) || die "seek failed - $!\n";
5358 my $outfd = new IO
::File
($tmpfn, "w") ||
5359 die "unable to write config for VM $vmid\n";
5361 my $cookie = { netcount
=> 0 };
5362 while (defined(my $line = <$fh>)) {
5363 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5372 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5373 die "interrupted by signal\n";
5375 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5377 $oldtimeout = alarm($timeout);
5384 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5385 my ($dev_id, $size, $devname) = ($1, $2, $3);
5386 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5387 } elsif ($line =~ m/^CTIME: /) {
5388 # we correctly received the vma config, so we can disable
5389 # the timeout now for disk allocation (set to 10 minutes, so
5390 # that we always timeout if something goes wrong)
5393 print $fifofh "done\n";
5394 my $tmp = $oldtimeout || 0;
5395 $oldtimeout = undef;
5401 print "restore vma archive: $cmd\n";
5402 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5406 alarm($oldtimeout) if $oldtimeout;
5409 foreach my $devname (keys %$devinfo) {
5410 my $volid = $devinfo->{$devname}->{volid
};
5411 push @$vollist, $volid if $volid;
5414 my $cfg = cfs_read_file
('storage.cfg');
5415 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5423 foreach my $devname (keys %$devinfo) {
5424 my $volid = $devinfo->{$devname}->{volid
};
5427 if ($volid =~ m
|^/|) {
5428 unlink $volid || die 'unlink failed\n';
5430 PVE
::Storage
::vdisk_free
($cfg, $volid);
5432 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5434 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5441 rename($tmpfn, $conffile) ||
5442 die "unable to commit configuration file '$conffile'\n";
5444 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5446 eval { rescan
($vmid, 1); };
5450 sub restore_tar_archive
{
5451 my ($archive, $vmid, $user, $opts) = @_;
5453 if ($archive ne '-') {
5454 my $firstfile = tar_archive_read_firstfile
($archive);
5455 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5456 if $firstfile ne 'qemu-server.conf';
5459 my $storecfg = cfs_read_file
('storage.cfg');
5461 # destroy existing data - keep empty config
5462 my $vmcfgfn = config_file
($vmid);
5463 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5465 my $tocmd = "/usr/lib/qemu-server/qmextract";
5467 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5468 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5469 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5470 $tocmd .= ' --info' if $opts->{info
};
5472 # tar option "xf" does not autodetect compression when read from STDIN,
5473 # so we pipe to zcat
5474 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5475 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5477 my $tmpdir = "/var/tmp/vzdumptmp$$";
5480 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5481 local $ENV{VZDUMP_VMID
} = $vmid;
5482 local $ENV{VZDUMP_USER
} = $user;
5484 my $conffile = config_file
($vmid);
5485 my $tmpfn = "$conffile.$$.tmp";
5487 # disable interrupts (always do cleanups)
5488 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5489 print STDERR
"got interrupt - ignored\n";
5494 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5495 die "interrupted by signal\n";
5498 if ($archive eq '-') {
5499 print "extracting archive from STDIN\n";
5500 run_command
($cmd, input
=> "<&STDIN");
5502 print "extracting archive '$archive'\n";
5506 return if $opts->{info
};
5510 my $statfile = "$tmpdir/qmrestore.stat";
5511 if (my $fd = IO
::File-
>new($statfile, "r")) {
5512 while (defined (my $line = <$fd>)) {
5513 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5514 $map->{$1} = $2 if $1;
5516 print STDERR
"unable to parse line in statfile - $line\n";
5522 my $confsrc = "$tmpdir/qemu-server.conf";
5524 my $srcfd = new IO
::File
($confsrc, "r") ||
5525 die "unable to open file '$confsrc'\n";
5527 my $outfd = new IO
::File
($tmpfn, "w") ||
5528 die "unable to write config for VM $vmid\n";
5530 my $cookie = { netcount
=> 0 };
5531 while (defined (my $line = <$srcfd>)) {
5532 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5544 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5551 rename $tmpfn, $conffile ||
5552 die "unable to commit configuration file '$conffile'\n";
5554 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5556 eval { rescan
($vmid, 1); };
5561 # Internal snapshots
5563 # NOTE: Snapshot create/delete involves several non-atomic
5564 # action, and can take a long time.
5565 # So we try to avoid locking the file and use 'lock' variable
5566 # inside the config file instead.
5568 my $snapshot_copy_config = sub {
5569 my ($source, $dest) = @_;
5571 foreach my $k (keys %$source) {
5572 next if $k eq 'snapshots';
5573 next if $k eq 'snapstate';
5574 next if $k eq 'snaptime';
5575 next if $k eq 'vmstate';
5576 next if $k eq 'lock';
5577 next if $k eq 'digest';
5578 next if $k eq 'description';
5579 next if $k =~ m/^unused\d+$/;
5581 $dest->{$k} = $source->{$k};
5585 my $snapshot_apply_config = sub {
5586 my ($conf, $snap) = @_;
5588 # copy snapshot list
5590 snapshots
=> $conf->{snapshots
},
5593 # keep description and list of unused disks
5594 foreach my $k (keys %$conf) {
5595 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5596 $newconf->{$k} = $conf->{$k};
5599 &$snapshot_copy_config($snap, $newconf);
5604 sub foreach_writable_storage
{
5605 my ($conf, $func) = @_;
5609 foreach my $ds (keys %$conf) {
5610 next if !valid_drivename
($ds);
5612 my $drive = parse_drive
($ds, $conf->{$ds});
5614 next if drive_is_cdrom
($drive);
5616 my $volid = $drive->{file
};
5618 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5619 $sidhash->{$sid} = $sid if $sid;
5622 foreach my $sid (sort keys %$sidhash) {
5627 my $alloc_vmstate_volid = sub {
5628 my ($storecfg, $vmid, $conf, $snapname) = @_;
5630 # Note: we try to be smart when selecting a $target storage
5634 # search shared storage first
5635 foreach_writable_storage
($conf, sub {
5637 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5638 return if !$scfg->{shared
};
5640 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5644 # now search local storage
5645 foreach_writable_storage
($conf, sub {
5647 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5648 return if $scfg->{shared
};
5650 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5654 $target = 'local' if !$target;
5656 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5657 # we abort live save after $conf->{memory}, so we need at max twice that space
5658 my $size = $conf->{memory
}*2 + $driver_state_size;
5660 my $name = "vm-$vmid-state-$snapname";
5661 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5662 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5663 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5668 my $snapshot_prepare = sub {
5669 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5673 my $updatefn = sub {
5675 my $conf = load_config
($vmid);
5677 die "you can't take a snapshot if it's a template\n"
5678 if is_template
($conf);
5682 $conf->{lock} = 'snapshot';
5684 die "snapshot name '$snapname' already used\n"
5685 if defined($conf->{snapshots
}->{$snapname});
5687 my $storecfg = PVE
::Storage
::config
();
5688 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5690 $snap = $conf->{snapshots
}->{$snapname} = {};
5692 if ($save_vmstate && check_running
($vmid)) {
5693 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5696 &$snapshot_copy_config($conf, $snap);
5698 $snap->{snapstate
} = "prepare";
5699 $snap->{snaptime
} = time();
5700 $snap->{description
} = $comment if $comment;
5702 # always overwrite machine if we save vmstate. This makes sure we
5703 # can restore it later using correct machine type
5704 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5706 update_config_nolock
($vmid, $conf, 1);
5709 lock_config
($vmid, $updatefn);
5714 my $snapshot_commit = sub {
5715 my ($vmid, $snapname) = @_;
5717 my $updatefn = sub {
5719 my $conf = load_config
($vmid);
5721 die "missing snapshot lock\n"
5722 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5724 my $has_machine_config = defined($conf->{machine
});
5726 my $snap = $conf->{snapshots
}->{$snapname};
5728 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5730 die "wrong snapshot state\n"
5731 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5733 delete $snap->{snapstate
};
5734 delete $conf->{lock};
5736 my $newconf = &$snapshot_apply_config($conf, $snap);
5738 delete $newconf->{machine
} if !$has_machine_config;
5740 $newconf->{parent
} = $snapname;
5742 update_config_nolock
($vmid, $newconf, 1);
5745 lock_config
($vmid, $updatefn);
5748 sub snapshot_rollback
{
5749 my ($vmid, $snapname) = @_;
5753 my $storecfg = PVE
::Storage
::config
();
5755 my $conf = load_config
($vmid);
5757 my $get_snapshot_config = sub {
5759 die "you can't rollback if vm is a template\n" if is_template
($conf);
5761 my $res = $conf->{snapshots
}->{$snapname};
5763 die "snapshot '$snapname' does not exist\n" if !defined($res);
5768 my $snap = &$get_snapshot_config();
5770 foreach_drive
($snap, sub {
5771 my ($ds, $drive) = @_;
5773 return if drive_is_cdrom
($drive);
5775 my $volid = $drive->{file
};
5777 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5780 my $updatefn = sub {
5782 $conf = load_config
($vmid);
5784 $snap = &$get_snapshot_config();
5786 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5787 if $snap->{snapstate
};
5791 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5794 die "unable to rollback vm $vmid: vm is running\n"
5795 if check_running
($vmid);
5798 $conf->{lock} = 'rollback';
5800 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5801 delete $conf->{lock};
5807 my $has_machine_config = defined($conf->{machine
});
5809 # copy snapshot config to current config
5810 $conf = &$snapshot_apply_config($conf, $snap);
5811 $conf->{parent
} = $snapname;
5813 # Note: old code did not store 'machine', so we try to be smart
5814 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5815 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5816 # we remove the 'machine' configuration if not explicitly specified
5817 # in the original config.
5818 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5821 update_config_nolock
($vmid, $conf, 1);
5823 if (!$prepare && $snap->{vmstate
}) {
5824 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5825 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5829 lock_config
($vmid, $updatefn);
5831 foreach_drive
($snap, sub {
5832 my ($ds, $drive) = @_;
5834 return if drive_is_cdrom
($drive);
5836 my $volid = $drive->{file
};
5837 my $device = "drive-$ds";
5839 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5843 lock_config
($vmid, $updatefn);
5846 my $savevm_wait = sub {
5850 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5851 if (!$stat->{status
}) {
5852 die "savevm not active\n";
5853 } elsif ($stat->{status
} eq 'active') {
5856 } elsif ($stat->{status
} eq 'completed') {
5859 die "query-savevm returned status '$stat->{status}'\n";
5864 sub do_snapshots_with_qemu
{
5865 my ($storecfg, $volid) = @_;
5867 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5869 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5870 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5874 if ($volid =~ m/\.(qcow2|qed)$/){
5881 sub snapshot_create
{
5882 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5884 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5886 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5888 my $config = load_config
($vmid);
5890 my $running = check_running
($vmid);
5892 my $freezefs = $running && $config->{agent
};
5893 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5898 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5899 warn "guest-fsfreeze-freeze problems - $@" if $@;
5903 # create internal snapshots of all drives
5905 my $storecfg = PVE
::Storage
::config
();
5908 if ($snap->{vmstate
}) {
5909 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5910 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5911 &$savevm_wait($vmid);
5913 vm_mon_cmd
($vmid, "savevm-start");
5917 foreach_drive
($snap, sub {
5918 my ($ds, $drive) = @_;
5920 return if drive_is_cdrom
($drive);
5922 my $volid = $drive->{file
};
5923 my $device = "drive-$ds";
5925 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5926 $drivehash->{$ds} = 1;
5932 eval { vm_mon_cmd
($vmid, "savevm-end") };
5936 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5937 warn "guest-fsfreeze-thaw problems - $@" if $@;
5940 # savevm-end is async, we need to wait
5942 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5943 if (!$stat->{bytes
}) {
5946 print "savevm not yet finished\n";
5954 warn "snapshot create failed: starting cleanup\n";
5955 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5960 &$snapshot_commit($vmid, $snapname);
5963 # Note: $drivehash is only set when called from snapshot_create.
5964 sub snapshot_delete
{
5965 my ($vmid, $snapname, $force, $drivehash) = @_;
5972 my $unlink_parent = sub {
5973 my ($confref, $new_parent) = @_;
5975 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5977 $confref->{parent
} = $new_parent;
5979 delete $confref->{parent
};
5984 my $updatefn = sub {
5985 my ($remove_drive) = @_;
5987 my $conf = load_config
($vmid);
5991 die "you can't delete a snapshot if vm is a template\n"
5992 if is_template
($conf);
5995 $snap = $conf->{snapshots
}->{$snapname};
5997 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5999 # remove parent refs
6001 &$unlink_parent($conf, $snap->{parent
});
6002 foreach my $sn (keys %{$conf->{snapshots
}}) {
6003 next if $sn eq $snapname;
6004 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6008 if ($remove_drive) {
6009 if ($remove_drive eq 'vmstate') {
6010 delete $snap->{$remove_drive};
6012 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6013 my $volid = $drive->{file
};
6014 delete $snap->{$remove_drive};
6015 add_unused_volume
($conf, $volid);
6020 $snap->{snapstate
} = 'delete';
6022 delete $conf->{snapshots
}->{$snapname};
6023 delete $conf->{lock} if $drivehash;
6024 foreach my $volid (@$unused) {
6025 add_unused_volume
($conf, $volid);
6029 update_config_nolock
($vmid, $conf, 1);
6032 lock_config
($vmid, $updatefn);
6034 # now remove vmstate file
6036 my $storecfg = PVE
::Storage
::config
();
6038 if ($snap->{vmstate
}) {
6039 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6041 die $err if !$force;
6044 # save changes (remove vmstate from snapshot)
6045 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6048 # now remove all internal snapshots
6049 foreach_drive
($snap, sub {
6050 my ($ds, $drive) = @_;
6052 return if drive_is_cdrom
($drive);
6054 my $volid = $drive->{file
};
6055 my $device = "drive-$ds";
6057 if (!$drivehash || $drivehash->{$ds}) {
6058 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6060 die $err if !$force;
6065 # save changes (remove drive fron snapshot)
6066 lock_config
($vmid, $updatefn, $ds) if !$force;
6067 push @$unused, $volid;
6070 # now cleanup config
6072 lock_config
($vmid, $updatefn);
6076 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6079 foreach_drive
($conf, sub {
6080 my ($ds, $drive) = @_;
6082 return if drive_is_cdrom
($drive);
6083 my $volid = $drive->{file
};
6084 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6087 return $err ?
0 : 1;
6090 sub template_create
{
6091 my ($vmid, $conf, $disk) = @_;
6093 my $storecfg = PVE
::Storage
::config
();
6095 foreach_drive
($conf, sub {
6096 my ($ds, $drive) = @_;
6098 return if drive_is_cdrom
($drive);
6099 return if $disk && $ds ne $disk;
6101 my $volid = $drive->{file
};
6102 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6104 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6105 $drive->{file
} = $voliddst;
6106 $conf->{$ds} = print_drive
($vmid, $drive);
6107 update_config_nolock
($vmid, $conf, 1);
6114 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6117 sub qemu_img_convert
{
6118 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6120 my $storecfg = PVE
::Storage
::config
();
6121 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6122 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6124 if ($src_storeid && $dst_storeid) {
6125 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6126 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6128 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6129 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6131 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6132 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6135 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6136 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6137 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6141 if($line =~ m/\((\S+)\/100\
%\)/){
6143 my $transferred = int($size * $percent / 100);
6144 my $remaining = $size - $transferred;
6146 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6151 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6153 die "copy failed: $err" if $err;
6157 sub qemu_img_format
{
6158 my ($scfg, $volname) = @_;
6160 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6167 sub qemu_drive_mirror
{
6168 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6170 my $storecfg = PVE
::Storage
::config
();
6171 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6173 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6175 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6177 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6179 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6180 $opts->{format
} = $format if $format;
6182 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6185 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6187 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6188 my $stat = @$stats[0];
6189 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6190 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6192 my $busy = $stat->{busy
};
6193 my $ready = $stat->{ready
};
6195 if (my $total = $stat->{len
}) {
6196 my $transferred = $stat->{offset
} || 0;
6197 my $remaining = $total - $transferred;
6198 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6200 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6204 if ($stat->{ready
} eq 'true') {
6206 last if $vmiddst != $vmid;
6208 # try to switch the disk if source and destination are on the same guest
6209 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6211 die $@ if $@ !~ m/cannot be completed/;
6220 my $cancel_job = sub {
6221 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6223 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6224 my $stat = @$stats[0];
6231 eval { &$cancel_job(); };
6232 die "mirroring error: $err";
6235 if ($vmiddst != $vmid) {
6236 # if we clone a disk for a new target vm, we don't switch the disk
6237 &$cancel_job(); # so we call block-job-cancel
6242 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6243 $newvmid, $storage, $format, $full, $newvollist) = @_;
6248 print "create linked clone of drive $drivename ($drive->{file})\n";
6249 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6250 push @$newvollist, $newvolid;
6252 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6253 $storeid = $storage if $storage;
6255 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6257 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6258 $format = qemu_img_format
($scfg, $volname);
6261 # test if requested format is supported - else use default
6262 my $supported = grep { $_ eq $format } @$validFormats;
6263 $format = $defFormat if !$supported;
6265 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6267 print "create full clone of drive $drivename ($drive->{file})\n";
6268 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6269 push @$newvollist, $newvolid;
6271 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6273 if (!$running || $snapname) {
6274 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6276 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6280 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6283 $disk->{format
} = undef;
6284 $disk->{file
} = $newvolid;
6285 $disk->{size
} = $size;
6290 # this only works if VM is running
6291 sub get_current_qemu_machine
{
6294 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6295 my $res = vm_qmp_command
($vmid, $cmd);
6297 my ($current, $default);
6298 foreach my $e (@$res) {
6299 $default = $e->{name
} if $e->{'is-default'};
6300 $current = $e->{name
} if $e->{'is-current'};
6303 # fallback to the default machine if current is not supported by qemu
6304 return $current || $default || 'pc';
6307 sub qemu_machine_feature_enabled
{
6308 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6313 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6315 $current_major = $3;
6316 $current_minor = $4;
6318 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6320 $current_major = $1;
6321 $current_minor = $2;
6324 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6333 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6334 my (undef, $id, $function) = @_;
6335 my $res = { id
=> $id, function
=> $function};
6336 push @{$devices->{$id}}, $res;
6342 sub vm_iothreads_list
{
6345 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6348 foreach my $iothread (@$res) {
6349 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6356 my ($conf, $drive) = @_;
6360 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6362 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6368 my $controller = int($drive->{index} / $maxdev);
6369 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6371 return ($maxdev, $controller, $controller_prefix);
6374 # bash completion helper
6376 sub complete_backup_archives
{
6377 my ($cmdname, $pname, $cvalue) = @_;
6379 my $cfg = PVE
::Storage
::config
();
6383 if ($cvalue =~ m/^([^:]+):/) {
6387 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6390 foreach my $id (keys %$data) {
6391 foreach my $item (@{$data->{$id}}) {
6392 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6393 push @$res, $item->{volid
} if defined($item->{volid
});
6400 my $complete_vmid_full = sub {
6403 my $idlist = vmstatus
();
6407 foreach my $id (keys %$idlist) {
6408 my $d = $idlist->{$id};
6409 if (defined($running)) {
6410 next if $d->{template
};
6411 next if $running && $d->{status
} ne 'running';
6412 next if !$running && $d->{status
} eq 'running';
6421 return &$complete_vmid_full();
6424 sub complete_vmid_stopped
{
6425 return &$complete_vmid_full(0);
6428 sub complete_vmid_running
{
6429 return &$complete_vmid_full(1);
6432 sub complete_storage
{
6434 my $cfg = PVE
::Storage
::config
();
6435 my $ids = $cfg->{ids
};
6438 foreach my $sid (keys %$ids) {
6439 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);