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]',
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>]',
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]',
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]',
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 [,driver=kvm|vfio] [,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+)?)[,\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]
880 my ($key, $data) = @_;
884 # $key may be undefined - used to verify JSON parameters
885 if (!defined($key)) {
886 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
888 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
889 $res->{interface
} = $1;
895 foreach my $p (split (/,/, $data)) {
896 next if $p =~ m/^\s*$/;
898 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)=(.+)$/) {
899 my ($k, $v) = ($1, $2);
901 $k = 'file' if $k eq 'volume';
903 return undef if defined $res->{$k};
905 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
906 return undef if !$v || $v !~ m/^\d+/;
908 $v = sprintf("%.3f", $v / (1024*1024));
912 if (!$res->{file
} && $p !~ m/=/) {
920 return undef if !$res->{file
};
922 return undef if $res->{cache
} &&
923 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
924 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
925 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
926 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
927 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
928 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
929 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
930 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
931 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
932 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
933 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
934 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
935 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
936 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
937 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
939 return undef if $res->{mbps_rd
} && $res->{mbps
};
940 return undef if $res->{mbps_wr
} && $res->{mbps
};
942 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
943 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
944 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
945 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
946 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
947 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
949 return undef if $res->{iops_rd
} && $res->{iops
};
950 return undef if $res->{iops_wr
} && $res->{iops
};
953 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
954 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
955 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
956 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
957 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
958 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);
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 return "$drive->{file}$opts";
997 my($fh, $noerr) = @_;
1000 my $SG_GET_VERSION_NUM = 0x2282;
1002 my $versionbuf = "\x00" x
8;
1003 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1005 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1008 my $version = unpack("I", $versionbuf);
1009 if ($version < 30000) {
1010 die "scsi generic interface too old\n" if !$noerr;
1014 my $buf = "\x00" x
36;
1015 my $sensebuf = "\x00" x
8;
1016 my $cmd = pack("C x3 C x1", 0x12, 36);
1018 # see /usr/include/scsi/sg.h
1019 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";
1021 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1022 length($sensebuf), 0, length($buf), $buf,
1023 $cmd, $sensebuf, 6000);
1025 $ret = ioctl($fh, $SG_IO, $packet);
1027 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1031 my @res = unpack($sg_io_hdr_t, $packet);
1032 if ($res[17] || $res[18]) {
1033 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1038 (my $byte0, my $byte1, $res->{vendor
},
1039 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1041 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1042 $res->{type
} = $byte0 & 31;
1050 my $fh = IO
::File-
>new("+<$path") || return undef;
1051 my $res = scsi_inquiry
($fh, 1);
1057 sub machine_type_is_q35
{
1060 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1063 sub print_tabletdevice_full
{
1066 my $q35 = machine_type_is_q35
($conf);
1068 # we use uhci for old VMs because tablet driver was buggy in older qemu
1069 my $usbbus = $q35 ?
"ehci" : "uhci";
1071 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1074 sub print_drivedevice_full
{
1075 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1080 if ($drive->{interface
} eq 'virtio') {
1081 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1082 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1083 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1084 } elsif ($drive->{interface
} eq 'scsi') {
1086 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1087 my $unit = $drive->{index} % $maxdev;
1088 my $devicetype = 'hd';
1090 if (drive_is_cdrom
($drive)) {
1093 if ($drive->{file
} =~ m
|^/|) {
1094 $path = $drive->{file
};
1096 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1099 if($path =~ m/^iscsi\:\/\
//){
1100 $devicetype = 'generic';
1102 if (my $info = path_is_scsi
($path)) {
1103 if ($info->{type
} == 0) {
1104 $devicetype = 'block';
1105 } elsif ($info->{type
} == 1) { # tape
1106 $devicetype = 'generic';
1112 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1113 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1115 $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}";
1118 } elsif ($drive->{interface
} eq 'ide'){
1120 my $controller = int($drive->{index} / $maxdev);
1121 my $unit = $drive->{index} % $maxdev;
1122 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1124 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1125 } elsif ($drive->{interface
} eq 'sata'){
1126 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1127 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1128 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1129 } elsif ($drive->{interface
} eq 'usb') {
1131 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1133 die "unsupported interface type";
1136 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1141 sub get_initiator_name
{
1144 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1145 while (defined(my $line = <$fh>)) {
1146 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1155 sub print_drive_full
{
1156 my ($storecfg, $vmid, $drive) = @_;
1159 my $volid = $drive->{file
};
1162 if (drive_is_cdrom
($drive)) {
1163 $path = get_iso_path
($storecfg, $vmid, $volid);
1165 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1167 $path = PVE
::Storage
::path
($storecfg, $volid);
1168 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1169 $format = qemu_img_format
($scfg, $volname);
1176 foreach my $o (@qemu_drive_options) {
1177 next if $o eq 'bootindex';
1178 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1181 $opts .= ",format=$format" if $format && !$drive->{format
};
1183 foreach my $o (qw(bps bps_rd bps_wr)) {
1184 my $v = $drive->{"m$o"};
1185 $opts .= ",$o=" . int($v*1024*1024) if $v;
1188 my $cache_direct = 0;
1190 if (my $cache = $drive->{cache
}) {
1191 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1192 } elsif (!drive_is_cdrom
($drive)) {
1193 $opts .= ",cache=none";
1197 # aio native works only with O_DIRECT
1198 if (!$drive->{aio
}) {
1200 $opts .= ",aio=native";
1202 $opts .= ",aio=threads";
1206 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1207 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1209 my $pathinfo = $path ?
"file=$path," : '';
1211 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1214 sub print_netdevice_full
{
1215 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1217 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1219 my $device = $net->{model
};
1220 if ($net->{model
} eq 'virtio') {
1221 $device = 'virtio-net-pci';
1224 my $pciaddr = print_pci_addr
("$netid", $bridges);
1225 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1226 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1227 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1228 my $vectors = $net->{queues
} * 2 + 2;
1229 $tmpstr .= ",vectors=$vectors,mq=on";
1231 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1235 sub print_netdev_full
{
1236 my ($vmid, $conf, $net, $netid) = @_;
1239 if ($netid =~ m/^net(\d+)$/) {
1243 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1245 my $ifname = "tap${vmid}i$i";
1247 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1248 die "interface name '$ifname' is too long (max 15 character)\n"
1249 if length($ifname) >= 16;
1251 my $vhostparam = '';
1252 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1254 my $vmname = $conf->{name
} || "vm$vmid";
1258 if ($net->{bridge
}) {
1259 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1261 $netdev = "type=user,id=$netid,hostname=$vmname";
1264 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1269 sub drive_is_cdrom
{
1272 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1281 foreach my $kvp (split(/,/, $data)) {
1283 if ($kvp =~ m/^memory=(\S+)$/) {
1284 $res->{memory
} = $1;
1285 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1286 $res->{policy
} = $1;
1287 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1288 $res->{cpus
}->{start
} = $1;
1289 $res->{cpus
}->{end
} = $3;
1290 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1291 $res->{hostnodes
}->{start
} = $1;
1292 $res->{hostnodes
}->{end
} = $3;
1304 return undef if !$value;
1307 my @list = split(/,/, $value);
1311 foreach my $kv (@list) {
1313 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1316 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1319 my $pcidevices = lspci
($2);
1320 $res->{pciid
} = $pcidevices->{$2};
1322 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1323 $res->{driver
} = $1;
1324 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1325 $res->{rombar
} = $1;
1326 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1327 $res->{'x-vga'} = $1;
1328 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1329 $res->{pcie
} = 1 if $1 == 1;
1331 warn "unknown hostpci setting '$kv'\n";
1335 return undef if !$found;
1340 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1346 foreach my $kvp (split(/,/, $data)) {
1348 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) {
1350 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1351 $res->{model
} = $model;
1352 $res->{macaddr
} = $mac;
1353 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1354 $res->{bridge
} = $1;
1355 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1356 $res->{queues
} = $1;
1357 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1359 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1361 } elsif ($kvp =~ m/^firewall=([01])$/) {
1362 $res->{firewall
} = $1;
1363 } elsif ($kvp =~ m/^link_down=([01])$/) {
1364 $res->{link_down
} = $1;
1371 return undef if !$res->{model
};
1379 my $res = "$net->{model}";
1380 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1381 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1382 $res .= ",rate=$net->{rate}" if $net->{rate
};
1383 $res .= ",tag=$net->{tag}" if $net->{tag
};
1384 $res .= ",firewall=1" if $net->{firewall
};
1385 $res .= ",link_down=1" if $net->{link_down
};
1386 $res .= ",queues=$net->{queues}" if $net->{queues
};
1391 sub add_random_macs
{
1392 my ($settings) = @_;
1394 foreach my $opt (keys %$settings) {
1395 next if $opt !~ m/^net(\d+)$/;
1396 my $net = parse_net
($settings->{$opt});
1398 $settings->{$opt} = print_net
($net);
1402 sub add_unused_volume
{
1403 my ($config, $volid) = @_;
1406 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1407 my $test = "unused$ind";
1408 if (my $vid = $config->{$test}) {
1409 return if $vid eq $volid; # do not add duplicates
1415 die "To many unused volume - please delete them first.\n" if !$key;
1417 $config->{$key} = $volid;
1422 sub vm_is_volid_owner
{
1423 my ($storecfg, $vmid, $volid) = @_;
1425 if ($volid !~ m
|^/|) {
1427 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1428 if ($owner && ($owner == $vmid)) {
1436 sub split_flagged_list
{
1437 my $text = shift || '';
1438 $text =~ s/[,;]/ /g;
1440 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1443 sub join_flagged_list
{
1444 my ($how, $lst) = @_;
1445 join $how, map { $lst->{$_} . $_ } keys %$lst;
1448 sub vmconfig_delete_pending_option
{
1449 my ($conf, $key, $force) = @_;
1451 delete $conf->{pending
}->{$key};
1452 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1453 $pending_delete_hash->{$key} = $force ?
'!' : '';
1454 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1457 sub vmconfig_undelete_pending_option
{
1458 my ($conf, $key) = @_;
1460 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1461 delete $pending_delete_hash->{$key};
1463 if (%$pending_delete_hash) {
1464 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1466 delete $conf->{pending
}->{delete};
1470 sub vmconfig_register_unused_drive
{
1471 my ($storecfg, $vmid, $conf, $drive) = @_;
1473 if (!drive_is_cdrom
($drive)) {
1474 my $volid = $drive->{file
};
1475 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1476 add_unused_volume
($conf, $volid, $vmid);
1481 sub vmconfig_cleanup_pending
{
1484 # remove pending changes when nothing changed
1486 foreach my $opt (keys %{$conf->{pending
}}) {
1487 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1489 delete $conf->{pending
}->{$opt};
1493 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1494 my $pending_delete_hash = {};
1495 while (my ($opt, $force) = each %$current_delete_hash) {
1496 if (defined($conf->{$opt})) {
1497 $pending_delete_hash->{$opt} = $force;
1503 if (%$pending_delete_hash) {
1504 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1506 delete $conf->{pending
}->{delete};
1512 my $valid_smbios1_options = {
1513 manufacturer
=> '\S+',
1517 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1522 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1528 foreach my $kvp (split(/,/, $data)) {
1529 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1530 my ($k, $v) = split(/=/, $kvp);
1531 return undef if !defined($k) || !defined($v);
1532 return undef if !$valid_smbios1_options->{$k};
1533 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1544 foreach my $k (keys %$smbios1) {
1545 next if !defined($smbios1->{$k});
1546 next if !$valid_smbios1_options->{$k};
1547 $data .= ',' if $data;
1548 $data .= "$k=$smbios1->{$k}";
1553 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1554 sub verify_smbios1
{
1555 my ($value, $noerr) = @_;
1557 return $value if parse_smbios1
($value);
1559 return undef if $noerr;
1561 die "unable to parse smbios (type 1) options\n";
1564 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1565 sub verify_bootdisk
{
1566 my ($value, $noerr) = @_;
1568 return $value if valid_drivename
($value);
1570 return undef if $noerr;
1572 die "invalid boot disk '$value'\n";
1575 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1577 my ($value, $noerr) = @_;
1579 return $value if parse_numa
($value);
1581 return undef if $noerr;
1583 die "unable to parse numa options\n";
1586 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1588 my ($value, $noerr) = @_;
1590 return $value if parse_net
($value);
1592 return undef if $noerr;
1594 die "unable to parse network options\n";
1597 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1599 my ($value, $noerr) = @_;
1601 return $value if parse_drive
(undef, $value);
1603 return undef if $noerr;
1605 die "unable to parse drive options\n";
1608 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1609 sub verify_hostpci
{
1610 my ($value, $noerr) = @_;
1612 return $value if parse_hostpci
($value);
1614 return undef if $noerr;
1616 die "unable to parse pci id\n";
1619 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1620 sub verify_watchdog
{
1621 my ($value, $noerr) = @_;
1623 return $value if parse_watchdog
($value);
1625 return undef if $noerr;
1627 die "unable to parse watchdog options\n";
1630 sub parse_watchdog
{
1633 return undef if !$value;
1637 foreach my $p (split(/,/, $value)) {
1638 next if $p =~ m/^\s*$/;
1640 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1642 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1643 $res->{action
} = $2;
1652 sub parse_usb_device
{
1655 return undef if !$value;
1657 my @dl = split(/,/, $value);
1661 foreach my $v (@dl) {
1662 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1664 $res->{vendorid
} = $2;
1665 $res->{productid
} = $4;
1666 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1668 $res->{hostbus
} = $1;
1669 $res->{hostport
} = $2;
1670 } elsif ($v =~ m/^spice$/) {
1677 return undef if !$found;
1682 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1683 sub verify_usb_device
{
1684 my ($value, $noerr) = @_;
1686 return $value if parse_usb_device
($value);
1688 return undef if $noerr;
1690 die "unable to parse usb device\n";
1693 # add JSON properties for create and set function
1694 sub json_config_properties
{
1697 foreach my $opt (keys %$confdesc) {
1698 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1699 $prop->{$opt} = $confdesc->{$opt};
1706 my ($key, $value) = @_;
1708 die "unknown setting '$key'\n" if !$confdesc->{$key};
1710 my $type = $confdesc->{$key}->{type
};
1712 if (!defined($value)) {
1713 die "got undefined value\n";
1716 if ($value =~ m/[\n\r]/) {
1717 die "property contains a line feed\n";
1720 if ($type eq 'boolean') {
1721 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1722 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1723 die "type check ('boolean') failed - got '$value'\n";
1724 } elsif ($type eq 'integer') {
1725 return int($1) if $value =~ m/^(\d+)$/;
1726 die "type check ('integer') failed - got '$value'\n";
1727 } elsif ($type eq 'number') {
1728 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1729 die "type check ('number') failed - got '$value'\n";
1730 } elsif ($type eq 'string') {
1731 if (my $fmt = $confdesc->{$key}->{format
}) {
1732 if ($fmt eq 'pve-qm-drive') {
1733 # special case - we need to pass $key to parse_drive()
1734 my $drive = parse_drive
($key, $value);
1735 return $value if $drive;
1736 die "unable to parse drive options\n";
1738 PVE
::JSONSchema
::check_format
($fmt, $value);
1741 $value =~ s/^\"(.*)\"$/$1/;
1744 die "internal error"
1748 sub lock_config_full
{
1749 my ($vmid, $timeout, $code, @param) = @_;
1751 my $filename = config_file_lock
($vmid);
1753 my $res = lock_file
($filename, $timeout, $code, @param);
1760 sub lock_config_mode
{
1761 my ($vmid, $timeout, $shared, $code, @param) = @_;
1763 my $filename = config_file_lock
($vmid);
1765 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1773 my ($vmid, $code, @param) = @_;
1775 return lock_config_full
($vmid, 10, $code, @param);
1778 sub cfs_config_path
{
1779 my ($vmid, $node) = @_;
1781 $node = $nodename if !$node;
1782 return "nodes/$node/qemu-server/$vmid.conf";
1785 sub check_iommu_support
{
1786 #fixme : need to check IOMMU support
1787 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1795 my ($vmid, $node) = @_;
1797 my $cfspath = cfs_config_path
($vmid, $node);
1798 return "/etc/pve/$cfspath";
1801 sub config_file_lock
{
1804 return "$lock_dir/lock-$vmid.conf";
1810 my $conf = config_file
($vmid);
1811 utime undef, undef, $conf;
1815 my ($storecfg, $vmid, $keep_empty_config) = @_;
1817 my $conffile = config_file
($vmid);
1819 my $conf = load_config
($vmid);
1823 # only remove disks owned by this VM
1824 foreach_drive
($conf, sub {
1825 my ($ds, $drive) = @_;
1827 return if drive_is_cdrom
($drive);
1829 my $volid = $drive->{file
};
1831 return if !$volid || $volid =~ m
|^/|;
1833 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1834 return if !$path || !$owner || ($owner != $vmid);
1836 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1839 if ($keep_empty_config) {
1840 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1845 # also remove unused disk
1847 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1850 PVE
::Storage
::foreach_volid
($dl, sub {
1851 my ($volid, $sid, $volname, $d) = @_;
1852 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1862 my ($vmid, $node) = @_;
1864 my $cfspath = cfs_config_path
($vmid, $node);
1866 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1868 die "no such VM ('$vmid')\n" if !defined($conf);
1873 sub parse_vm_config
{
1874 my ($filename, $raw) = @_;
1876 return undef if !defined($raw);
1879 digest
=> Digest
::SHA
::sha1_hex
($raw),
1884 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1885 || die "got strange filename '$filename'";
1893 my @lines = split(/\n/, $raw);
1894 foreach my $line (@lines) {
1895 next if $line =~ m/^\s*$/;
1897 if ($line =~ m/^\[PENDING\]\s*$/i) {
1898 $section = 'pending';
1899 if (defined($descr)) {
1901 $conf->{description
} = $descr;
1904 $conf = $res->{$section} = {};
1907 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1909 if (defined($descr)) {
1911 $conf->{description
} = $descr;
1914 $conf = $res->{snapshots
}->{$section} = {};
1918 if ($line =~ m/^\#(.*)\s*$/) {
1919 $descr = '' if !defined($descr);
1920 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1924 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1925 $descr = '' if !defined($descr);
1926 $descr .= PVE
::Tools
::decode_text
($2);
1927 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1928 $conf->{snapstate
} = $1;
1929 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1932 $conf->{$key} = $value;
1933 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1935 if ($section eq 'pending') {
1936 $conf->{delete} = $value; # we parse this later
1938 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1940 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1943 eval { $value = check_type
($key, $value); };
1945 warn "vm $vmid - unable to parse value of '$key' - $@";
1947 my $fmt = $confdesc->{$key}->{format
};
1948 if ($fmt && $fmt eq 'pve-qm-drive') {
1949 my $v = parse_drive
($key, $value);
1950 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1951 $v->{file
} = $volid;
1952 $value = print_drive
($vmid, $v);
1954 warn "vm $vmid - unable to parse value of '$key'\n";
1959 if ($key eq 'cdrom') {
1960 $conf->{ide2
} = $value;
1962 $conf->{$key} = $value;
1968 if (defined($descr)) {
1970 $conf->{description
} = $descr;
1972 delete $res->{snapstate
}; # just to be sure
1977 sub write_vm_config
{
1978 my ($filename, $conf) = @_;
1980 delete $conf->{snapstate
}; # just to be sure
1982 if ($conf->{cdrom
}) {
1983 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1984 $conf->{ide2
} = $conf->{cdrom
};
1985 delete $conf->{cdrom
};
1988 # we do not use 'smp' any longer
1989 if ($conf->{sockets
}) {
1990 delete $conf->{smp
};
1991 } elsif ($conf->{smp
}) {
1992 $conf->{sockets
} = $conf->{smp
};
1993 delete $conf->{cores
};
1994 delete $conf->{smp
};
1997 my $used_volids = {};
1999 my $cleanup_config = sub {
2000 my ($cref, $pending, $snapname) = @_;
2002 foreach my $key (keys %$cref) {
2003 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2004 $key eq 'snapstate' || $key eq 'pending';
2005 my $value = $cref->{$key};
2006 if ($key eq 'delete') {
2007 die "propertry 'delete' is only allowed in [PENDING]\n"
2009 # fixme: check syntax?
2012 eval { $value = check_type
($key, $value); };
2013 die "unable to parse value of '$key' - $@" if $@;
2015 $cref->{$key} = $value;
2017 if (!$snapname && valid_drivename
($key)) {
2018 my $drive = parse_drive
($key, $value);
2019 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2024 &$cleanup_config($conf);
2026 &$cleanup_config($conf->{pending
}, 1);
2028 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2029 die "internal error" if $snapname eq 'pending';
2030 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2033 # remove 'unusedX' settings if we re-add a volume
2034 foreach my $key (keys %$conf) {
2035 my $value = $conf->{$key};
2036 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2037 delete $conf->{$key};
2041 my $generate_raw_config = sub {
2042 my ($conf, $pending) = @_;
2046 # add description as comment to top of file
2047 if (defined(my $descr = $conf->{description
})) {
2049 foreach my $cl (split(/\n/, $descr)) {
2050 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2053 $raw .= "#\n" if $pending;
2057 foreach my $key (sort keys %$conf) {
2058 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2059 $raw .= "$key: $conf->{$key}\n";
2064 my $raw = &$generate_raw_config($conf);
2066 if (scalar(keys %{$conf->{pending
}})){
2067 $raw .= "\n[PENDING]\n";
2068 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2071 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2072 $raw .= "\n[$snapname]\n";
2073 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2079 sub update_config_nolock
{
2080 my ($vmid, $conf, $skiplock) = @_;
2082 check_lock
($conf) if !$skiplock;
2084 my $cfspath = cfs_config_path
($vmid);
2086 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2090 my ($vmid, $conf, $skiplock) = @_;
2092 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2099 # we use static defaults from our JSON schema configuration
2100 foreach my $key (keys %$confdesc) {
2101 if (defined(my $default = $confdesc->{$key}->{default})) {
2102 $res->{$key} = $default;
2106 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2107 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2113 my $vmlist = PVE
::Cluster
::get_vmlist
();
2115 return $res if !$vmlist || !$vmlist->{ids
};
2116 my $ids = $vmlist->{ids
};
2118 foreach my $vmid (keys %$ids) {
2119 my $d = $ids->{$vmid};
2120 next if !$d->{node
} || $d->{node
} ne $nodename;
2121 next if !$d->{type
} || $d->{type
} ne 'qemu';
2122 $res->{$vmid}->{exists} = 1;
2127 # test if VM uses local resources (to prevent migration)
2128 sub check_local_resources
{
2129 my ($conf, $noerr) = @_;
2133 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2134 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2136 foreach my $k (keys %$conf) {
2137 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2138 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2141 die "VM uses local resources\n" if $loc_res && !$noerr;
2146 # check if used storages are available on all nodes (use by migrate)
2147 sub check_storage_availability
{
2148 my ($storecfg, $conf, $node) = @_;
2150 foreach_drive
($conf, sub {
2151 my ($ds, $drive) = @_;
2153 my $volid = $drive->{file
};
2156 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2159 # check if storage is available on both nodes
2160 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2161 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2165 # list nodes where all VM images are available (used by has_feature API)
2167 my ($conf, $storecfg) = @_;
2169 my $nodelist = PVE
::Cluster
::get_nodelist
();
2170 my $nodehash = { map { $_ => 1 } @$nodelist };
2171 my $nodename = PVE
::INotify
::nodename
();
2173 foreach_drive
($conf, sub {
2174 my ($ds, $drive) = @_;
2176 my $volid = $drive->{file
};
2179 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2181 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2182 if ($scfg->{disable
}) {
2184 } elsif (my $avail = $scfg->{nodes
}) {
2185 foreach my $node (keys %$nodehash) {
2186 delete $nodehash->{$node} if !$avail->{$node};
2188 } elsif (!$scfg->{shared
}) {
2189 foreach my $node (keys %$nodehash) {
2190 delete $nodehash->{$node} if $node ne $nodename
2202 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2206 my ($pidfile, $pid) = @_;
2208 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2212 return undef if !$line;
2213 my @param = split(/\0/, $line);
2215 my $cmd = $param[0];
2216 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2218 for (my $i = 0; $i < scalar (@param); $i++) {
2221 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2222 my $p = $param[$i+1];
2223 return 1 if $p && ($p eq $pidfile);
2232 my ($vmid, $nocheck, $node) = @_;
2234 my $filename = config_file
($vmid, $node);
2236 die "unable to find configuration file for VM $vmid - no such machine\n"
2237 if !$nocheck && ! -f
$filename;
2239 my $pidfile = pidfile_name
($vmid);
2241 if (my $fd = IO
::File-
>new("<$pidfile")) {
2246 my $mtime = $st->mtime;
2247 if ($mtime > time()) {
2248 warn "file '$filename' modified in future\n";
2251 if ($line =~ m/^(\d+)$/) {
2253 if (check_cmdline
($pidfile, $pid)) {
2254 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2266 my $vzlist = config_list
();
2268 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2270 while (defined(my $de = $fd->read)) {
2271 next if $de !~ m/^(\d+)\.pid$/;
2273 next if !defined($vzlist->{$vmid});
2274 if (my $pid = check_running
($vmid)) {
2275 $vzlist->{$vmid}->{pid
} = $pid;
2283 my ($storecfg, $conf) = @_;
2285 my $bootdisk = $conf->{bootdisk
};
2286 return undef if !$bootdisk;
2287 return undef if !valid_drivename
($bootdisk);
2289 return undef if !$conf->{$bootdisk};
2291 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2292 return undef if !defined($drive);
2294 return undef if drive_is_cdrom
($drive);
2296 my $volid = $drive->{file
};
2297 return undef if !$volid;
2299 return $drive->{size
};
2302 my $last_proc_pid_stat;
2304 # get VM status information
2305 # This must be fast and should not block ($full == false)
2306 # We only query KVM using QMP if $full == true (this can be slow)
2308 my ($opt_vmid, $full) = @_;
2312 my $storecfg = PVE
::Storage
::config
();
2314 my $list = vzlist
();
2315 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2317 my $cpucount = $cpuinfo->{cpus
} || 1;
2319 foreach my $vmid (keys %$list) {
2320 next if $opt_vmid && ($vmid ne $opt_vmid);
2322 my $cfspath = cfs_config_path
($vmid);
2323 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2326 $d->{pid
} = $list->{$vmid}->{pid
};
2328 # fixme: better status?
2329 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2331 my $size = disksize
($storecfg, $conf);
2332 if (defined($size)) {
2333 $d->{disk
} = 0; # no info available
2334 $d->{maxdisk
} = $size;
2340 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2341 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2342 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2344 $d->{name
} = $conf->{name
} || "VM $vmid";
2345 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2347 if ($conf->{balloon
}) {
2348 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2349 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2360 $d->{diskwrite
} = 0;
2362 $d->{template
} = is_template
($conf);
2367 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2368 foreach my $dev (keys %$netdev) {
2369 next if $dev !~ m/^tap([1-9]\d*)i/;
2371 my $d = $res->{$vmid};
2374 $d->{netout
} += $netdev->{$dev}->{receive
};
2375 $d->{netin
} += $netdev->{$dev}->{transmit
};
2378 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2379 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2384 my $ctime = gettimeofday
;
2386 foreach my $vmid (keys %$list) {
2388 my $d = $res->{$vmid};
2389 my $pid = $d->{pid
};
2392 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2393 next if !$pstat; # not running
2395 my $used = $pstat->{utime} + $pstat->{stime
};
2397 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2399 if ($pstat->{vsize
}) {
2400 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2403 my $old = $last_proc_pid_stat->{$pid};
2405 $last_proc_pid_stat->{$pid} = {
2413 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2415 if ($dtime > 1000) {
2416 my $dutime = $used - $old->{used
};
2418 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2419 $last_proc_pid_stat->{$pid} = {
2425 $d->{cpu
} = $old->{cpu
};
2429 return $res if !$full;
2431 my $qmpclient = PVE
::QMPClient-
>new();
2433 my $ballooncb = sub {
2434 my ($vmid, $resp) = @_;
2436 my $info = $resp->{'return'};
2437 return if !$info->{max_mem
};
2439 my $d = $res->{$vmid};
2441 # use memory assigned to VM
2442 $d->{maxmem
} = $info->{max_mem
};
2443 $d->{balloon
} = $info->{actual
};
2445 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2446 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2447 $d->{freemem
} = $info->{free_mem
};
2450 $d->{ballooninfo
} = $info;
2453 my $blockstatscb = sub {
2454 my ($vmid, $resp) = @_;
2455 my $data = $resp->{'return'} || [];
2456 my $totalrdbytes = 0;
2457 my $totalwrbytes = 0;
2459 for my $blockstat (@$data) {
2460 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2461 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2463 $blockstat->{device
} =~ s/drive-//;
2464 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2466 $res->{$vmid}->{diskread
} = $totalrdbytes;
2467 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2470 my $statuscb = sub {
2471 my ($vmid, $resp) = @_;
2473 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2474 # this fails if ballon driver is not loaded, so this must be
2475 # the last commnand (following command are aborted if this fails).
2476 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2478 my $status = 'unknown';
2479 if (!defined($status = $resp->{'return'}->{status
})) {
2480 warn "unable to get VM status\n";
2484 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2487 foreach my $vmid (keys %$list) {
2488 next if $opt_vmid && ($vmid ne $opt_vmid);
2489 next if !$res->{$vmid}->{pid
}; # not running
2490 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2493 $qmpclient->queue_execute(undef, 1);
2495 foreach my $vmid (keys %$list) {
2496 next if $opt_vmid && ($vmid ne $opt_vmid);
2497 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2504 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2507 my $current_size = 1024;
2508 my $dimm_size = 512;
2509 return if $current_size == $memory;
2511 for (my $j = 0; $j < 8; $j++) {
2512 for (my $i = 0; $i < 32; $i++) {
2513 my $name = "dimm${dimm_id}";
2515 my $numanode = $i % $sockets;
2516 $current_size += $dimm_size;
2517 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2518 return $current_size if $current_size >= $memory;
2524 sub foreach_reverse_dimm
{
2525 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2528 my $current_size = 4177920;
2529 my $dimm_size = 65536;
2530 return if $current_size == $memory;
2532 for (my $j = 0; $j < 8; $j++) {
2533 for (my $i = 0; $i < 32; $i++) {
2534 my $name = "dimm${dimm_id}";
2536 my $numanode = $i % $sockets;
2537 $current_size -= $dimm_size;
2538 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2539 return $current_size if $current_size <= $memory;
2546 my ($conf, $func) = @_;
2548 foreach my $ds (keys %$conf) {
2549 next if !valid_drivename
($ds);
2551 my $drive = parse_drive
($ds, $conf->{$ds});
2554 &$func($ds, $drive);
2559 my ($conf, $func) = @_;
2563 my $test_volid = sub {
2564 my ($volid, $is_cdrom) = @_;
2568 $volhash->{$volid} = $is_cdrom || 0;
2571 foreach_drive
($conf, sub {
2572 my ($ds, $drive) = @_;
2573 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2576 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2577 my $snap = $conf->{snapshots
}->{$snapname};
2578 &$test_volid($snap->{vmstate
}, 0);
2579 foreach_drive
($snap, sub {
2580 my ($ds, $drive) = @_;
2581 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2585 foreach my $volid (keys %$volhash) {
2586 &$func($volid, $volhash->{$volid});
2590 sub vga_conf_has_spice
{
2593 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2598 sub config_to_command
{
2599 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2602 my $globalFlags = [];
2603 my $machineFlags = [];
2609 my $kvmver = kvm_user_version
();
2610 my $vernum = 0; # unknown
2611 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2612 $vernum = $1*1000000+$2*1000;
2613 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2614 $vernum = $1*1000000+$2*1000+$3;
2617 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2619 my $have_ovz = -f
'/proc/vz/vestat';
2621 my $q35 = machine_type_is_q35
($conf);
2622 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2623 my $machine_type = $forcemachine || $conf->{machine
};
2625 my $cpuunits = defined($conf->{cpuunits
}) ?
2626 $conf->{cpuunits
} : $defaults->{cpuunits
};
2628 push @$cmd, '/usr/bin/systemd-run';
2629 push @$cmd, '--scope';
2630 push @$cmd, '--slice', "qemu";
2631 push @$cmd, '--unit', $vmid;
2632 push @$cmd, '-p', "CPUShares=$cpuunits";
2633 if ($conf->{cpulimit
}) {
2634 my $cpulimit = int($conf->{cpulimit
} * 100);
2635 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2638 push @$cmd, '/usr/bin/kvm';
2640 push @$cmd, '-id', $vmid;
2644 my $qmpsocket = qmp_socket
($vmid);
2645 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2646 push @$cmd, '-mon', "chardev=qmp,mode=control";
2648 my $socket = vnc_socket
($vmid);
2649 push @$cmd, '-vnc', "unix:$socket,x509,password";
2651 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2653 push @$cmd, '-daemonize';
2655 if ($conf->{smbios1
}) {
2656 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2660 # the q35 chipset support native usb2, so we enable usb controller
2661 # by default for this machine type
2662 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2664 $pciaddr = print_pci_addr
("piix3", $bridges);
2665 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2668 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2669 next if !$conf->{"usb$i"};
2672 # include usb device config
2673 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2676 my $vga = $conf->{vga
};
2678 my $qxlnum = vga_conf_has_spice
($vga);
2679 $vga = 'qxl' if $qxlnum;
2682 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2683 $conf->{ostype
} eq 'win7' ||
2684 $conf->{ostype
} eq 'w2k8')) {
2691 # enable absolute mouse coordinates (needed by vnc)
2693 if (defined($conf->{tablet
})) {
2694 $tablet = $conf->{tablet
};
2696 $tablet = $defaults->{tablet
};
2697 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2698 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2701 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2704 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2705 my $d = parse_hostpci
($conf->{"hostpci$i"});
2708 my $pcie = $d->{pcie
};
2710 die "q35 machine model is not enabled" if !$q35;
2711 $pciaddr = print_pcie_addr
("hostpci$i");
2713 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2716 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2717 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2718 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2719 if ($xvga && $xvga ne '') {
2720 push @$cpuFlags, 'kvm=off';
2723 $driver = "vfio-pci" if $xvga ne '';
2724 my $pcidevices = $d->{pciid
};
2725 my $multifunction = 1 if @$pcidevices > 1;
2728 foreach my $pcidevice (@$pcidevices) {
2730 my $id = "hostpci$i";
2731 $id .= ".$j" if $multifunction;
2732 my $addr = $pciaddr;
2733 $addr .= ".$j" if $multifunction;
2734 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2737 $devicestr .= "$rombar$xvga";
2738 $devicestr .= ",multifunction=on" if $multifunction;
2741 push @$devices, '-device', $devicestr;
2747 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2748 my $d = parse_usb_device
($conf->{"usb$i"});
2750 if ($d->{vendorid
} && $d->{productid
}) {
2751 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2752 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2753 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2754 } elsif ($d->{spice
}) {
2755 # usb redir support for spice
2756 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2757 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2762 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2763 if (my $path = $conf->{"serial$i"}) {
2764 if ($path eq 'socket') {
2765 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2766 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2767 push @$devices, '-device', "isa-serial,chardev=serial$i";
2769 die "no such serial device\n" if ! -c
$path;
2770 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2771 push @$devices, '-device', "isa-serial,chardev=serial$i";
2777 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2778 if (my $path = $conf->{"parallel$i"}) {
2779 die "no such parallel device\n" if ! -c
$path;
2780 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2781 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2782 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2786 my $vmname = $conf->{name
} || "vm$vmid";
2788 push @$cmd, '-name', $vmname;
2791 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2792 $sockets = $conf->{sockets
} if $conf->{sockets
};
2794 my $cores = $conf->{cores
} || 1;
2796 my $maxcpus = $sockets * $cores;
2798 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2800 my $allowed_vcpus = $cpuinfo->{cpus
};
2802 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2803 if ($allowed_vcpus < $maxcpus);
2805 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2807 push @$cmd, '-nodefaults';
2809 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2811 my $bootindex_hash = {};
2813 foreach my $o (split(//, $bootorder)) {
2814 $bootindex_hash->{$o} = $i*100;
2818 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2820 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2822 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2824 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2827 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2829 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2830 my $useLocaltime = $conf->{localtime};
2832 if (my $ost = $conf->{ostype
}) {
2833 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2835 if ($ost =~ m/^w/) { # windows
2836 $useLocaltime = 1 if !defined($conf->{localtime});
2838 # use time drift fix when acpi is enabled
2839 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2840 $tdf = 1 if !defined($conf->{tdf
});
2844 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2846 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2847 push @$cmd, '-no-hpet';
2848 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2849 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2850 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2851 push @$cpuFlags , 'hv_time' if !$nokvm;
2854 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2858 if ($ost eq 'win7' || $ost eq 'win8') {
2859 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2863 push @$rtcFlags, 'driftfix=slew' if $tdf;
2866 push @$machineFlags, 'accel=tcg';
2868 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2871 if ($machine_type) {
2872 push @$machineFlags, "type=${machine_type}";
2875 if ($conf->{startdate
}) {
2876 push @$rtcFlags, "base=$conf->{startdate}";
2877 } elsif ($useLocaltime) {
2878 push @$rtcFlags, 'base=localtime';
2881 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2882 $cpu = $conf->{cpu
} if $conf->{cpu
};
2884 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2886 push @$cpuFlags , '-x2apic'
2887 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2889 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2891 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2893 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2895 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2896 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2899 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2901 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2903 push @$cmd, '-cpu', $cpu;
2905 my $memory = $conf->{memory
} || $defaults->{memory
};
2906 my $static_memory = 0;
2907 my $dimm_memory = 0;
2909 if ($hotplug_features->{memory
}) {
2910 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2911 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2912 $static_memory = $STATICMEM;
2913 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2914 $dimm_memory = $memory - $static_memory;
2915 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2919 $static_memory = $memory;
2920 push @$cmd, '-m', $static_memory;
2923 if ($conf->{numa
}) {
2925 my $numa_totalmemory = undef;
2926 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2927 next if !$conf->{"numa$i"};
2928 my $numa = parse_numa
($conf->{"numa$i"});
2931 die "missing numa node$i memory value\n" if !$numa->{memory
};
2932 my $numa_memory = $numa->{memory
};
2933 $numa_totalmemory += $numa_memory;
2934 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2937 my $cpus_start = $numa->{cpus
}->{start
};
2938 die "missing numa node$i cpus\n" if !defined($cpus_start);
2939 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2940 my $cpus = $cpus_start;
2941 if (defined($cpus_end)) {
2942 $cpus .= "-$cpus_end";
2943 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2947 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2948 if (defined($hostnodes_start)) {
2949 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2950 my $hostnodes = $hostnodes_start;
2951 if (defined($hostnodes_end)) {
2952 $hostnodes .= "-$hostnodes_end";
2953 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2956 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2957 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2958 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2962 my $policy = $numa->{policy
};
2963 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2964 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2967 push @$cmd, '-object', $numa_object;
2968 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2971 die "total memory for NUMA nodes must be equal to vm static memory\n"
2972 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2974 #if no custom tology, we split memory and cores across numa nodes
2975 if(!$numa_totalmemory) {
2977 my $numa_memory = ($static_memory / $sockets) . "M";
2979 for (my $i = 0; $i < $sockets; $i++) {
2981 my $cpustart = ($cores * $i);
2982 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2983 my $cpus = $cpustart;
2984 $cpus .= "-$cpuend" if $cpuend;
2986 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2987 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2992 if ($hotplug_features->{memory
}) {
2993 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2994 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2995 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2996 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2998 #if dimm_memory is not aligned to dimm map
2999 if($current_size > $memory) {
3000 $conf->{memory
} = $current_size;
3001 update_config_nolock
($vmid, $conf, 1);
3006 push @$cmd, '-S' if $conf->{freeze
};
3008 # set keyboard layout
3009 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3010 push @$cmd, '-k', $kb if $kb;
3013 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3014 #push @$cmd, '-soundhw', 'es1370';
3015 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3017 if($conf->{agent
}) {
3018 my $qgasocket = qmp_socket
($vmid, 1);
3019 my $pciaddr = print_pci_addr
("qga0", $bridges);
3020 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3021 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3022 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3029 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3030 for(my $i = 1; $i < $qxlnum; $i++){
3031 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3032 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3035 # assume other OS works like Linux
3036 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3037 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3041 my $pciaddr = print_pci_addr
("spice", $bridges);
3043 my $nodename = PVE
::INotify
::nodename
();
3044 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3045 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3047 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3049 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3050 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3051 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3054 # enable balloon by default, unless explicitly disabled
3055 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3056 $pciaddr = print_pci_addr
("balloon0", $bridges);
3057 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3060 if ($conf->{watchdog
}) {
3061 my $wdopts = parse_watchdog
($conf->{watchdog
});
3062 $pciaddr = print_pci_addr
("watchdog", $bridges);
3063 my $watchdog = $wdopts->{model
} || 'i6300esb';
3064 push @$devices, '-device', "$watchdog$pciaddr";
3065 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3069 my $scsicontroller = {};
3070 my $ahcicontroller = {};
3071 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3073 # Add iscsi initiator name if available
3074 if (my $initiator = get_initiator_name
()) {
3075 push @$devices, '-iscsi', "initiator-name=$initiator";
3078 foreach_drive
($conf, sub {
3079 my ($ds, $drive) = @_;
3081 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3082 push @$vollist, $drive->{file
};
3085 $use_virtio = 1 if $ds =~ m/^virtio/;
3087 if (drive_is_cdrom
($drive)) {
3088 if ($bootindex_hash->{d
}) {
3089 $drive->{bootindex
} = $bootindex_hash->{d
};
3090 $bootindex_hash->{d
} += 1;
3093 if ($bootindex_hash->{c
}) {
3094 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3095 $bootindex_hash->{c
} += 1;
3099 if($drive->{interface
} eq 'virtio'){
3100 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3103 if ($drive->{interface
} eq 'scsi') {
3105 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3107 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3108 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3111 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3112 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3113 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3117 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3118 $queues = ",num_queues=$drive->{queues}";
3121 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3122 $scsicontroller->{$controller}=1;
3125 if ($drive->{interface
} eq 'sata') {
3126 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3127 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3128 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3129 $ahcicontroller->{$controller}=1;
3132 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3133 push @$devices, '-drive',$drive_cmd;
3134 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3137 for (my $i = 0; $i < $MAX_NETS; $i++) {
3138 next if !$conf->{"net$i"};
3139 my $d = parse_net
($conf->{"net$i"});
3142 $use_virtio = 1 if $d->{model
} eq 'virtio';
3144 if ($bootindex_hash->{n
}) {
3145 $d->{bootindex
} = $bootindex_hash->{n
};
3146 $bootindex_hash->{n
} += 1;
3149 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3150 push @$devices, '-netdev', $netdevfull;
3152 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3153 push @$devices, '-device', $netdevicefull;
3158 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3163 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3165 while (my ($k, $v) = each %$bridges) {
3166 $pciaddr = print_pci_addr
("pci.$k");
3167 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3172 if ($conf->{args
}) {
3173 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3177 push @$cmd, @$devices;
3178 push @$cmd, '-rtc', join(',', @$rtcFlags)
3179 if scalar(@$rtcFlags);
3180 push @$cmd, '-machine', join(',', @$machineFlags)
3181 if scalar(@$machineFlags);
3182 push @$cmd, '-global', join(',', @$globalFlags)
3183 if scalar(@$globalFlags);
3185 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3190 return "${var_run_tmpdir}/$vmid.vnc";
3196 my $res = vm_mon_cmd
($vmid, 'query-spice');
3198 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3202 my ($vmid, $qga) = @_;
3203 my $sockettype = $qga ?
'qga' : 'qmp';
3204 return "${var_run_tmpdir}/$vmid.$sockettype";
3209 return "${var_run_tmpdir}/$vmid.pid";
3212 sub vm_devices_list
{
3215 my $res = vm_mon_cmd
($vmid, 'query-pci');
3217 foreach my $pcibus (@$res) {
3218 foreach my $device (@{$pcibus->{devices
}}) {
3219 next if !$device->{'qdev_id'};
3220 if ($device->{'pci_bridge'}) {
3221 $devices->{$device->{'qdev_id'}} = 1;
3222 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3223 next if !$bridge_device->{'qdev_id'};
3224 $devices->{$bridge_device->{'qdev_id'}} = 1;
3225 $devices->{$device->{'qdev_id'}}++;
3228 $devices->{$device->{'qdev_id'}} = 1;
3233 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3234 foreach my $block (@$resblock) {
3235 if($block->{device
} =~ m/^drive-(\S+)/){
3240 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3241 foreach my $mice (@$resmice) {
3242 if ($mice->{name
} eq 'QEMU HID Tablet') {
3243 $devices->{tablet
} = 1;
3252 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3254 my $q35 = machine_type_is_q35
($conf);
3256 my $devices_list = vm_devices_list
($vmid);
3257 return 1 if defined($devices_list->{$deviceid});
3259 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3261 if ($deviceid eq 'tablet') {
3263 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3265 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3267 qemu_iothread_add
($vmid, $deviceid, $device);
3269 qemu_driveadd
($storecfg, $vmid, $device);
3270 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3272 qemu_deviceadd
($vmid, $devicefull);
3273 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3275 eval { qemu_drivedel
($vmid, $deviceid); };
3280 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3283 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3284 my $pciaddr = print_pci_addr
($deviceid);
3285 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3287 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3289 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3290 qemu_iothread_add
($vmid, $deviceid, $device);
3291 $devicefull .= ",iothread=iothread-$deviceid";
3294 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3295 $devicefull .= ",num_queues=$device->{queues}";
3298 qemu_deviceadd
($vmid, $devicefull);
3299 qemu_deviceaddverify
($vmid, $deviceid);
3301 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3303 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3304 qemu_driveadd
($storecfg, $vmid, $device);
3306 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3307 eval { qemu_deviceadd
($vmid, $devicefull); };
3309 eval { qemu_drivedel
($vmid, $deviceid); };
3314 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3316 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3317 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3318 qemu_deviceadd
($vmid, $netdevicefull);
3319 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3321 eval { qemu_netdevdel
($vmid, $deviceid); };
3326 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3329 my $pciaddr = print_pci_addr
($deviceid);
3330 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3332 qemu_deviceadd
($vmid, $devicefull);
3333 qemu_deviceaddverify
($vmid, $deviceid);
3336 die "can't hotplug device '$deviceid'\n";
3342 # fixme: this should raise exceptions on error!
3343 sub vm_deviceunplug
{
3344 my ($vmid, $conf, $deviceid) = @_;
3346 my $devices_list = vm_devices_list
($vmid);
3347 return 1 if !defined($devices_list->{$deviceid});
3349 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3351 if ($deviceid eq 'tablet') {
3353 qemu_devicedel
($vmid, $deviceid);
3355 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3357 qemu_devicedel
($vmid, $deviceid);
3358 qemu_devicedelverify
($vmid, $deviceid);
3359 qemu_drivedel
($vmid, $deviceid);
3360 qemu_iothread_del
($conf, $vmid, $deviceid);
3362 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3364 qemu_devicedel
($vmid, $deviceid);
3365 qemu_devicedelverify
($vmid, $deviceid);
3366 qemu_iothread_del
($conf, $vmid, $deviceid);
3368 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3370 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3371 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3372 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3374 qemu_devicedel
($vmid, $deviceid);
3375 qemu_drivedel
($vmid, $deviceid);
3376 qemu_deletescsihw
($conf, $vmid, $deviceid);
3378 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3380 qemu_devicedel
($vmid, $deviceid);
3381 qemu_devicedelverify
($vmid, $deviceid);
3382 qemu_netdevdel
($vmid, $deviceid);
3385 die "can't unplug device '$deviceid'\n";
3391 sub qemu_deviceadd
{
3392 my ($vmid, $devicefull) = @_;
3394 $devicefull = "driver=".$devicefull;
3395 my %options = split(/[=,]/, $devicefull);
3397 vm_mon_cmd
($vmid, "device_add" , %options);
3400 sub qemu_devicedel
{
3401 my ($vmid, $deviceid) = @_;
3403 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3406 sub qemu_iothread_add
{
3407 my($vmid, $deviceid, $device) = @_;
3409 if ($device->{iothread
}) {
3410 my $iothreads = vm_iothreads_list
($vmid);
3411 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3415 sub qemu_iothread_del
{
3416 my($conf, $vmid, $deviceid) = @_;
3418 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3419 if ($device->{iothread
}) {
3420 my $iothreads = vm_iothreads_list
($vmid);
3421 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3425 sub qemu_objectadd
{
3426 my($vmid, $objectid, $qomtype) = @_;
3428 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3433 sub qemu_objectdel
{
3434 my($vmid, $objectid) = @_;
3436 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3442 my ($storecfg, $vmid, $device) = @_;
3444 my $drive = print_drive_full
($storecfg, $vmid, $device);
3445 $drive =~ s/\\/\\\\/g;
3446 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3448 # If the command succeeds qemu prints: "OK
"
3449 return 1 if $ret =~ m/OK/s;
3451 die "adding drive failed
: $ret\n";
3455 my($vmid, $deviceid) = @_;
3457 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3460 return 1 if $ret eq "";
3462 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3463 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3465 die "deleting drive
$deviceid failed
: $ret\n";
3468 sub qemu_deviceaddverify {
3469 my ($vmid, $deviceid) = @_;
3471 for (my $i = 0; $i <= 5; $i++) {
3472 my $devices_list = vm_devices_list($vmid);
3473 return 1 if defined($devices_list->{$deviceid});
3477 die "error on hotplug device
'$deviceid'\n";
3481 sub qemu_devicedelverify {
3482 my ($vmid, $deviceid) = @_;
3484 # need to verify that the device is correctly removed as device_del
3485 # is async and empty return is not reliable
3487 for (my $i = 0; $i <= 5; $i++) {
3488 my $devices_list = vm_devices_list($vmid);
3489 return 1 if !defined($devices_list->{$deviceid});
3493 die "error on hot-unplugging device
'$deviceid'\n";
3496 sub qemu_findorcreatescsihw {
3497 my ($storecfg, $conf, $vmid, $device) = @_;
3499 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3501 my $scsihwid="$controller_prefix$controller";
3502 my $devices_list = vm_devices_list($vmid);
3504 if(!defined($devices_list->{$scsihwid})) {
3505 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3511 sub qemu_deletescsihw {
3512 my ($conf, $vmid, $opt) = @_;
3514 my $device = parse_drive($opt, $conf->{$opt});
3516 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3517 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3521 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3523 my $devices_list = vm_devices_list($vmid);
3524 foreach my $opt (keys %{$devices_list}) {
3525 if (PVE::QemuServer::valid_drivename($opt)) {
3526 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3527 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3533 my $scsihwid="scsihw
$controller";
3535 vm_deviceunplug($vmid, $conf, $scsihwid);
3540 sub qemu_add_pci_bridge {
3541 my ($storecfg, $conf, $vmid, $device) = @_;
3547 print_pci_addr($device, $bridges);
3549 while (my ($k, $v) = each %$bridges) {
3552 return 1 if !defined($bridgeid) || $bridgeid < 1;
3554 my $bridge = "pci
.$bridgeid";
3555 my $devices_list = vm_devices_list($vmid);
3557 if (!defined($devices_list->{$bridge})) {
3558 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3564 sub qemu_set_link_status {
3565 my ($vmid, $device, $up) = @_;
3567 vm_mon_cmd($vmid, "set_link
", name => $device,
3568 up => $up ? JSON::true : JSON::false);
3571 sub qemu_netdevadd {
3572 my ($vmid, $conf, $device, $deviceid) = @_;
3574 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3575 my %options = split(/[=,]/, $netdev);
3577 vm_mon_cmd($vmid, "netdev_add
", %options);
3581 sub qemu_netdevdel {
3582 my ($vmid, $deviceid) = @_;
3584 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3587 sub qemu_cpu_hotplug {
3588 my ($vmid, $conf, $vcpus) = @_;
3591 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3592 $sockets = $conf->{sockets} if $conf->{sockets};
3593 my $cores = $conf->{cores} || 1;
3594 my $maxcpus = $sockets * $cores;
3596 $vcpus = $maxcpus if !$vcpus;
3598 die "you can
't add more vcpus than maxcpus\n"
3599 if $vcpus > $maxcpus;
3601 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3602 die "online cpu unplug is not yet possible\n"
3603 if $vcpus < $currentvcpus;
3605 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3606 die "vcpus in running vm is different than configuration\n"
3607 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3609 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3610 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3614 sub qemu_memory_hotplug {
3615 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3617 return $value if !check_running($vmid);
3619 my $memory = $conf->{memory} || $defaults->{memory};
3620 $value = $defaults->{memory} if !$value;
3621 return $value if $value == $memory;
3623 my $static_memory = $STATICMEM;
3624 my $dimm_memory = $memory - $static_memory;
3626 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3627 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3631 $sockets = $conf->{sockets} if $conf->{sockets};
3633 if($value > $memory) {
3635 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3636 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3638 return if $current_size <= $conf->{memory};
3640 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3642 eval { qemu_objectdel($vmid, "mem-
$name"); };
3646 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3648 eval { qemu_objectdel($vmid, "mem-
$name"); };
3651 #update conf after each succesful module hotplug
3652 $conf->{memory} = $current_size;
3653 update_config_nolock($vmid, $conf, 1);
3658 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3659 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3661 return if $current_size >= $conf->{memory};
3662 print "try to unplug memory dimm
$name\n";
3666 eval { qemu_devicedel($vmid, $name) };
3668 my $dimm_list = qemu_dimm_list($vmid);
3669 last if !$dimm_list->{$name};
3670 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3674 #update conf after each succesful module unplug
3675 $conf->{memory} = $current_size;
3677 eval { qemu_objectdel($vmid, "mem-
$name"); };
3678 update_config_nolock($vmid, $conf, 1);
3683 sub qemu_dimm_list {
3686 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3689 foreach my $dimm (@$dimmarray) {
3691 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3692 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3693 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3694 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3695 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3700 sub qemu_block_set_io_throttle {
3701 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3703 return if !check_running($vmid) ;
3705 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));
3709 # old code, only used to shutdown old VM after update
3711 my ($fh, $timeout) = @_;
3713 my $sel = new IO::Select;
3720 while (scalar (@ready = $sel->can_read($timeout))) {
3722 if ($count = $fh->sysread($buf, 8192)) {
3723 if ($buf =~ /^(.*)\(qemu\) $/s) {
3730 if (!defined($count)) {
3737 die "monitor
read timeout
\n" if !scalar(@ready);
3742 # old code, only used to shutdown old VM after update
3743 sub vm_monitor_command {
3744 my ($vmid, $cmdstr, $nocheck) = @_;
3749 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3751 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3753 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3754 die "unable to
connect to VM
$vmid socket - $!\n";
3758 # hack: migrate sometime blocks the monitor (when migrate_downtime
3760 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3761 $timeout = 60*60; # 1 hour
3765 my $data = __read_avail($sock, $timeout);
3767 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3768 die "got unexpected qemu monitor banner
\n";
3771 my $sel = new IO::Select;
3774 if (!scalar(my @ready = $sel->can_write($timeout))) {
3775 die "monitor
write error
- timeout
";
3778 my $fullcmd = "$cmdstr\r";
3780 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3783 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3784 die "monitor
write error
- $!";
3787 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3791 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3792 $timeout = 60*60; # 1 hour
3793 } elsif ($cmdstr =~ m/^(eject|change)/) {
3794 $timeout = 60; # note: cdrom mount command is slow
3796 if ($res = __read_avail($sock, $timeout)) {
3798 my @lines = split("\r?
\n", $res);
3800 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3802 $res = join("\n", @lines);
3810 syslog("err
", "VM
$vmid monitor command failed
- $err");
3817 sub qemu_block_resize {
3818 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3820 my $running = check_running($vmid);
3822 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3824 return if !$running;
3826 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3830 sub qemu_volume_snapshot {
3831 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3833 my $running = check_running($vmid);
3835 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3836 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3838 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3842 sub qemu_volume_snapshot_delete {
3843 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3845 my $running = check_running($vmid);
3847 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3849 return if !$running;
3851 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3854 sub set_migration_caps {
3860 "auto-converge
" => 1,
3862 "x-rdma-pin-all
" => 0,
3866 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3868 for my $supported_capability (@$supported_capabilities) {
3870 capability => $supported_capability->{capability},
3871 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3875 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3878 my $fast_plug_option = {
3887 # hotplug changes in [PENDING]
3888 # $selection hash can be used to only apply specified options, for
3889 # example: { cores => 1 } (only apply changed 'cores')
3890 # $errors ref is used to return error messages
3891 sub vmconfig_hotplug_pending {
3892 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3894 my $defaults = load_defaults();
3896 # commit values which do not have any impact on running VM first
3897 # Note: those option cannot raise errors, we we do not care about
3898 # $selection and always apply them.
3900 my $add_error = sub {
3901 my ($opt, $msg) = @_;
3902 $errors->{$opt} = "hotplug problem
- $msg";
3906 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3907 if ($fast_plug_option->{$opt}) {
3908 $conf->{$opt} = $conf->{pending}->{$opt};
3909 delete $conf->{pending}->{$opt};
3915 update_config_nolock($vmid, $conf, 1);
3916 $conf = load_config($vmid); # update/reload
3919 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3921 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3922 while (my ($opt, $force) = each %$pending_delete_hash) {
3923 next if $selection && !$selection->{$opt};
3925 if ($opt eq 'hotplug') {
3926 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3927 } elsif ($opt eq 'tablet') {
3928 die "skip
\n" if !$hotplug_features->{usb};
3929 if ($defaults->{tablet}) {
3930 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3932 vm_deviceunplug($vmid, $conf, $opt);
3934 } elsif ($opt eq 'vcpus') {
3935 die "skip
\n" if !$hotplug_features->{cpu};
3936 qemu_cpu_hotplug($vmid, $conf, undef);
3937 } elsif ($opt eq 'balloon') {
3938 # enable balloon device is not hotpluggable
3939 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3940 } elsif ($fast_plug_option->{$opt}) {
3942 } elsif ($opt =~ m/^net(\d+)$/) {
3943 die "skip
\n" if !$hotplug_features->{network};
3944 vm_deviceunplug($vmid, $conf, $opt);
3945 } elsif (valid_drivename($opt)) {
3946 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3947 vm_deviceunplug($vmid, $conf, $opt);
3948 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3949 } elsif ($opt =~ m/^memory$/) {
3950 die "skip
\n" if !$hotplug_features->{memory};
3951 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3952 } elsif ($opt eq 'cpuunits') {
3953 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3954 } elsif ($opt eq 'cpulimit') {
3955 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3961 &$add_error($opt, $err) if $err ne "skip
\n";
3963 # save new config if hotplug was successful
3964 delete $conf->{$opt};
3965 vmconfig_undelete_pending_option($conf, $opt);
3966 update_config_nolock($vmid, $conf, 1);
3967 $conf = load_config($vmid); # update/reload
3971 foreach my $opt (keys %{$conf->{pending}}) {
3972 next if $selection && !$selection->{$opt};
3973 my $value = $conf->{pending}->{$opt};
3975 if ($opt eq 'hotplug') {
3976 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3977 } elsif ($opt eq 'tablet') {
3978 die "skip
\n" if !$hotplug_features->{usb};
3980 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3981 } elsif ($value == 0) {
3982 vm_deviceunplug($vmid, $conf, $opt);
3984 } elsif ($opt eq 'vcpus') {
3985 die "skip
\n" if !$hotplug_features->{cpu};
3986 qemu_cpu_hotplug($vmid, $conf, $value);
3987 } elsif ($opt eq 'balloon') {
3988 # enable/disable balloning device is not hotpluggable
3989 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3990 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3991 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3993 # allow manual ballooning if shares is set to zero
3994 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3995 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3996 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3998 } elsif ($opt =~ m/^net(\d+)$/) {
3999 # some changes can be done without hotplug
4000 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4001 $vmid, $opt, $value);
4002 } elsif (valid_drivename($opt)) {
4003 # some changes can be done without hotplug
4004 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4005 $vmid, $opt, $value, 1);
4006 } elsif ($opt =~ m/^memory$/) { #dimms
4007 die "skip
\n" if !$hotplug_features->{memory};
4008 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4009 } elsif ($opt eq 'cpuunits') {
4010 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4011 } elsif ($opt eq 'cpulimit') {
4012 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4013 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4015 die "skip
\n"; # skip non-hot-pluggable options
4019 &$add_error($opt, $err) if $err ne "skip
\n";
4021 # save new config if hotplug was successful
4022 $conf->{$opt} = $value;
4023 delete $conf->{pending}->{$opt};
4024 update_config_nolock($vmid, $conf, 1);
4025 $conf = load_config($vmid); # update/reload
4030 sub try_deallocate_drive {
4031 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4033 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4034 my $volid = $drive->{file};
4035 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4036 my $sid = PVE::Storage::parse_volume_id($volid);
4037 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4039 # check if the disk is really unused
4040 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4041 my $path = PVE::Storage::path($storecfg, $volid);
4042 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4043 if $used_paths->{$path};
4044 PVE::Storage::vdisk_free($storecfg, $volid);
4047 # If vm is not owner of this disk remove from config
4055 sub vmconfig_delete_or_detach_drive {
4056 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4058 my $drive = parse_drive($opt, $conf->{$opt});
4060 my $rpcenv = PVE::RPCEnvironment::get();
4061 my $authuser = $rpcenv->get_user();
4064 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4065 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4067 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4071 sub vmconfig_apply_pending {
4072 my ($vmid, $conf, $storecfg) = @_;
4076 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4077 while (my ($opt, $force) = each %$pending_delete_hash) {
4078 die "internal error
" if $opt =~ m/^unused/;
4079 $conf = load_config($vmid); # update/reload
4080 if (!defined($conf->{$opt})) {
4081 vmconfig_undelete_pending_option($conf, $opt);
4082 update_config_nolock($vmid, $conf, 1);
4083 } elsif (valid_drivename($opt)) {
4084 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4085 vmconfig_undelete_pending_option($conf, $opt);
4086 delete $conf->{$opt};
4087 update_config_nolock($vmid, $conf, 1);
4089 vmconfig_undelete_pending_option($conf, $opt);
4090 delete $conf->{$opt};
4091 update_config_nolock($vmid, $conf, 1);
4095 $conf = load_config($vmid); # update/reload
4097 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4098 $conf = load_config($vmid); # update/reload
4100 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4101 # skip if nothing changed
4102 } elsif (valid_drivename($opt)) {
4103 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4104 if defined($conf->{$opt});
4105 $conf->{$opt} = $conf->{pending}->{$opt};
4107 $conf->{$opt} = $conf->{pending}->{$opt};
4110 delete $conf->{pending}->{$opt};
4111 update_config_nolock($vmid, $conf, 1);
4115 my $safe_num_ne = sub {
4118 return 0 if !defined($a) && !defined($b);
4119 return 1 if !defined($a);
4120 return 1 if !defined($b);
4125 my $safe_string_ne = sub {
4128 return 0 if !defined($a) && !defined($b);
4129 return 1 if !defined($a);
4130 return 1 if !defined($b);
4135 sub vmconfig_update_net {
4136 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4138 my $newnet = parse_net($value);
4140 if ($conf->{$opt}) {
4141 my $oldnet = parse_net($conf->{$opt});
4143 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4144 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4145 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4146 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4148 # for non online change, we try to hot-unplug
4149 die "skip
\n" if !$hotplug;
4150 vm_deviceunplug($vmid, $conf, $opt);
4153 die "internal error
" if $opt !~ m/net(\d+)/;
4154 my $iface = "tap
${vmid
}i
$1";
4156 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4157 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4160 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4161 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4162 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4163 PVE::Network::tap_unplug($iface);
4164 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4167 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4168 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4176 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4182 sub vmconfig_update_disk {
4183 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4185 # fixme: do we need force?
4187 my $drive = parse_drive($opt, $value);
4189 if ($conf->{$opt}) {
4191 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4193 my $media = $drive->{media} || 'disk';
4194 my $oldmedia = $old_drive->{media} || 'disk';
4195 die "unable to change media type
\n" if $media ne $oldmedia;
4197 if (!drive_is_cdrom($old_drive)) {
4199 if ($drive->{file} ne $old_drive->{file}) {
4201 die "skip
\n" if !$hotplug;
4203 # unplug and register as unused
4204 vm_deviceunplug($vmid, $conf, $opt);
4205 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4208 # update existing disk
4210 # skip non hotpluggable value
4211 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4212 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4213 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4214 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4219 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4220 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4221 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4222 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4223 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4224 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4225 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4226 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4227 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4228 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4229 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4230 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4232 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4233 ($drive->{mbps} || 0)*1024*1024,
4234 ($drive->{mbps_rd} || 0)*1024*1024,
4235 ($drive->{mbps_wr} || 0)*1024*1024,
4236 $drive->{iops} || 0,
4237 $drive->{iops_rd} || 0,
4238 $drive->{iops_wr} || 0,
4239 ($drive->{mbps_max} || 0)*1024*1024,
4240 ($drive->{mbps_rd_max} || 0)*1024*1024,
4241 ($drive->{mbps_wr_max} || 0)*1024*1024,
4242 $drive->{iops_max} || 0,
4243 $drive->{iops_rd_max} || 0,
4244 $drive->{iops_wr_max} || 0);
4253 if ($drive->{file} eq 'none') {
4254 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4256 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4257 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4258 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4266 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4268 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4272 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4274 lock_config($vmid, sub {
4275 my $conf = load_config($vmid, $migratedfrom);
4277 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4279 check_lock($conf) if !$skiplock;
4281 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4283 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4284 vmconfig_apply_pending($vmid, $conf, $storecfg);
4285 $conf = load_config($vmid); # update/reload
4288 my $defaults = load_defaults();
4290 # set environment variable useful inside network script
4291 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4293 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4295 my $migrate_port = 0;
4298 if ($statefile eq 'tcp') {
4299 my $localip = "localhost
";
4300 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4301 my $nodename = PVE::INotify::nodename();
4302 if ($datacenterconf->{migration_unsecure}) {
4303 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4305 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4306 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4307 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4308 push @$cmd, '-incoming', $migrate_uri;
4311 push @$cmd, '-loadstate', $statefile;
4318 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4319 my $d = parse_hostpci($conf->{"hostpci
$i"});
4321 my $pcidevices = $d->{pciid};
4322 foreach my $pcidevice (@$pcidevices) {
4323 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4325 my $info = pci_device_info("0000:$pciid");
4326 die "IOMMU
not present
\n" if !check_iommu_support();
4327 die "no pci device info
for device
'$pciid'\n" if !$info;
4329 if ($d->{driver} && $d->{driver} eq "vfio
") {
4330 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4332 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4335 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4339 PVE::Storage::activate_volumes($storecfg, $vollist);
4341 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4344 die "start failed: $err" if $err;
4346 print "migration listens on $migrate_uri\n" if $migrate_uri;
4348 if ($statefile && $statefile ne 'tcp
') {
4349 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4353 if ($migratedfrom) {
4356 set_migration_caps($vmid);
4361 print "spice listens on port $spice_port\n";
4362 if ($spice_ticket) {
4363 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4364 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4370 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4371 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4372 if $conf->{balloon};
4375 foreach my $opt (keys %$conf) {
4376 next if $opt !~ m/^net\d+$/;
4377 my $nicconf = parse_net($conf->{$opt});
4378 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4382 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4383 path => "machine/peripheral/balloon0",
4384 property => "guest-stats-polling-interval",
4385 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4391 my ($vmid, $execute, %params) = @_;
4393 my $cmd = { execute => $execute, arguments => \%params };
4394 vm_qmp_command($vmid, $cmd);
4397 sub vm_mon_cmd_nocheck {
4398 my ($vmid, $execute, %params) = @_;
4400 my $cmd = { execute => $execute, arguments => \%params };
4401 vm_qmp_command($vmid, $cmd, 1);
4404 sub vm_qmp_command {
4405 my ($vmid, $cmd, $nocheck) = @_;
4410 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4411 $timeout = $cmd->{arguments}->{timeout};
4412 delete $cmd->{arguments}->{timeout};
4416 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4417 my $sname = qmp_socket($vmid);
4418 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4419 my $qmpclient = PVE::QMPClient->new();
4421 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4422 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4423 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4424 if scalar(%{$cmd->{arguments}});
4425 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4427 die "unable to
open monitor
socket\n";
4431 syslog("err
", "VM
$vmid qmp command failed
- $err");
4438 sub vm_human_monitor_command {
4439 my ($vmid, $cmdline) = @_;
4444 execute => 'human-monitor-command',
4445 arguments => { 'command-line' => $cmdline},
4448 return vm_qmp_command($vmid, $cmd);
4451 sub vm_commandline {
4452 my ($storecfg, $vmid) = @_;
4454 my $conf = load_config($vmid);
4456 my $defaults = load_defaults();
4458 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4460 return join(' ', @$cmd);
4464 my ($vmid, $skiplock) = @_;
4466 lock_config($vmid, sub {
4468 my $conf = load_config($vmid);
4470 check_lock($conf) if !$skiplock;
4472 vm_mon_cmd($vmid, "system_reset
");
4476 sub get_vm_volumes {
4480 foreach_volid($conf, sub {
4481 my ($volid, $is_cdrom) = @_;
4483 return if $volid =~ m|^/|;
4485 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4488 push @$vollist, $volid;
4494 sub vm_stop_cleanup {
4495 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4500 my $vollist = get_vm_volumes($conf);
4501 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4504 foreach my $ext (qw(mon qmp pid vnc qga)) {
4505 unlink "/var/run/qemu-server/${vmid}.$ext";
4508 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4510 warn $@ if $@; # avoid errors - just warn
4513 # Note: use $nockeck to skip tests if VM configuration file exists.
4514 # We need that when migration VMs to other nodes (files already moved)
4515 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4517 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4519 $force = 1 if !defined($force) && !$shutdown;
4522 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4523 kill 15, $pid if $pid;
4524 my $conf = load_config
($vmid, $migratedfrom);
4525 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4529 lock_config
($vmid, sub {
4531 my $pid = check_running
($vmid, $nocheck);
4536 $conf = load_config
($vmid);
4537 check_lock
($conf) if !$skiplock;
4538 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4539 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4540 $timeout = $opts->{down
} if $opts->{down
};
4544 $timeout = 60 if !defined($timeout);
4548 if (defined($conf) && $conf->{agent
}) {
4549 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4551 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4554 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4561 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4566 if ($count >= $timeout) {
4568 warn "VM still running - terminating now with SIGTERM\n";
4571 die "VM quit/powerdown failed - got timeout\n";
4574 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4579 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4582 die "VM quit/powerdown failed\n";
4590 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4595 if ($count >= $timeout) {
4596 warn "VM still running - terminating now with SIGKILL\n";
4601 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4606 my ($vmid, $skiplock) = @_;
4608 lock_config
($vmid, sub {
4610 my $conf = load_config
($vmid);
4612 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4614 vm_mon_cmd
($vmid, "stop");
4619 my ($vmid, $skiplock) = @_;
4621 lock_config
($vmid, sub {
4623 my $conf = load_config
($vmid);
4625 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4627 vm_mon_cmd
($vmid, "cont");
4632 my ($vmid, $skiplock, $key) = @_;
4634 lock_config
($vmid, sub {
4636 my $conf = load_config
($vmid);
4638 # there is no qmp command, so we use the human monitor command
4639 vm_human_monitor_command
($vmid, "sendkey $key");
4644 my ($storecfg, $vmid, $skiplock) = @_;
4646 lock_config
($vmid, sub {
4648 my $conf = load_config
($vmid);
4650 check_lock
($conf) if !$skiplock;
4652 if (!check_running
($vmid)) {
4653 destroy_vm
($storecfg, $vmid);
4655 die "VM $vmid is running - destroy failed\n";
4663 my ($filename, $buf) = @_;
4665 my $fh = IO
::File-
>new($filename, "w");
4666 return undef if !$fh;
4668 my $res = print $fh $buf;
4675 sub pci_device_info
{
4680 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4681 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4683 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4684 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4686 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4687 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4689 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4690 return undef if !defined($product) || $product !~ s/^0x//;
4695 product
=> $product,
4701 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4710 my $name = $dev->{name
};
4712 my $fn = "$pcisysfs/devices/$name/reset";
4714 return file_write
($fn, "1");
4717 sub pci_dev_bind_to_stub
{
4720 my $name = $dev->{name
};
4722 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4723 return 1 if -d
$testdir;
4725 my $data = "$dev->{vendor} $dev->{product}";
4726 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4728 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4729 if (!file_write
($fn, $name)) {
4730 return undef if -f
$fn;
4733 $fn = "$pcisysfs/drivers/pci-stub/bind";
4734 if (! -d
$testdir) {
4735 return undef if !file_write
($fn, $name);
4741 sub pci_dev_bind_to_vfio
{
4744 my $name = $dev->{name
};
4746 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4748 if (!-d
$vfio_basedir) {
4749 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4751 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4753 my $testdir = "$vfio_basedir/$name";
4754 return 1 if -d
$testdir;
4756 my $data = "$dev->{vendor} $dev->{product}";
4757 return undef if !file_write
("$vfio_basedir/new_id", $data);
4759 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4760 if (!file_write
($fn, $name)) {
4761 return undef if -f
$fn;
4764 $fn = "$vfio_basedir/bind";
4765 if (! -d
$testdir) {
4766 return undef if !file_write
($fn, $name);
4772 sub pci_dev_group_bind_to_vfio
{
4775 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4777 if (!-d
$vfio_basedir) {
4778 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4780 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4782 # get IOMMU group devices
4783 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4784 my @devs = grep /^0000:/, readdir($D);
4787 foreach my $pciid (@devs) {
4788 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4790 # pci bridges, switches or root ports are not supported
4791 # they have a pci_bus subdirectory so skip them
4792 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4794 my $info = pci_device_info
($1);
4795 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4801 sub print_pci_addr
{
4802 my ($id, $bridges) = @_;
4806 piix3
=> { bus
=> 0, addr
=> 1 },
4807 #addr2 : first videocard
4808 balloon0
=> { bus
=> 0, addr
=> 3 },
4809 watchdog
=> { bus
=> 0, addr
=> 4 },
4810 scsihw0
=> { bus
=> 0, addr
=> 5 },
4811 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4812 scsihw1
=> { bus
=> 0, addr
=> 6 },
4813 ahci0
=> { bus
=> 0, addr
=> 7 },
4814 qga0
=> { bus
=> 0, addr
=> 8 },
4815 spice
=> { bus
=> 0, addr
=> 9 },
4816 virtio0
=> { bus
=> 0, addr
=> 10 },
4817 virtio1
=> { bus
=> 0, addr
=> 11 },
4818 virtio2
=> { bus
=> 0, addr
=> 12 },
4819 virtio3
=> { bus
=> 0, addr
=> 13 },
4820 virtio4
=> { bus
=> 0, addr
=> 14 },
4821 virtio5
=> { bus
=> 0, addr
=> 15 },
4822 hostpci0
=> { bus
=> 0, addr
=> 16 },
4823 hostpci1
=> { bus
=> 0, addr
=> 17 },
4824 net0
=> { bus
=> 0, addr
=> 18 },
4825 net1
=> { bus
=> 0, addr
=> 19 },
4826 net2
=> { bus
=> 0, addr
=> 20 },
4827 net3
=> { bus
=> 0, addr
=> 21 },
4828 net4
=> { bus
=> 0, addr
=> 22 },
4829 net5
=> { bus
=> 0, addr
=> 23 },
4830 vga1
=> { bus
=> 0, addr
=> 24 },
4831 vga2
=> { bus
=> 0, addr
=> 25 },
4832 vga3
=> { bus
=> 0, addr
=> 26 },
4833 hostpci2
=> { bus
=> 0, addr
=> 27 },
4834 hostpci3
=> { bus
=> 0, addr
=> 28 },
4835 #addr29 : usb-host (pve-usb.cfg)
4836 'pci.1' => { bus
=> 0, addr
=> 30 },
4837 'pci.2' => { bus
=> 0, addr
=> 31 },
4838 'net6' => { bus
=> 1, addr
=> 1 },
4839 'net7' => { bus
=> 1, addr
=> 2 },
4840 'net8' => { bus
=> 1, addr
=> 3 },
4841 'net9' => { bus
=> 1, addr
=> 4 },
4842 'net10' => { bus
=> 1, addr
=> 5 },
4843 'net11' => { bus
=> 1, addr
=> 6 },
4844 'net12' => { bus
=> 1, addr
=> 7 },
4845 'net13' => { bus
=> 1, addr
=> 8 },
4846 'net14' => { bus
=> 1, addr
=> 9 },
4847 'net15' => { bus
=> 1, addr
=> 10 },
4848 'net16' => { bus
=> 1, addr
=> 11 },
4849 'net17' => { bus
=> 1, addr
=> 12 },
4850 'net18' => { bus
=> 1, addr
=> 13 },
4851 'net19' => { bus
=> 1, addr
=> 14 },
4852 'net20' => { bus
=> 1, addr
=> 15 },
4853 'net21' => { bus
=> 1, addr
=> 16 },
4854 'net22' => { bus
=> 1, addr
=> 17 },
4855 'net23' => { bus
=> 1, addr
=> 18 },
4856 'net24' => { bus
=> 1, addr
=> 19 },
4857 'net25' => { bus
=> 1, addr
=> 20 },
4858 'net26' => { bus
=> 1, addr
=> 21 },
4859 'net27' => { bus
=> 1, addr
=> 22 },
4860 'net28' => { bus
=> 1, addr
=> 23 },
4861 'net29' => { bus
=> 1, addr
=> 24 },
4862 'net30' => { bus
=> 1, addr
=> 25 },
4863 'net31' => { bus
=> 1, addr
=> 26 },
4864 'virtio6' => { bus
=> 2, addr
=> 1 },
4865 'virtio7' => { bus
=> 2, addr
=> 2 },
4866 'virtio8' => { bus
=> 2, addr
=> 3 },
4867 'virtio9' => { bus
=> 2, addr
=> 4 },
4868 'virtio10' => { bus
=> 2, addr
=> 5 },
4869 'virtio11' => { bus
=> 2, addr
=> 6 },
4870 'virtio12' => { bus
=> 2, addr
=> 7 },
4871 'virtio13' => { bus
=> 2, addr
=> 8 },
4872 'virtio14' => { bus
=> 2, addr
=> 9 },
4873 'virtio15' => { bus
=> 2, addr
=> 10 },
4874 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4875 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4876 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4877 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4878 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4879 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4880 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4881 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4882 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4883 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4884 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4885 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4886 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4887 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4888 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4889 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4890 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4891 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4892 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4893 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4894 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4895 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4896 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4897 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4898 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4899 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4900 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4901 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4902 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4903 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4904 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4908 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4909 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4910 my $bus = $devices->{$id}->{bus
};
4911 $res = ",bus=pci.$bus,addr=$addr";
4912 $bridges->{$bus} = 1 if $bridges;
4918 sub print_pcie_addr
{
4923 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4924 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4925 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4926 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4929 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4930 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4931 my $bus = $devices->{$id}->{bus
};
4932 $res = ",bus=$bus,addr=$addr";
4938 # vzdump restore implementaion
4940 sub tar_archive_read_firstfile
{
4941 my $archive = shift;
4943 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4945 # try to detect archive type first
4946 my $pid = open (TMP
, "tar tf '$archive'|") ||
4947 die "unable to open file '$archive'\n";
4948 my $firstfile = <TMP
>;
4952 die "ERROR: archive contaions no data\n" if !$firstfile;
4958 sub tar_restore_cleanup
{
4959 my ($storecfg, $statfile) = @_;
4961 print STDERR
"starting cleanup\n";
4963 if (my $fd = IO
::File-
>new($statfile, "r")) {
4964 while (defined(my $line = <$fd>)) {
4965 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4968 if ($volid =~ m
|^/|) {
4969 unlink $volid || die 'unlink failed\n';
4971 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4973 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4975 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4977 print STDERR
"unable to parse line in statfile - $line";
4984 sub restore_archive
{
4985 my ($archive, $vmid, $user, $opts) = @_;
4987 my $format = $opts->{format
};
4990 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4991 $format = 'tar' if !$format;
4993 } elsif ($archive =~ m/\.tar$/) {
4994 $format = 'tar' if !$format;
4995 } elsif ($archive =~ m/.tar.lzo$/) {
4996 $format = 'tar' if !$format;
4998 } elsif ($archive =~ m/\.vma$/) {
4999 $format = 'vma' if !$format;
5000 } elsif ($archive =~ m/\.vma\.gz$/) {
5001 $format = 'vma' if !$format;
5003 } elsif ($archive =~ m/\.vma\.lzo$/) {
5004 $format = 'vma' if !$format;
5007 $format = 'vma' if !$format; # default
5010 # try to detect archive format
5011 if ($format eq 'tar') {
5012 return restore_tar_archive
($archive, $vmid, $user, $opts);
5014 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5018 sub restore_update_config_line
{
5019 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5021 return if $line =~ m/^\#qmdump\#/;
5022 return if $line =~ m/^\#vzdump\#/;
5023 return if $line =~ m/^lock:/;
5024 return if $line =~ m/^unused\d+:/;
5025 return if $line =~ m/^parent:/;
5026 return if $line =~ m/^template:/; # restored VM is never a template
5028 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5029 # try to convert old 1.X settings
5030 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5031 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5032 my ($model, $macaddr) = split(/\=/, $devconfig);
5033 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5036 bridge
=> "vmbr$ind",
5037 macaddr
=> $macaddr,
5039 my $netstr = print_net
($net);
5041 print $outfd "net$cookie->{netcount}: $netstr\n";
5042 $cookie->{netcount
}++;
5044 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5045 my ($id, $netstr) = ($1, $2);
5046 my $net = parse_net
($netstr);
5047 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5048 $netstr = print_net
($net);
5049 print $outfd "$id: $netstr\n";
5050 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5053 if ($line =~ m/backup=no/) {
5054 print $outfd "#$line";
5055 } elsif ($virtdev && $map->{$virtdev}) {
5056 my $di = parse_drive
($virtdev, $value);
5057 delete $di->{format
}; # format can change on restore
5058 $di->{file
} = $map->{$virtdev};
5059 $value = print_drive
($vmid, $di);
5060 print $outfd "$virtdev: $value\n";
5070 my ($cfg, $vmid) = @_;
5072 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5074 my $volid_hash = {};
5075 foreach my $storeid (keys %$info) {
5076 foreach my $item (@{$info->{$storeid}}) {
5077 next if !($item->{volid
} && $item->{size
});
5078 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5079 $volid_hash->{$item->{volid
}} = $item;
5086 sub get_used_paths
{
5087 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5091 my $scan_config = sub {
5092 my ($cref, $snapname) = @_;
5094 foreach my $key (keys %$cref) {
5095 my $value = $cref->{$key};
5096 if (valid_drivename
($key)) {
5097 next if $skip_drive && $key eq $skip_drive;
5098 my $drive = parse_drive
($key, $value);
5099 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5100 if ($drive->{file
} =~ m!^/!) {
5101 $used_path->{$drive->{file
}}++; # = 1;
5103 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5105 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5107 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5108 $used_path->{$path}++; # = 1;
5114 &$scan_config($conf);
5118 if ($scan_snapshots) {
5119 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5120 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5127 sub update_disksize
{
5128 my ($vmid, $conf, $volid_hash) = @_;
5134 # Note: it is allowed to define multiple storages with same path (alias), so
5135 # we need to check both 'volid' and real 'path' (two different volid can point
5136 # to the same path).
5141 foreach my $opt (keys %$conf) {
5142 if (valid_drivename
($opt)) {
5143 my $drive = parse_drive
($opt, $conf->{$opt});
5144 my $volid = $drive->{file
};
5147 $used->{$volid} = 1;
5148 if ($volid_hash->{$volid} &&
5149 (my $path = $volid_hash->{$volid}->{path
})) {
5150 $usedpath->{$path} = 1;
5153 next if drive_is_cdrom
($drive);
5154 next if !$volid_hash->{$volid};
5156 $drive->{size
} = $volid_hash->{$volid}->{size
};
5157 my $new = print_drive
($vmid, $drive);
5158 if ($new ne $conf->{$opt}) {
5160 $conf->{$opt} = $new;
5165 # remove 'unusedX' entry if volume is used
5166 foreach my $opt (keys %$conf) {
5167 next if $opt !~ m/^unused\d+$/;
5168 my $volid = $conf->{$opt};
5169 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5170 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5172 delete $conf->{$opt};
5176 foreach my $volid (sort keys %$volid_hash) {
5177 next if $volid =~ m/vm-$vmid-state-/;
5178 next if $used->{$volid};
5179 my $path = $volid_hash->{$volid}->{path
};
5180 next if !$path; # just to be sure
5181 next if $usedpath->{$path};
5183 add_unused_volume
($conf, $volid);
5184 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5191 my ($vmid, $nolock) = @_;
5193 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5195 my $volid_hash = scan_volids
($cfg, $vmid);
5197 my $updatefn = sub {
5200 my $conf = load_config
($vmid);
5205 foreach my $volid (keys %$volid_hash) {
5206 my $info = $volid_hash->{$volid};
5207 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5210 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5212 update_config_nolock
($vmid, $conf, 1) if $changes;
5215 if (defined($vmid)) {
5219 lock_config
($vmid, $updatefn, $vmid);
5222 my $vmlist = config_list
();
5223 foreach my $vmid (keys %$vmlist) {
5227 lock_config
($vmid, $updatefn, $vmid);
5233 sub restore_vma_archive
{
5234 my ($archive, $vmid, $user, $opts, $comp) = @_;
5236 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5237 my $readfrom = $archive;
5242 my $qarchive = PVE
::Tools
::shellquote
($archive);
5243 if ($comp eq 'gzip') {
5244 $uncomp = "zcat $qarchive|";
5245 } elsif ($comp eq 'lzop') {
5246 $uncomp = "lzop -d -c $qarchive|";
5248 die "unknown compression method '$comp'\n";
5253 my $tmpdir = "/var/tmp/vzdumptmp$$";
5256 # disable interrupts (always do cleanups)
5257 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5258 warn "got interrupt - ignored\n";
5261 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5262 POSIX
::mkfifo
($mapfifo, 0600);
5265 my $openfifo = sub {
5266 open($fifofh, '>', $mapfifo) || die $!;
5269 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5276 my $rpcenv = PVE
::RPCEnvironment
::get
();
5278 my $conffile = config_file
($vmid);
5279 my $tmpfn = "$conffile.$$.tmp";
5281 # Note: $oldconf is undef if VM does not exists
5282 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5284 my $print_devmap = sub {
5285 my $virtdev_hash = {};
5287 my $cfgfn = "$tmpdir/qemu-server.conf";
5289 # we can read the config - that is already extracted
5290 my $fh = IO
::File-
>new($cfgfn, "r") ||
5291 "unable to read qemu-server.conf - $!\n";
5293 while (defined(my $line = <$fh>)) {
5294 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5295 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5296 die "archive does not contain data for drive '$virtdev'\n"
5297 if !$devinfo->{$devname};
5298 if (defined($opts->{storage
})) {
5299 $storeid = $opts->{storage
} || 'local';
5300 } elsif (!$storeid) {
5303 $format = 'raw' if !$format;
5304 $devinfo->{$devname}->{devname
} = $devname;
5305 $devinfo->{$devname}->{virtdev
} = $virtdev;
5306 $devinfo->{$devname}->{format
} = $format;
5307 $devinfo->{$devname}->{storeid
} = $storeid;
5309 # check permission on storage
5310 my $pool = $opts->{pool
}; # todo: do we need that?
5311 if ($user ne 'root@pam') {
5312 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5315 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5319 foreach my $devname (keys %$devinfo) {
5320 die "found no device mapping information for device '$devname'\n"
5321 if !$devinfo->{$devname}->{virtdev
};
5324 my $cfg = cfs_read_file
('storage.cfg');
5326 # create empty/temp config
5328 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5329 foreach_drive
($oldconf, sub {
5330 my ($ds, $drive) = @_;
5332 return if drive_is_cdrom
($drive);
5334 my $volid = $drive->{file
};
5336 return if !$volid || $volid =~ m
|^/|;
5338 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5339 return if !$path || !$owner || ($owner != $vmid);
5341 # Note: only delete disk we want to restore
5342 # other volumes will become unused
5343 if ($virtdev_hash->{$ds}) {
5344 PVE
::Storage
::vdisk_free
($cfg, $volid);
5350 foreach my $virtdev (sort keys %$virtdev_hash) {
5351 my $d = $virtdev_hash->{$virtdev};
5352 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5353 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5355 # test if requested format is supported
5356 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5357 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5358 $d->{format
} = $defFormat if !$supported;
5360 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5361 $d->{format
}, undef, $alloc_size);
5362 print STDERR
"new volume ID is '$volid'\n";
5363 $d->{volid
} = $volid;
5364 my $path = PVE
::Storage
::path
($cfg, $volid);
5366 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5368 my $write_zeros = 1;
5369 # fixme: what other storages types initialize volumes with zero?
5370 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5371 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5375 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5377 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5378 $map->{$virtdev} = $volid;
5381 $fh->seek(0, 0) || die "seek failed - $!\n";
5383 my $outfd = new IO
::File
($tmpfn, "w") ||
5384 die "unable to write config for VM $vmid\n";
5386 my $cookie = { netcount
=> 0 };
5387 while (defined(my $line = <$fh>)) {
5388 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5397 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5398 die "interrupted by signal\n";
5400 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5402 $oldtimeout = alarm($timeout);
5409 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5410 my ($dev_id, $size, $devname) = ($1, $2, $3);
5411 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5412 } elsif ($line =~ m/^CTIME: /) {
5413 # we correctly received the vma config, so we can disable
5414 # the timeout now for disk allocation (set to 10 minutes, so
5415 # that we always timeout if something goes wrong)
5418 print $fifofh "done\n";
5419 my $tmp = $oldtimeout || 0;
5420 $oldtimeout = undef;
5426 print "restore vma archive: $cmd\n";
5427 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5431 alarm($oldtimeout) if $oldtimeout;
5434 foreach my $devname (keys %$devinfo) {
5435 my $volid = $devinfo->{$devname}->{volid
};
5436 push @$vollist, $volid if $volid;
5439 my $cfg = cfs_read_file
('storage.cfg');
5440 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5448 foreach my $devname (keys %$devinfo) {
5449 my $volid = $devinfo->{$devname}->{volid
};
5452 if ($volid =~ m
|^/|) {
5453 unlink $volid || die 'unlink failed\n';
5455 PVE
::Storage
::vdisk_free
($cfg, $volid);
5457 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5459 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5466 rename($tmpfn, $conffile) ||
5467 die "unable to commit configuration file '$conffile'\n";
5469 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5471 eval { rescan
($vmid, 1); };
5475 sub restore_tar_archive
{
5476 my ($archive, $vmid, $user, $opts) = @_;
5478 if ($archive ne '-') {
5479 my $firstfile = tar_archive_read_firstfile
($archive);
5480 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5481 if $firstfile ne 'qemu-server.conf';
5484 my $storecfg = cfs_read_file
('storage.cfg');
5486 # destroy existing data - keep empty config
5487 my $vmcfgfn = config_file
($vmid);
5488 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5490 my $tocmd = "/usr/lib/qemu-server/qmextract";
5492 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5493 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5494 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5495 $tocmd .= ' --info' if $opts->{info
};
5497 # tar option "xf" does not autodetect compression when read from STDIN,
5498 # so we pipe to zcat
5499 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5500 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5502 my $tmpdir = "/var/tmp/vzdumptmp$$";
5505 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5506 local $ENV{VZDUMP_VMID
} = $vmid;
5507 local $ENV{VZDUMP_USER
} = $user;
5509 my $conffile = config_file
($vmid);
5510 my $tmpfn = "$conffile.$$.tmp";
5512 # disable interrupts (always do cleanups)
5513 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5514 print STDERR
"got interrupt - ignored\n";
5519 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5520 die "interrupted by signal\n";
5523 if ($archive eq '-') {
5524 print "extracting archive from STDIN\n";
5525 run_command
($cmd, input
=> "<&STDIN");
5527 print "extracting archive '$archive'\n";
5531 return if $opts->{info
};
5535 my $statfile = "$tmpdir/qmrestore.stat";
5536 if (my $fd = IO
::File-
>new($statfile, "r")) {
5537 while (defined (my $line = <$fd>)) {
5538 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5539 $map->{$1} = $2 if $1;
5541 print STDERR
"unable to parse line in statfile - $line\n";
5547 my $confsrc = "$tmpdir/qemu-server.conf";
5549 my $srcfd = new IO
::File
($confsrc, "r") ||
5550 die "unable to open file '$confsrc'\n";
5552 my $outfd = new IO
::File
($tmpfn, "w") ||
5553 die "unable to write config for VM $vmid\n";
5555 my $cookie = { netcount
=> 0 };
5556 while (defined (my $line = <$srcfd>)) {
5557 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5569 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5576 rename $tmpfn, $conffile ||
5577 die "unable to commit configuration file '$conffile'\n";
5579 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5581 eval { rescan
($vmid, 1); };
5586 # Internal snapshots
5588 # NOTE: Snapshot create/delete involves several non-atomic
5589 # action, and can take a long time.
5590 # So we try to avoid locking the file and use 'lock' variable
5591 # inside the config file instead.
5593 my $snapshot_copy_config = sub {
5594 my ($source, $dest) = @_;
5596 foreach my $k (keys %$source) {
5597 next if $k eq 'snapshots';
5598 next if $k eq 'snapstate';
5599 next if $k eq 'snaptime';
5600 next if $k eq 'vmstate';
5601 next if $k eq 'lock';
5602 next if $k eq 'digest';
5603 next if $k eq 'description';
5604 next if $k =~ m/^unused\d+$/;
5606 $dest->{$k} = $source->{$k};
5610 my $snapshot_apply_config = sub {
5611 my ($conf, $snap) = @_;
5613 # copy snapshot list
5615 snapshots
=> $conf->{snapshots
},
5618 # keep description and list of unused disks
5619 foreach my $k (keys %$conf) {
5620 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5621 $newconf->{$k} = $conf->{$k};
5624 &$snapshot_copy_config($snap, $newconf);
5629 sub foreach_writable_storage
{
5630 my ($conf, $func) = @_;
5634 foreach my $ds (keys %$conf) {
5635 next if !valid_drivename
($ds);
5637 my $drive = parse_drive
($ds, $conf->{$ds});
5639 next if drive_is_cdrom
($drive);
5641 my $volid = $drive->{file
};
5643 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5644 $sidhash->{$sid} = $sid if $sid;
5647 foreach my $sid (sort keys %$sidhash) {
5652 my $alloc_vmstate_volid = sub {
5653 my ($storecfg, $vmid, $conf, $snapname) = @_;
5655 # Note: we try to be smart when selecting a $target storage
5659 # search shared storage first
5660 foreach_writable_storage
($conf, sub {
5662 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5663 return if !$scfg->{shared
};
5665 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5669 # now search local storage
5670 foreach_writable_storage
($conf, sub {
5672 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5673 return if $scfg->{shared
};
5675 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5679 $target = 'local' if !$target;
5681 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5682 # we abort live save after $conf->{memory}, so we need at max twice that space
5683 my $size = $conf->{memory
}*2 + $driver_state_size;
5685 my $name = "vm-$vmid-state-$snapname";
5686 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5687 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5688 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5693 my $snapshot_prepare = sub {
5694 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5698 my $updatefn = sub {
5700 my $conf = load_config
($vmid);
5702 die "you can't take a snapshot if it's a template\n"
5703 if is_template
($conf);
5707 $conf->{lock} = 'snapshot';
5709 die "snapshot name '$snapname' already used\n"
5710 if defined($conf->{snapshots
}->{$snapname});
5712 my $storecfg = PVE
::Storage
::config
();
5713 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5715 $snap = $conf->{snapshots
}->{$snapname} = {};
5717 if ($save_vmstate && check_running
($vmid)) {
5718 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5721 &$snapshot_copy_config($conf, $snap);
5723 $snap->{snapstate
} = "prepare";
5724 $snap->{snaptime
} = time();
5725 $snap->{description
} = $comment if $comment;
5727 # always overwrite machine if we save vmstate. This makes sure we
5728 # can restore it later using correct machine type
5729 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5731 update_config_nolock
($vmid, $conf, 1);
5734 lock_config
($vmid, $updatefn);
5739 my $snapshot_commit = sub {
5740 my ($vmid, $snapname) = @_;
5742 my $updatefn = sub {
5744 my $conf = load_config
($vmid);
5746 die "missing snapshot lock\n"
5747 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5749 my $has_machine_config = defined($conf->{machine
});
5751 my $snap = $conf->{snapshots
}->{$snapname};
5753 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5755 die "wrong snapshot state\n"
5756 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5758 delete $snap->{snapstate
};
5759 delete $conf->{lock};
5761 my $newconf = &$snapshot_apply_config($conf, $snap);
5763 delete $newconf->{machine
} if !$has_machine_config;
5765 $newconf->{parent
} = $snapname;
5767 update_config_nolock
($vmid, $newconf, 1);
5770 lock_config
($vmid, $updatefn);
5773 sub snapshot_rollback
{
5774 my ($vmid, $snapname) = @_;
5778 my $storecfg = PVE
::Storage
::config
();
5780 my $conf = load_config
($vmid);
5782 my $get_snapshot_config = sub {
5784 die "you can't rollback if vm is a template\n" if is_template
($conf);
5786 my $res = $conf->{snapshots
}->{$snapname};
5788 die "snapshot '$snapname' does not exist\n" if !defined($res);
5793 my $snap = &$get_snapshot_config();
5795 foreach_drive
($snap, sub {
5796 my ($ds, $drive) = @_;
5798 return if drive_is_cdrom
($drive);
5800 my $volid = $drive->{file
};
5802 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5805 my $updatefn = sub {
5807 $conf = load_config
($vmid);
5809 $snap = &$get_snapshot_config();
5811 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5812 if $snap->{snapstate
};
5816 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5819 die "unable to rollback vm $vmid: vm is running\n"
5820 if check_running
($vmid);
5823 $conf->{lock} = 'rollback';
5825 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5826 delete $conf->{lock};
5832 my $has_machine_config = defined($conf->{machine
});
5834 # copy snapshot config to current config
5835 $conf = &$snapshot_apply_config($conf, $snap);
5836 $conf->{parent
} = $snapname;
5838 # Note: old code did not store 'machine', so we try to be smart
5839 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5840 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5841 # we remove the 'machine' configuration if not explicitly specified
5842 # in the original config.
5843 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5846 update_config_nolock
($vmid, $conf, 1);
5848 if (!$prepare && $snap->{vmstate
}) {
5849 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5850 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5854 lock_config
($vmid, $updatefn);
5856 foreach_drive
($snap, sub {
5857 my ($ds, $drive) = @_;
5859 return if drive_is_cdrom
($drive);
5861 my $volid = $drive->{file
};
5862 my $device = "drive-$ds";
5864 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5868 lock_config
($vmid, $updatefn);
5871 my $savevm_wait = sub {
5875 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5876 if (!$stat->{status
}) {
5877 die "savevm not active\n";
5878 } elsif ($stat->{status
} eq 'active') {
5881 } elsif ($stat->{status
} eq 'completed') {
5884 die "query-savevm returned status '$stat->{status}'\n";
5889 sub do_snapshots_with_qemu
{
5890 my ($storecfg, $volid) = @_;
5892 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5894 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5895 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5899 if ($volid =~ m/\.(qcow2|qed)$/){
5906 sub snapshot_create
{
5907 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5909 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5911 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5913 my $config = load_config
($vmid);
5915 my $running = check_running
($vmid);
5917 my $freezefs = $running && $config->{agent
};
5918 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5923 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5924 warn "guest-fsfreeze-freeze problems - $@" if $@;
5928 # create internal snapshots of all drives
5930 my $storecfg = PVE
::Storage
::config
();
5933 if ($snap->{vmstate
}) {
5934 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5935 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5936 &$savevm_wait($vmid);
5938 vm_mon_cmd
($vmid, "savevm-start");
5942 foreach_drive
($snap, sub {
5943 my ($ds, $drive) = @_;
5945 return if drive_is_cdrom
($drive);
5947 my $volid = $drive->{file
};
5948 my $device = "drive-$ds";
5950 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5951 $drivehash->{$ds} = 1;
5957 eval { vm_mon_cmd
($vmid, "savevm-end") };
5961 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5962 warn "guest-fsfreeze-thaw problems - $@" if $@;
5965 # savevm-end is async, we need to wait
5967 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5968 if (!$stat->{bytes
}) {
5971 print "savevm not yet finished\n";
5979 warn "snapshot create failed: starting cleanup\n";
5980 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5985 &$snapshot_commit($vmid, $snapname);
5988 # Note: $drivehash is only set when called from snapshot_create.
5989 sub snapshot_delete
{
5990 my ($vmid, $snapname, $force, $drivehash) = @_;
5997 my $unlink_parent = sub {
5998 my ($confref, $new_parent) = @_;
6000 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6002 $confref->{parent
} = $new_parent;
6004 delete $confref->{parent
};
6009 my $updatefn = sub {
6010 my ($remove_drive) = @_;
6012 my $conf = load_config
($vmid);
6016 die "you can't delete a snapshot if vm is a template\n"
6017 if is_template
($conf);
6020 $snap = $conf->{snapshots
}->{$snapname};
6022 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6024 # remove parent refs
6026 &$unlink_parent($conf, $snap->{parent
});
6027 foreach my $sn (keys %{$conf->{snapshots
}}) {
6028 next if $sn eq $snapname;
6029 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6033 if ($remove_drive) {
6034 if ($remove_drive eq 'vmstate') {
6035 delete $snap->{$remove_drive};
6037 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6038 my $volid = $drive->{file
};
6039 delete $snap->{$remove_drive};
6040 add_unused_volume
($conf, $volid);
6045 $snap->{snapstate
} = 'delete';
6047 delete $conf->{snapshots
}->{$snapname};
6048 delete $conf->{lock} if $drivehash;
6049 foreach my $volid (@$unused) {
6050 add_unused_volume
($conf, $volid);
6054 update_config_nolock
($vmid, $conf, 1);
6057 lock_config
($vmid, $updatefn);
6059 # now remove vmstate file
6061 my $storecfg = PVE
::Storage
::config
();
6063 if ($snap->{vmstate
}) {
6064 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6066 die $err if !$force;
6069 # save changes (remove vmstate from snapshot)
6070 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6073 # now remove all internal snapshots
6074 foreach_drive
($snap, sub {
6075 my ($ds, $drive) = @_;
6077 return if drive_is_cdrom
($drive);
6079 my $volid = $drive->{file
};
6080 my $device = "drive-$ds";
6082 if (!$drivehash || $drivehash->{$ds}) {
6083 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6085 die $err if !$force;
6090 # save changes (remove drive fron snapshot)
6091 lock_config
($vmid, $updatefn, $ds) if !$force;
6092 push @$unused, $volid;
6095 # now cleanup config
6097 lock_config
($vmid, $updatefn);
6101 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6104 foreach_drive
($conf, sub {
6105 my ($ds, $drive) = @_;
6107 return if drive_is_cdrom
($drive);
6108 my $volid = $drive->{file
};
6109 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6112 return $err ?
0 : 1;
6115 sub template_create
{
6116 my ($vmid, $conf, $disk) = @_;
6118 my $storecfg = PVE
::Storage
::config
();
6120 foreach_drive
($conf, sub {
6121 my ($ds, $drive) = @_;
6123 return if drive_is_cdrom
($drive);
6124 return if $disk && $ds ne $disk;
6126 my $volid = $drive->{file
};
6127 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6129 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6130 $drive->{file
} = $voliddst;
6131 $conf->{$ds} = print_drive
($vmid, $drive);
6132 update_config_nolock
($vmid, $conf, 1);
6139 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6142 sub qemu_img_convert
{
6143 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6145 my $storecfg = PVE
::Storage
::config
();
6146 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6147 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6149 if ($src_storeid && $dst_storeid) {
6150 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6151 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6153 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6154 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6156 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6157 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6160 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6161 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6162 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6166 if($line =~ m/\((\S+)\/100\
%\)/){
6168 my $transferred = int($size * $percent / 100);
6169 my $remaining = $size - $transferred;
6171 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6176 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6178 die "copy failed: $err" if $err;
6182 sub qemu_img_format
{
6183 my ($scfg, $volname) = @_;
6185 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6192 sub qemu_drive_mirror
{
6193 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6195 my $storecfg = PVE
::Storage
::config
();
6196 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6198 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6200 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6202 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6204 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6205 $opts->{format
} = $format if $format;
6207 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6210 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6212 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6213 my $stat = @$stats[0];
6214 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6215 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6217 my $busy = $stat->{busy
};
6218 my $ready = $stat->{ready
};
6220 if (my $total = $stat->{len
}) {
6221 my $transferred = $stat->{offset
} || 0;
6222 my $remaining = $total - $transferred;
6223 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6225 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6229 if ($stat->{ready
} eq 'true') {
6231 last if $vmiddst != $vmid;
6233 # try to switch the disk if source and destination are on the same guest
6234 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6236 die $@ if $@ !~ m/cannot be completed/;
6245 my $cancel_job = sub {
6246 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6248 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6249 my $stat = @$stats[0];
6256 eval { &$cancel_job(); };
6257 die "mirroring error: $err";
6260 if ($vmiddst != $vmid) {
6261 # if we clone a disk for a new target vm, we don't switch the disk
6262 &$cancel_job(); # so we call block-job-cancel
6267 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6268 $newvmid, $storage, $format, $full, $newvollist) = @_;
6273 print "create linked clone of drive $drivename ($drive->{file})\n";
6274 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6275 push @$newvollist, $newvolid;
6277 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6278 $storeid = $storage if $storage;
6280 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6282 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6283 $format = qemu_img_format
($scfg, $volname);
6286 # test if requested format is supported - else use default
6287 my $supported = grep { $_ eq $format } @$validFormats;
6288 $format = $defFormat if !$supported;
6290 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6292 print "create full clone of drive $drivename ($drive->{file})\n";
6293 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6294 push @$newvollist, $newvolid;
6296 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6298 if (!$running || $snapname) {
6299 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6301 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6305 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6308 $disk->{format
} = undef;
6309 $disk->{file
} = $newvolid;
6310 $disk->{size
} = $size;
6315 # this only works if VM is running
6316 sub get_current_qemu_machine
{
6319 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6320 my $res = vm_qmp_command
($vmid, $cmd);
6322 my ($current, $default);
6323 foreach my $e (@$res) {
6324 $default = $e->{name
} if $e->{'is-default'};
6325 $current = $e->{name
} if $e->{'is-current'};
6328 # fallback to the default machine if current is not supported by qemu
6329 return $current || $default || 'pc';
6332 sub qemu_machine_feature_enabled
{
6333 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6338 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6340 $current_major = $3;
6341 $current_minor = $4;
6343 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6345 $current_major = $1;
6346 $current_minor = $2;
6349 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6358 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6359 my (undef, $id, $function) = @_;
6360 my $res = { id
=> $id, function
=> $function};
6361 push @{$devices->{$id}}, $res;
6367 sub vm_iothreads_list
{
6370 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6373 foreach my $iothread (@$res) {
6374 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6381 my ($conf, $drive) = @_;
6385 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6387 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6393 my $controller = int($drive->{index} / $maxdev);
6394 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6396 return ($maxdev, $controller, $controller_prefix);
6399 # bash completion helper
6401 sub complete_backup_archives
{
6402 my ($cmdname, $pname, $cvalue) = @_;
6404 my $cfg = PVE
::Storage
::config
();
6408 if ($cvalue =~ m/^([^:]+):/) {
6412 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6415 foreach my $id (keys %$data) {
6416 foreach my $item (@{$data->{$id}}) {
6417 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6418 push @$res, $item->{volid
} if defined($item->{volid
});
6425 my $complete_vmid_full = sub {
6428 my $idlist = vmstatus
();
6432 foreach my $id (keys %$idlist) {
6433 my $d = $idlist->{$id};
6434 if (defined($running)) {
6435 next if $d->{template
};
6436 next if $running && $d->{status
} ne 'running';
6437 next if !$running && $d->{status
} eq 'running';
6446 return &$complete_vmid_full();
6449 sub complete_vmid_stopped
{
6450 return &$complete_vmid_full(0);
6453 sub complete_vmid_running
{
6454 return &$complete_vmid_full(1);
6457 sub complete_storage
{
6459 my $cfg = PVE
::Storage
::config
();
6460 my $ids = $cfg->{ids
};
6463 foreach my $sid (keys %$ids) {
6464 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);