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 [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
538 description
=> <<EODESCR,
539 Map host pci devices. HOSTPCIDEVICE syntax is:
541 'bus:dev.func' (hexadecimal numbers)
543 You can us the 'lspci' command to list existing pci devices.
545 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
547 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
549 Experimental: user reported problems with this option.
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
557 pattern
=> '(/dev/.+|socket)',
558 description
=> <<EODESCR,
559 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
561 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
563 Experimental: user reported problems with this option.
570 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
571 description
=> <<EODESCR,
572 Map host parallel devices (n is 0 to 2).
574 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
576 Experimental: user reported problems with this option.
580 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
581 $confdesc->{"parallel$i"} = $paralleldesc;
584 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
585 $confdesc->{"serial$i"} = $serialdesc;
588 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
589 $confdesc->{"hostpci$i"} = $hostpcidesc;
592 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
593 $drivename_hash->{"ide$i"} = 1;
594 $confdesc->{"ide$i"} = $idedesc;
597 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
598 $drivename_hash->{"sata$i"} = 1;
599 $confdesc->{"sata$i"} = $satadesc;
602 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
603 $drivename_hash->{"scsi$i"} = 1;
604 $confdesc->{"scsi$i"} = $scsidesc ;
607 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
608 $drivename_hash->{"virtio$i"} = 1;
609 $confdesc->{"virtio$i"} = $virtiodesc;
612 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
613 $confdesc->{"usb$i"} = $usbdesc;
618 type
=> 'string', format
=> 'pve-volume-id',
619 description
=> "Reference to unused volumes.",
622 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
623 $confdesc->{"unused$i"} = $unuseddesc;
626 my $kvm_api_version = 0;
630 return $kvm_api_version if $kvm_api_version;
632 my $fh = IO
::File-
>new("</dev/kvm") ||
635 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
636 $kvm_api_version = $v;
641 return $kvm_api_version;
644 my $kvm_user_version;
646 sub kvm_user_version
{
648 return $kvm_user_version if $kvm_user_version;
650 $kvm_user_version = 'unknown';
652 my $tmp = `kvm -help 2>/dev/null`;
654 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
655 $kvm_user_version = $2;
658 return $kvm_user_version;
662 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
665 # order is important - used to autoselect boot disk
666 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
667 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
668 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
669 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
672 sub valid_drivename
{
675 return defined($drivename_hash->{$dev});
680 return defined($confdesc->{$key});
684 return $nic_model_list;
687 sub os_list_description
{
692 w2k
=> 'Windows 2000',
693 w2k3
=>, 'Windows 2003',
694 w2k8
=> 'Windows 2008',
695 wvista
=> 'Windows Vista',
697 win8
=> 'Windows 8/2012',
707 return $cdrom_path if $cdrom_path;
709 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
710 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
711 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
715 my ($storecfg, $vmid, $cdrom) = @_;
717 if ($cdrom eq 'cdrom') {
718 return get_cdrom_path
();
719 } elsif ($cdrom eq 'none') {
721 } elsif ($cdrom =~ m
|^/|) {
724 return PVE
::Storage
::path
($storecfg, $cdrom);
728 # try to convert old style file names to volume IDs
729 sub filename_to_volume_id
{
730 my ($vmid, $file, $media) = @_;
732 if (!($file eq 'none' || $file eq 'cdrom' ||
733 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
735 return undef if $file =~ m
|/|;
737 if ($media && $media eq 'cdrom') {
738 $file = "local:iso/$file";
740 $file = "local:$vmid/$file";
747 sub verify_media_type
{
748 my ($opt, $vtype, $media) = @_;
753 if ($media eq 'disk') {
755 } elsif ($media eq 'cdrom') {
758 die "internal error";
761 return if ($vtype eq $etype);
763 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
766 sub cleanup_drive_path
{
767 my ($opt, $storecfg, $drive) = @_;
769 # try to convert filesystem paths to volume IDs
771 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
772 ($drive->{file
} !~ m
|^/dev/.+|) &&
773 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
774 ($drive->{file
} !~ m/^\d+$/)) {
775 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
776 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
777 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
778 verify_media_type
($opt, $vtype, $drive->{media
});
779 $drive->{file
} = $volid;
782 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
785 sub create_conf_nolock
{
786 my ($vmid, $settings) = @_;
788 my $filename = config_file
($vmid);
790 die "configuration file '$filename' already exists\n" if -f
$filename;
792 my $defaults = load_defaults
();
794 $settings->{name
} = "vm$vmid" if !$settings->{name
};
795 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
798 foreach my $opt (keys %$settings) {
799 next if !$confdesc->{$opt};
801 my $value = $settings->{$opt};
804 $data .= "$opt: $value\n";
807 PVE
::Tools
::file_set_contents
($filename, $data);
810 sub parse_hotplug_features
{
815 return $res if $data eq '0';
817 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
819 foreach my $feature (PVE
::Tools
::split_list
($data)) {
820 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
823 warn "ignoring unknown hotplug feature '$feature'\n";
829 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
830 sub pve_verify_hotplug_features
{
831 my ($value, $noerr) = @_;
833 return $value if parse_hotplug_features
($value);
835 return undef if $noerr;
837 die "unable to parse hotplug option\n";
840 my $parse_size = sub {
843 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
844 my ($size, $unit) = ($1, $3);
847 $size = $size * 1024;
848 } elsif ($unit eq 'M') {
849 $size = $size * 1024 * 1024;
850 } elsif ($unit eq 'G') {
851 $size = $size * 1024 * 1024 * 1024;
857 my $format_size = sub {
862 my $kb = int($size/1024);
863 return $size if $kb*1024 != $size;
865 my $mb = int($kb/1024);
866 return "${kb}K" if $mb*1024 != $kb;
868 my $gb = int($mb/1024);
869 return "${mb}M" if $gb*1024 != $mb;
874 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
875 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
876 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
877 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
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/^rombar=(on|off)$/) {
1323 $res->{rombar
} = $1;
1324 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1325 $res->{'x-vga'} = $1;
1326 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1327 $res->{pcie
} = 1 if $1 == 1;
1329 warn "unknown hostpci setting '$kv'\n";
1333 return undef if !$found;
1338 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1344 foreach my $kvp (split(/,/, $data)) {
1346 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) {
1348 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1349 $res->{model
} = $model;
1350 $res->{macaddr
} = $mac;
1351 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1352 $res->{bridge
} = $1;
1353 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1354 $res->{queues
} = $1;
1355 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1357 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1359 } elsif ($kvp =~ m/^firewall=([01])$/) {
1360 $res->{firewall
} = $1;
1361 } elsif ($kvp =~ m/^link_down=([01])$/) {
1362 $res->{link_down
} = $1;
1369 return undef if !$res->{model
};
1377 my $res = "$net->{model}";
1378 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1379 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1380 $res .= ",rate=$net->{rate}" if $net->{rate
};
1381 $res .= ",tag=$net->{tag}" if $net->{tag
};
1382 $res .= ",firewall=1" if $net->{firewall
};
1383 $res .= ",link_down=1" if $net->{link_down
};
1384 $res .= ",queues=$net->{queues}" if $net->{queues
};
1389 sub add_random_macs
{
1390 my ($settings) = @_;
1392 foreach my $opt (keys %$settings) {
1393 next if $opt !~ m/^net(\d+)$/;
1394 my $net = parse_net
($settings->{$opt});
1396 $settings->{$opt} = print_net
($net);
1400 sub add_unused_volume
{
1401 my ($config, $volid) = @_;
1404 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1405 my $test = "unused$ind";
1406 if (my $vid = $config->{$test}) {
1407 return if $vid eq $volid; # do not add duplicates
1413 die "To many unused volume - please delete them first.\n" if !$key;
1415 $config->{$key} = $volid;
1420 sub vm_is_volid_owner
{
1421 my ($storecfg, $vmid, $volid) = @_;
1423 if ($volid !~ m
|^/|) {
1425 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1426 if ($owner && ($owner == $vmid)) {
1434 sub split_flagged_list
{
1435 my $text = shift || '';
1436 $text =~ s/[,;]/ /g;
1438 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1441 sub join_flagged_list
{
1442 my ($how, $lst) = @_;
1443 join $how, map { $lst->{$_} . $_ } keys %$lst;
1446 sub vmconfig_delete_pending_option
{
1447 my ($conf, $key, $force) = @_;
1449 delete $conf->{pending
}->{$key};
1450 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1451 $pending_delete_hash->{$key} = $force ?
'!' : '';
1452 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1455 sub vmconfig_undelete_pending_option
{
1456 my ($conf, $key) = @_;
1458 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1459 delete $pending_delete_hash->{$key};
1461 if (%$pending_delete_hash) {
1462 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1464 delete $conf->{pending
}->{delete};
1468 sub vmconfig_register_unused_drive
{
1469 my ($storecfg, $vmid, $conf, $drive) = @_;
1471 if (!drive_is_cdrom
($drive)) {
1472 my $volid = $drive->{file
};
1473 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1474 add_unused_volume
($conf, $volid, $vmid);
1479 sub vmconfig_cleanup_pending
{
1482 # remove pending changes when nothing changed
1484 foreach my $opt (keys %{$conf->{pending
}}) {
1485 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1487 delete $conf->{pending
}->{$opt};
1491 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1492 my $pending_delete_hash = {};
1493 while (my ($opt, $force) = each %$current_delete_hash) {
1494 if (defined($conf->{$opt})) {
1495 $pending_delete_hash->{$opt} = $force;
1501 if (%$pending_delete_hash) {
1502 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1504 delete $conf->{pending
}->{delete};
1510 my $valid_smbios1_options = {
1511 manufacturer
=> '\S+',
1515 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1520 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1526 foreach my $kvp (split(/,/, $data)) {
1527 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1528 my ($k, $v) = split(/=/, $kvp);
1529 return undef if !defined($k) || !defined($v);
1530 return undef if !$valid_smbios1_options->{$k};
1531 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1542 foreach my $k (keys %$smbios1) {
1543 next if !defined($smbios1->{$k});
1544 next if !$valid_smbios1_options->{$k};
1545 $data .= ',' if $data;
1546 $data .= "$k=$smbios1->{$k}";
1551 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1552 sub verify_smbios1
{
1553 my ($value, $noerr) = @_;
1555 return $value if parse_smbios1
($value);
1557 return undef if $noerr;
1559 die "unable to parse smbios (type 1) options\n";
1562 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1563 sub verify_bootdisk
{
1564 my ($value, $noerr) = @_;
1566 return $value if valid_drivename
($value);
1568 return undef if $noerr;
1570 die "invalid boot disk '$value'\n";
1573 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1575 my ($value, $noerr) = @_;
1577 return $value if parse_numa
($value);
1579 return undef if $noerr;
1581 die "unable to parse numa options\n";
1584 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1586 my ($value, $noerr) = @_;
1588 return $value if parse_net
($value);
1590 return undef if $noerr;
1592 die "unable to parse network options\n";
1595 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1597 my ($value, $noerr) = @_;
1599 return $value if parse_drive
(undef, $value);
1601 return undef if $noerr;
1603 die "unable to parse drive options\n";
1606 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1607 sub verify_hostpci
{
1608 my ($value, $noerr) = @_;
1610 return $value if parse_hostpci
($value);
1612 return undef if $noerr;
1614 die "unable to parse pci id\n";
1617 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1618 sub verify_watchdog
{
1619 my ($value, $noerr) = @_;
1621 return $value if parse_watchdog
($value);
1623 return undef if $noerr;
1625 die "unable to parse watchdog options\n";
1628 sub parse_watchdog
{
1631 return undef if !$value;
1635 foreach my $p (split(/,/, $value)) {
1636 next if $p =~ m/^\s*$/;
1638 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1640 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1641 $res->{action
} = $2;
1650 sub parse_usb_device
{
1653 return undef if !$value;
1655 my @dl = split(/,/, $value);
1659 foreach my $v (@dl) {
1660 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1662 $res->{vendorid
} = $2;
1663 $res->{productid
} = $4;
1664 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1666 $res->{hostbus
} = $1;
1667 $res->{hostport
} = $2;
1668 } elsif ($v =~ m/^spice$/) {
1675 return undef if !$found;
1680 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1681 sub verify_usb_device
{
1682 my ($value, $noerr) = @_;
1684 return $value if parse_usb_device
($value);
1686 return undef if $noerr;
1688 die "unable to parse usb device\n";
1691 # add JSON properties for create and set function
1692 sub json_config_properties
{
1695 foreach my $opt (keys %$confdesc) {
1696 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1697 $prop->{$opt} = $confdesc->{$opt};
1704 my ($key, $value) = @_;
1706 die "unknown setting '$key'\n" if !$confdesc->{$key};
1708 my $type = $confdesc->{$key}->{type
};
1710 if (!defined($value)) {
1711 die "got undefined value\n";
1714 if ($value =~ m/[\n\r]/) {
1715 die "property contains a line feed\n";
1718 if ($type eq 'boolean') {
1719 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1720 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1721 die "type check ('boolean') failed - got '$value'\n";
1722 } elsif ($type eq 'integer') {
1723 return int($1) if $value =~ m/^(\d+)$/;
1724 die "type check ('integer') failed - got '$value'\n";
1725 } elsif ($type eq 'number') {
1726 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1727 die "type check ('number') failed - got '$value'\n";
1728 } elsif ($type eq 'string') {
1729 if (my $fmt = $confdesc->{$key}->{format
}) {
1730 if ($fmt eq 'pve-qm-drive') {
1731 # special case - we need to pass $key to parse_drive()
1732 my $drive = parse_drive
($key, $value);
1733 return $value if $drive;
1734 die "unable to parse drive options\n";
1736 PVE
::JSONSchema
::check_format
($fmt, $value);
1739 $value =~ s/^\"(.*)\"$/$1/;
1742 die "internal error"
1746 sub lock_config_full
{
1747 my ($vmid, $timeout, $code, @param) = @_;
1749 my $filename = config_file_lock
($vmid);
1751 my $res = lock_file
($filename, $timeout, $code, @param);
1758 sub lock_config_mode
{
1759 my ($vmid, $timeout, $shared, $code, @param) = @_;
1761 my $filename = config_file_lock
($vmid);
1763 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1771 my ($vmid, $code, @param) = @_;
1773 return lock_config_full
($vmid, 10, $code, @param);
1776 sub cfs_config_path
{
1777 my ($vmid, $node) = @_;
1779 $node = $nodename if !$node;
1780 return "nodes/$node/qemu-server/$vmid.conf";
1783 sub check_iommu_support
{
1784 #fixme : need to check IOMMU support
1785 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1793 my ($vmid, $node) = @_;
1795 my $cfspath = cfs_config_path
($vmid, $node);
1796 return "/etc/pve/$cfspath";
1799 sub config_file_lock
{
1802 return "$lock_dir/lock-$vmid.conf";
1808 my $conf = config_file
($vmid);
1809 utime undef, undef, $conf;
1813 my ($storecfg, $vmid, $keep_empty_config) = @_;
1815 my $conffile = config_file
($vmid);
1817 my $conf = load_config
($vmid);
1821 # only remove disks owned by this VM
1822 foreach_drive
($conf, sub {
1823 my ($ds, $drive) = @_;
1825 return if drive_is_cdrom
($drive);
1827 my $volid = $drive->{file
};
1829 return if !$volid || $volid =~ m
|^/|;
1831 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1832 return if !$path || !$owner || ($owner != $vmid);
1834 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1837 if ($keep_empty_config) {
1838 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1843 # also remove unused disk
1845 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1848 PVE
::Storage
::foreach_volid
($dl, sub {
1849 my ($volid, $sid, $volname, $d) = @_;
1850 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1860 my ($vmid, $node) = @_;
1862 my $cfspath = cfs_config_path
($vmid, $node);
1864 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1866 die "no such VM ('$vmid')\n" if !defined($conf);
1871 sub parse_vm_config
{
1872 my ($filename, $raw) = @_;
1874 return undef if !defined($raw);
1877 digest
=> Digest
::SHA
::sha1_hex
($raw),
1882 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1883 || die "got strange filename '$filename'";
1891 my @lines = split(/\n/, $raw);
1892 foreach my $line (@lines) {
1893 next if $line =~ m/^\s*$/;
1895 if ($line =~ m/^\[PENDING\]\s*$/i) {
1896 $section = 'pending';
1897 if (defined($descr)) {
1899 $conf->{description
} = $descr;
1902 $conf = $res->{$section} = {};
1905 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1907 if (defined($descr)) {
1909 $conf->{description
} = $descr;
1912 $conf = $res->{snapshots
}->{$section} = {};
1916 if ($line =~ m/^\#(.*)\s*$/) {
1917 $descr = '' if !defined($descr);
1918 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1922 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1923 $descr = '' if !defined($descr);
1924 $descr .= PVE
::Tools
::decode_text
($2);
1925 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1926 $conf->{snapstate
} = $1;
1927 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1930 $conf->{$key} = $value;
1931 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1933 if ($section eq 'pending') {
1934 $conf->{delete} = $value; # we parse this later
1936 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1938 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1941 eval { $value = check_type
($key, $value); };
1943 warn "vm $vmid - unable to parse value of '$key' - $@";
1945 my $fmt = $confdesc->{$key}->{format
};
1946 if ($fmt && $fmt eq 'pve-qm-drive') {
1947 my $v = parse_drive
($key, $value);
1948 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1949 $v->{file
} = $volid;
1950 $value = print_drive
($vmid, $v);
1952 warn "vm $vmid - unable to parse value of '$key'\n";
1957 if ($key eq 'cdrom') {
1958 $conf->{ide2
} = $value;
1960 $conf->{$key} = $value;
1966 if (defined($descr)) {
1968 $conf->{description
} = $descr;
1970 delete $res->{snapstate
}; # just to be sure
1975 sub write_vm_config
{
1976 my ($filename, $conf) = @_;
1978 delete $conf->{snapstate
}; # just to be sure
1980 if ($conf->{cdrom
}) {
1981 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1982 $conf->{ide2
} = $conf->{cdrom
};
1983 delete $conf->{cdrom
};
1986 # we do not use 'smp' any longer
1987 if ($conf->{sockets
}) {
1988 delete $conf->{smp
};
1989 } elsif ($conf->{smp
}) {
1990 $conf->{sockets
} = $conf->{smp
};
1991 delete $conf->{cores
};
1992 delete $conf->{smp
};
1995 my $used_volids = {};
1997 my $cleanup_config = sub {
1998 my ($cref, $pending, $snapname) = @_;
2000 foreach my $key (keys %$cref) {
2001 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2002 $key eq 'snapstate' || $key eq 'pending';
2003 my $value = $cref->{$key};
2004 if ($key eq 'delete') {
2005 die "propertry 'delete' is only allowed in [PENDING]\n"
2007 # fixme: check syntax?
2010 eval { $value = check_type
($key, $value); };
2011 die "unable to parse value of '$key' - $@" if $@;
2013 $cref->{$key} = $value;
2015 if (!$snapname && valid_drivename
($key)) {
2016 my $drive = parse_drive
($key, $value);
2017 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2022 &$cleanup_config($conf);
2024 &$cleanup_config($conf->{pending
}, 1);
2026 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2027 die "internal error" if $snapname eq 'pending';
2028 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2031 # remove 'unusedX' settings if we re-add a volume
2032 foreach my $key (keys %$conf) {
2033 my $value = $conf->{$key};
2034 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2035 delete $conf->{$key};
2039 my $generate_raw_config = sub {
2040 my ($conf, $pending) = @_;
2044 # add description as comment to top of file
2045 if (defined(my $descr = $conf->{description
})) {
2047 foreach my $cl (split(/\n/, $descr)) {
2048 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2051 $raw .= "#\n" if $pending;
2055 foreach my $key (sort keys %$conf) {
2056 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2057 $raw .= "$key: $conf->{$key}\n";
2062 my $raw = &$generate_raw_config($conf);
2064 if (scalar(keys %{$conf->{pending
}})){
2065 $raw .= "\n[PENDING]\n";
2066 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2069 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2070 $raw .= "\n[$snapname]\n";
2071 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2077 sub update_config_nolock
{
2078 my ($vmid, $conf, $skiplock) = @_;
2080 check_lock
($conf) if !$skiplock;
2082 my $cfspath = cfs_config_path
($vmid);
2084 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2088 my ($vmid, $conf, $skiplock) = @_;
2090 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2097 # we use static defaults from our JSON schema configuration
2098 foreach my $key (keys %$confdesc) {
2099 if (defined(my $default = $confdesc->{$key}->{default})) {
2100 $res->{$key} = $default;
2104 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2105 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2111 my $vmlist = PVE
::Cluster
::get_vmlist
();
2113 return $res if !$vmlist || !$vmlist->{ids
};
2114 my $ids = $vmlist->{ids
};
2116 foreach my $vmid (keys %$ids) {
2117 my $d = $ids->{$vmid};
2118 next if !$d->{node
} || $d->{node
} ne $nodename;
2119 next if !$d->{type
} || $d->{type
} ne 'qemu';
2120 $res->{$vmid}->{exists} = 1;
2125 # test if VM uses local resources (to prevent migration)
2126 sub check_local_resources
{
2127 my ($conf, $noerr) = @_;
2131 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2132 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2134 foreach my $k (keys %$conf) {
2135 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2136 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2139 die "VM uses local resources\n" if $loc_res && !$noerr;
2144 # check if used storages are available on all nodes (use by migrate)
2145 sub check_storage_availability
{
2146 my ($storecfg, $conf, $node) = @_;
2148 foreach_drive
($conf, sub {
2149 my ($ds, $drive) = @_;
2151 my $volid = $drive->{file
};
2154 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2157 # check if storage is available on both nodes
2158 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2159 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2163 # list nodes where all VM images are available (used by has_feature API)
2165 my ($conf, $storecfg) = @_;
2167 my $nodelist = PVE
::Cluster
::get_nodelist
();
2168 my $nodehash = { map { $_ => 1 } @$nodelist };
2169 my $nodename = PVE
::INotify
::nodename
();
2171 foreach_drive
($conf, sub {
2172 my ($ds, $drive) = @_;
2174 my $volid = $drive->{file
};
2177 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2179 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2180 if ($scfg->{disable
}) {
2182 } elsif (my $avail = $scfg->{nodes
}) {
2183 foreach my $node (keys %$nodehash) {
2184 delete $nodehash->{$node} if !$avail->{$node};
2186 } elsif (!$scfg->{shared
}) {
2187 foreach my $node (keys %$nodehash) {
2188 delete $nodehash->{$node} if $node ne $nodename
2200 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2204 my ($pidfile, $pid) = @_;
2206 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2210 return undef if !$line;
2211 my @param = split(/\0/, $line);
2213 my $cmd = $param[0];
2214 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2216 for (my $i = 0; $i < scalar (@param); $i++) {
2219 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2220 my $p = $param[$i+1];
2221 return 1 if $p && ($p eq $pidfile);
2230 my ($vmid, $nocheck, $node) = @_;
2232 my $filename = config_file
($vmid, $node);
2234 die "unable to find configuration file for VM $vmid - no such machine\n"
2235 if !$nocheck && ! -f
$filename;
2237 my $pidfile = pidfile_name
($vmid);
2239 if (my $fd = IO
::File-
>new("<$pidfile")) {
2244 my $mtime = $st->mtime;
2245 if ($mtime > time()) {
2246 warn "file '$filename' modified in future\n";
2249 if ($line =~ m/^(\d+)$/) {
2251 if (check_cmdline
($pidfile, $pid)) {
2252 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2264 my $vzlist = config_list
();
2266 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2268 while (defined(my $de = $fd->read)) {
2269 next if $de !~ m/^(\d+)\.pid$/;
2271 next if !defined($vzlist->{$vmid});
2272 if (my $pid = check_running
($vmid)) {
2273 $vzlist->{$vmid}->{pid
} = $pid;
2281 my ($storecfg, $conf) = @_;
2283 my $bootdisk = $conf->{bootdisk
};
2284 return undef if !$bootdisk;
2285 return undef if !valid_drivename
($bootdisk);
2287 return undef if !$conf->{$bootdisk};
2289 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2290 return undef if !defined($drive);
2292 return undef if drive_is_cdrom
($drive);
2294 my $volid = $drive->{file
};
2295 return undef if !$volid;
2297 return $drive->{size
};
2300 my $last_proc_pid_stat;
2302 # get VM status information
2303 # This must be fast and should not block ($full == false)
2304 # We only query KVM using QMP if $full == true (this can be slow)
2306 my ($opt_vmid, $full) = @_;
2310 my $storecfg = PVE
::Storage
::config
();
2312 my $list = vzlist
();
2313 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2315 my $cpucount = $cpuinfo->{cpus
} || 1;
2317 foreach my $vmid (keys %$list) {
2318 next if $opt_vmid && ($vmid ne $opt_vmid);
2320 my $cfspath = cfs_config_path
($vmid);
2321 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2324 $d->{pid
} = $list->{$vmid}->{pid
};
2326 # fixme: better status?
2327 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2329 my $size = disksize
($storecfg, $conf);
2330 if (defined($size)) {
2331 $d->{disk
} = 0; # no info available
2332 $d->{maxdisk
} = $size;
2338 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2339 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2340 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2342 $d->{name
} = $conf->{name
} || "VM $vmid";
2343 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2345 if ($conf->{balloon
}) {
2346 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2347 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2358 $d->{diskwrite
} = 0;
2360 $d->{template
} = is_template
($conf);
2365 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2366 foreach my $dev (keys %$netdev) {
2367 next if $dev !~ m/^tap([1-9]\d*)i/;
2369 my $d = $res->{$vmid};
2372 $d->{netout
} += $netdev->{$dev}->{receive
};
2373 $d->{netin
} += $netdev->{$dev}->{transmit
};
2376 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2377 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2382 my $ctime = gettimeofday
;
2384 foreach my $vmid (keys %$list) {
2386 my $d = $res->{$vmid};
2387 my $pid = $d->{pid
};
2390 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2391 next if !$pstat; # not running
2393 my $used = $pstat->{utime} + $pstat->{stime
};
2395 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2397 if ($pstat->{vsize
}) {
2398 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2401 my $old = $last_proc_pid_stat->{$pid};
2403 $last_proc_pid_stat->{$pid} = {
2411 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2413 if ($dtime > 1000) {
2414 my $dutime = $used - $old->{used
};
2416 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2417 $last_proc_pid_stat->{$pid} = {
2423 $d->{cpu
} = $old->{cpu
};
2427 return $res if !$full;
2429 my $qmpclient = PVE
::QMPClient-
>new();
2431 my $ballooncb = sub {
2432 my ($vmid, $resp) = @_;
2434 my $info = $resp->{'return'};
2435 return if !$info->{max_mem
};
2437 my $d = $res->{$vmid};
2439 # use memory assigned to VM
2440 $d->{maxmem
} = $info->{max_mem
};
2441 $d->{balloon
} = $info->{actual
};
2443 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2444 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2445 $d->{freemem
} = $info->{free_mem
};
2448 $d->{ballooninfo
} = $info;
2451 my $blockstatscb = sub {
2452 my ($vmid, $resp) = @_;
2453 my $data = $resp->{'return'} || [];
2454 my $totalrdbytes = 0;
2455 my $totalwrbytes = 0;
2457 for my $blockstat (@$data) {
2458 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2459 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2461 $blockstat->{device
} =~ s/drive-//;
2462 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2464 $res->{$vmid}->{diskread
} = $totalrdbytes;
2465 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2468 my $statuscb = sub {
2469 my ($vmid, $resp) = @_;
2471 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2472 # this fails if ballon driver is not loaded, so this must be
2473 # the last commnand (following command are aborted if this fails).
2474 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2476 my $status = 'unknown';
2477 if (!defined($status = $resp->{'return'}->{status
})) {
2478 warn "unable to get VM status\n";
2482 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2485 foreach my $vmid (keys %$list) {
2486 next if $opt_vmid && ($vmid ne $opt_vmid);
2487 next if !$res->{$vmid}->{pid
}; # not running
2488 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2491 $qmpclient->queue_execute(undef, 1);
2493 foreach my $vmid (keys %$list) {
2494 next if $opt_vmid && ($vmid ne $opt_vmid);
2495 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2502 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2505 my $current_size = 1024;
2506 my $dimm_size = 512;
2507 return if $current_size == $memory;
2509 for (my $j = 0; $j < 8; $j++) {
2510 for (my $i = 0; $i < 32; $i++) {
2511 my $name = "dimm${dimm_id}";
2513 my $numanode = $i % $sockets;
2514 $current_size += $dimm_size;
2515 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2516 return $current_size if $current_size >= $memory;
2522 sub foreach_reverse_dimm
{
2523 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2526 my $current_size = 4177920;
2527 my $dimm_size = 65536;
2528 return if $current_size == $memory;
2530 for (my $j = 0; $j < 8; $j++) {
2531 for (my $i = 0; $i < 32; $i++) {
2532 my $name = "dimm${dimm_id}";
2534 my $numanode = $i % $sockets;
2535 $current_size -= $dimm_size;
2536 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2537 return $current_size if $current_size <= $memory;
2544 my ($conf, $func) = @_;
2546 foreach my $ds (keys %$conf) {
2547 next if !valid_drivename
($ds);
2549 my $drive = parse_drive
($ds, $conf->{$ds});
2552 &$func($ds, $drive);
2557 my ($conf, $func) = @_;
2561 my $test_volid = sub {
2562 my ($volid, $is_cdrom) = @_;
2566 $volhash->{$volid} = $is_cdrom || 0;
2569 foreach_drive
($conf, sub {
2570 my ($ds, $drive) = @_;
2571 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2574 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2575 my $snap = $conf->{snapshots
}->{$snapname};
2576 &$test_volid($snap->{vmstate
}, 0);
2577 foreach_drive
($snap, sub {
2578 my ($ds, $drive) = @_;
2579 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2583 foreach my $volid (keys %$volhash) {
2584 &$func($volid, $volhash->{$volid});
2588 sub vga_conf_has_spice
{
2591 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2596 sub config_to_command
{
2597 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2600 my $globalFlags = [];
2601 my $machineFlags = [];
2607 my $kvmver = kvm_user_version
();
2608 my $vernum = 0; # unknown
2609 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2610 $vernum = $1*1000000+$2*1000;
2611 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2612 $vernum = $1*1000000+$2*1000+$3;
2615 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2617 my $have_ovz = -f
'/proc/vz/vestat';
2619 my $q35 = machine_type_is_q35
($conf);
2620 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2621 my $machine_type = $forcemachine || $conf->{machine
};
2623 my $cpuunits = defined($conf->{cpuunits
}) ?
2624 $conf->{cpuunits
} : $defaults->{cpuunits
};
2626 push @$cmd, '/usr/bin/systemd-run';
2627 push @$cmd, '--scope';
2628 push @$cmd, '--slice', "qemu";
2629 push @$cmd, '--unit', $vmid;
2630 push @$cmd, '-p', "CPUShares=$cpuunits";
2631 if ($conf->{cpulimit
}) {
2632 my $cpulimit = int($conf->{cpulimit
} * 100);
2633 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2636 push @$cmd, '/usr/bin/kvm';
2638 push @$cmd, '-id', $vmid;
2642 my $qmpsocket = qmp_socket
($vmid);
2643 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2644 push @$cmd, '-mon', "chardev=qmp,mode=control";
2646 my $socket = vnc_socket
($vmid);
2647 push @$cmd, '-vnc', "unix:$socket,x509,password";
2649 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2651 push @$cmd, '-daemonize';
2653 if ($conf->{smbios1
}) {
2654 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2658 # the q35 chipset support native usb2, so we enable usb controller
2659 # by default for this machine type
2660 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2662 $pciaddr = print_pci_addr
("piix3", $bridges);
2663 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2666 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2667 next if !$conf->{"usb$i"};
2670 # include usb device config
2671 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2674 my $vga = $conf->{vga
};
2676 my $qxlnum = vga_conf_has_spice
($vga);
2677 $vga = 'qxl' if $qxlnum;
2680 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2681 $conf->{ostype
} eq 'win7' ||
2682 $conf->{ostype
} eq 'w2k8')) {
2689 # enable absolute mouse coordinates (needed by vnc)
2691 if (defined($conf->{tablet
})) {
2692 $tablet = $conf->{tablet
};
2694 $tablet = $defaults->{tablet
};
2695 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2696 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2699 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2702 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2703 my $d = parse_hostpci
($conf->{"hostpci$i"});
2706 my $pcie = $d->{pcie
};
2708 die "q35 machine model is not enabled" if !$q35;
2709 $pciaddr = print_pcie_addr
("hostpci$i");
2711 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2714 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2715 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2716 if ($xvga && $xvga ne '') {
2717 push @$cpuFlags, 'kvm=off';
2720 my $pcidevices = $d->{pciid
};
2721 my $multifunction = 1 if @$pcidevices > 1;
2724 foreach my $pcidevice (@$pcidevices) {
2726 my $id = "hostpci$i";
2727 $id .= ".$j" if $multifunction;
2728 my $addr = $pciaddr;
2729 $addr .= ".$j" if $multifunction;
2730 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2733 $devicestr .= "$rombar$xvga";
2734 $devicestr .= ",multifunction=on" if $multifunction;
2737 push @$devices, '-device', $devicestr;
2743 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2744 my $d = parse_usb_device
($conf->{"usb$i"});
2746 if ($d->{vendorid
} && $d->{productid
}) {
2747 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2748 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2749 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2750 } elsif ($d->{spice
}) {
2751 # usb redir support for spice
2752 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2753 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2758 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2759 if (my $path = $conf->{"serial$i"}) {
2760 if ($path eq 'socket') {
2761 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2762 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2763 push @$devices, '-device', "isa-serial,chardev=serial$i";
2765 die "no such serial device\n" if ! -c
$path;
2766 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2767 push @$devices, '-device', "isa-serial,chardev=serial$i";
2773 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2774 if (my $path = $conf->{"parallel$i"}) {
2775 die "no such parallel device\n" if ! -c
$path;
2776 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2777 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2778 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2782 my $vmname = $conf->{name
} || "vm$vmid";
2784 push @$cmd, '-name', $vmname;
2787 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2788 $sockets = $conf->{sockets
} if $conf->{sockets
};
2790 my $cores = $conf->{cores
} || 1;
2792 my $maxcpus = $sockets * $cores;
2794 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2796 my $allowed_vcpus = $cpuinfo->{cpus
};
2798 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2799 if ($allowed_vcpus < $maxcpus);
2801 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2803 push @$cmd, '-nodefaults';
2805 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2807 my $bootindex_hash = {};
2809 foreach my $o (split(//, $bootorder)) {
2810 $bootindex_hash->{$o} = $i*100;
2814 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2816 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2818 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2820 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2823 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2825 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2826 my $useLocaltime = $conf->{localtime};
2828 if (my $ost = $conf->{ostype
}) {
2829 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2831 if ($ost =~ m/^w/) { # windows
2832 $useLocaltime = 1 if !defined($conf->{localtime});
2834 # use time drift fix when acpi is enabled
2835 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2836 $tdf = 1 if !defined($conf->{tdf
});
2840 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2842 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2843 push @$cmd, '-no-hpet';
2844 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2845 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2846 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2847 push @$cpuFlags , 'hv_time' if !$nokvm;
2850 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2854 if ($ost eq 'win7' || $ost eq 'win8') {
2855 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2859 push @$rtcFlags, 'driftfix=slew' if $tdf;
2862 push @$machineFlags, 'accel=tcg';
2864 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2867 if ($machine_type) {
2868 push @$machineFlags, "type=${machine_type}";
2871 if ($conf->{startdate
}) {
2872 push @$rtcFlags, "base=$conf->{startdate}";
2873 } elsif ($useLocaltime) {
2874 push @$rtcFlags, 'base=localtime';
2877 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2878 $cpu = $conf->{cpu
} if $conf->{cpu
};
2880 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2882 push @$cpuFlags , '-x2apic'
2883 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2885 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2887 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2889 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2891 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2892 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2895 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2897 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2899 push @$cmd, '-cpu', $cpu;
2901 my $memory = $conf->{memory
} || $defaults->{memory
};
2902 my $static_memory = 0;
2903 my $dimm_memory = 0;
2905 if ($hotplug_features->{memory
}) {
2906 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2907 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2908 $static_memory = $STATICMEM;
2909 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2910 $dimm_memory = $memory - $static_memory;
2911 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2915 $static_memory = $memory;
2916 push @$cmd, '-m', $static_memory;
2919 if ($conf->{numa
}) {
2921 my $numa_totalmemory = undef;
2922 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2923 next if !$conf->{"numa$i"};
2924 my $numa = parse_numa
($conf->{"numa$i"});
2927 die "missing numa node$i memory value\n" if !$numa->{memory
};
2928 my $numa_memory = $numa->{memory
};
2929 $numa_totalmemory += $numa_memory;
2930 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2933 my $cpus_start = $numa->{cpus
}->{start
};
2934 die "missing numa node$i cpus\n" if !defined($cpus_start);
2935 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2936 my $cpus = $cpus_start;
2937 if (defined($cpus_end)) {
2938 $cpus .= "-$cpus_end";
2939 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2943 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2944 if (defined($hostnodes_start)) {
2945 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2946 my $hostnodes = $hostnodes_start;
2947 if (defined($hostnodes_end)) {
2948 $hostnodes .= "-$hostnodes_end";
2949 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2952 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2953 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2954 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2958 my $policy = $numa->{policy
};
2959 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2960 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2963 push @$cmd, '-object', $numa_object;
2964 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2967 die "total memory for NUMA nodes must be equal to vm static memory\n"
2968 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2970 #if no custom tology, we split memory and cores across numa nodes
2971 if(!$numa_totalmemory) {
2973 my $numa_memory = ($static_memory / $sockets) . "M";
2975 for (my $i = 0; $i < $sockets; $i++) {
2977 my $cpustart = ($cores * $i);
2978 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2979 my $cpus = $cpustart;
2980 $cpus .= "-$cpuend" if $cpuend;
2982 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2983 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2988 if ($hotplug_features->{memory
}) {
2989 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2990 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2991 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2992 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2994 #if dimm_memory is not aligned to dimm map
2995 if($current_size > $memory) {
2996 $conf->{memory
} = $current_size;
2997 update_config_nolock
($vmid, $conf, 1);
3002 push @$cmd, '-S' if $conf->{freeze
};
3004 # set keyboard layout
3005 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3006 push @$cmd, '-k', $kb if $kb;
3009 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3010 #push @$cmd, '-soundhw', 'es1370';
3011 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3013 if($conf->{agent
}) {
3014 my $qgasocket = qmp_socket
($vmid, 1);
3015 my $pciaddr = print_pci_addr
("qga0", $bridges);
3016 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3017 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3018 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3025 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3026 for(my $i = 1; $i < $qxlnum; $i++){
3027 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3028 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3031 # assume other OS works like Linux
3032 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3033 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3037 my $pciaddr = print_pci_addr
("spice", $bridges);
3039 my $nodename = PVE
::INotify
::nodename
();
3040 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3041 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3043 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3045 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3046 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3047 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3050 # enable balloon by default, unless explicitly disabled
3051 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3052 $pciaddr = print_pci_addr
("balloon0", $bridges);
3053 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3056 if ($conf->{watchdog
}) {
3057 my $wdopts = parse_watchdog
($conf->{watchdog
});
3058 $pciaddr = print_pci_addr
("watchdog", $bridges);
3059 my $watchdog = $wdopts->{model
} || 'i6300esb';
3060 push @$devices, '-device', "$watchdog$pciaddr";
3061 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3065 my $scsicontroller = {};
3066 my $ahcicontroller = {};
3067 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3069 # Add iscsi initiator name if available
3070 if (my $initiator = get_initiator_name
()) {
3071 push @$devices, '-iscsi', "initiator-name=$initiator";
3074 foreach_drive
($conf, sub {
3075 my ($ds, $drive) = @_;
3077 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3078 push @$vollist, $drive->{file
};
3081 $use_virtio = 1 if $ds =~ m/^virtio/;
3083 if (drive_is_cdrom
($drive)) {
3084 if ($bootindex_hash->{d
}) {
3085 $drive->{bootindex
} = $bootindex_hash->{d
};
3086 $bootindex_hash->{d
} += 1;
3089 if ($bootindex_hash->{c
}) {
3090 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3091 $bootindex_hash->{c
} += 1;
3095 if($drive->{interface
} eq 'virtio'){
3096 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3099 if ($drive->{interface
} eq 'scsi') {
3101 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3103 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3104 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3107 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3108 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3109 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3113 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3114 $queues = ",num_queues=$drive->{queues}";
3117 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3118 $scsicontroller->{$controller}=1;
3121 if ($drive->{interface
} eq 'sata') {
3122 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3123 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3124 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3125 $ahcicontroller->{$controller}=1;
3128 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3129 push @$devices, '-drive',$drive_cmd;
3130 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3133 for (my $i = 0; $i < $MAX_NETS; $i++) {
3134 next if !$conf->{"net$i"};
3135 my $d = parse_net
($conf->{"net$i"});
3138 $use_virtio = 1 if $d->{model
} eq 'virtio';
3140 if ($bootindex_hash->{n
}) {
3141 $d->{bootindex
} = $bootindex_hash->{n
};
3142 $bootindex_hash->{n
} += 1;
3145 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3146 push @$devices, '-netdev', $netdevfull;
3148 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3149 push @$devices, '-device', $netdevicefull;
3154 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3159 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3161 while (my ($k, $v) = each %$bridges) {
3162 $pciaddr = print_pci_addr
("pci.$k");
3163 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3168 if ($conf->{args
}) {
3169 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3173 push @$cmd, @$devices;
3174 push @$cmd, '-rtc', join(',', @$rtcFlags)
3175 if scalar(@$rtcFlags);
3176 push @$cmd, '-machine', join(',', @$machineFlags)
3177 if scalar(@$machineFlags);
3178 push @$cmd, '-global', join(',', @$globalFlags)
3179 if scalar(@$globalFlags);
3181 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3186 return "${var_run_tmpdir}/$vmid.vnc";
3192 my $res = vm_mon_cmd
($vmid, 'query-spice');
3194 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3198 my ($vmid, $qga) = @_;
3199 my $sockettype = $qga ?
'qga' : 'qmp';
3200 return "${var_run_tmpdir}/$vmid.$sockettype";
3205 return "${var_run_tmpdir}/$vmid.pid";
3208 sub vm_devices_list
{
3211 my $res = vm_mon_cmd
($vmid, 'query-pci');
3213 foreach my $pcibus (@$res) {
3214 foreach my $device (@{$pcibus->{devices
}}) {
3215 next if !$device->{'qdev_id'};
3216 if ($device->{'pci_bridge'}) {
3217 $devices->{$device->{'qdev_id'}} = 1;
3218 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3219 next if !$bridge_device->{'qdev_id'};
3220 $devices->{$bridge_device->{'qdev_id'}} = 1;
3221 $devices->{$device->{'qdev_id'}}++;
3224 $devices->{$device->{'qdev_id'}} = 1;
3229 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3230 foreach my $block (@$resblock) {
3231 if($block->{device
} =~ m/^drive-(\S+)/){
3236 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3237 foreach my $mice (@$resmice) {
3238 if ($mice->{name
} eq 'QEMU HID Tablet') {
3239 $devices->{tablet
} = 1;
3248 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3250 my $q35 = machine_type_is_q35
($conf);
3252 my $devices_list = vm_devices_list
($vmid);
3253 return 1 if defined($devices_list->{$deviceid});
3255 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3257 if ($deviceid eq 'tablet') {
3259 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3261 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3263 qemu_iothread_add
($vmid, $deviceid, $device);
3265 qemu_driveadd
($storecfg, $vmid, $device);
3266 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3268 qemu_deviceadd
($vmid, $devicefull);
3269 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3271 eval { qemu_drivedel
($vmid, $deviceid); };
3276 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3279 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3280 my $pciaddr = print_pci_addr
($deviceid);
3281 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3283 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3285 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3286 qemu_iothread_add
($vmid, $deviceid, $device);
3287 $devicefull .= ",iothread=iothread-$deviceid";
3290 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3291 $devicefull .= ",num_queues=$device->{queues}";
3294 qemu_deviceadd
($vmid, $devicefull);
3295 qemu_deviceaddverify
($vmid, $deviceid);
3297 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3299 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3300 qemu_driveadd
($storecfg, $vmid, $device);
3302 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3303 eval { qemu_deviceadd
($vmid, $devicefull); };
3305 eval { qemu_drivedel
($vmid, $deviceid); };
3310 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3312 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3313 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3314 qemu_deviceadd
($vmid, $netdevicefull);
3315 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3317 eval { qemu_netdevdel
($vmid, $deviceid); };
3322 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3325 my $pciaddr = print_pci_addr
($deviceid);
3326 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3328 qemu_deviceadd
($vmid, $devicefull);
3329 qemu_deviceaddverify
($vmid, $deviceid);
3332 die "can't hotplug device '$deviceid'\n";
3338 # fixme: this should raise exceptions on error!
3339 sub vm_deviceunplug
{
3340 my ($vmid, $conf, $deviceid) = @_;
3342 my $devices_list = vm_devices_list
($vmid);
3343 return 1 if !defined($devices_list->{$deviceid});
3345 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3347 if ($deviceid eq 'tablet') {
3349 qemu_devicedel
($vmid, $deviceid);
3351 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3353 qemu_devicedel
($vmid, $deviceid);
3354 qemu_devicedelverify
($vmid, $deviceid);
3355 qemu_drivedel
($vmid, $deviceid);
3356 qemu_iothread_del
($conf, $vmid, $deviceid);
3358 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3360 qemu_devicedel
($vmid, $deviceid);
3361 qemu_devicedelverify
($vmid, $deviceid);
3362 qemu_iothread_del
($conf, $vmid, $deviceid);
3364 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3366 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3367 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3368 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3370 qemu_devicedel
($vmid, $deviceid);
3371 qemu_drivedel
($vmid, $deviceid);
3372 qemu_deletescsihw
($conf, $vmid, $deviceid);
3374 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3376 qemu_devicedel
($vmid, $deviceid);
3377 qemu_devicedelverify
($vmid, $deviceid);
3378 qemu_netdevdel
($vmid, $deviceid);
3381 die "can't unplug device '$deviceid'\n";
3387 sub qemu_deviceadd
{
3388 my ($vmid, $devicefull) = @_;
3390 $devicefull = "driver=".$devicefull;
3391 my %options = split(/[=,]/, $devicefull);
3393 vm_mon_cmd
($vmid, "device_add" , %options);
3396 sub qemu_devicedel
{
3397 my ($vmid, $deviceid) = @_;
3399 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3402 sub qemu_iothread_add
{
3403 my($vmid, $deviceid, $device) = @_;
3405 if ($device->{iothread
}) {
3406 my $iothreads = vm_iothreads_list
($vmid);
3407 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3411 sub qemu_iothread_del
{
3412 my($conf, $vmid, $deviceid) = @_;
3414 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3415 if ($device->{iothread
}) {
3416 my $iothreads = vm_iothreads_list
($vmid);
3417 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3421 sub qemu_objectadd
{
3422 my($vmid, $objectid, $qomtype) = @_;
3424 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3429 sub qemu_objectdel
{
3430 my($vmid, $objectid) = @_;
3432 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3438 my ($storecfg, $vmid, $device) = @_;
3440 my $drive = print_drive_full
($storecfg, $vmid, $device);
3441 $drive =~ s/\\/\\\\/g;
3442 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3444 # If the command succeeds qemu prints: "OK
"
3445 return 1 if $ret =~ m/OK/s;
3447 die "adding drive failed
: $ret\n";
3451 my($vmid, $deviceid) = @_;
3453 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3456 return 1 if $ret eq "";
3458 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3459 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3461 die "deleting drive
$deviceid failed
: $ret\n";
3464 sub qemu_deviceaddverify {
3465 my ($vmid, $deviceid) = @_;
3467 for (my $i = 0; $i <= 5; $i++) {
3468 my $devices_list = vm_devices_list($vmid);
3469 return 1 if defined($devices_list->{$deviceid});
3473 die "error on hotplug device
'$deviceid'\n";
3477 sub qemu_devicedelverify {
3478 my ($vmid, $deviceid) = @_;
3480 # need to verify that the device is correctly removed as device_del
3481 # is async and empty return is not reliable
3483 for (my $i = 0; $i <= 5; $i++) {
3484 my $devices_list = vm_devices_list($vmid);
3485 return 1 if !defined($devices_list->{$deviceid});
3489 die "error on hot-unplugging device
'$deviceid'\n";
3492 sub qemu_findorcreatescsihw {
3493 my ($storecfg, $conf, $vmid, $device) = @_;
3495 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3497 my $scsihwid="$controller_prefix$controller";
3498 my $devices_list = vm_devices_list($vmid);
3500 if(!defined($devices_list->{$scsihwid})) {
3501 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3507 sub qemu_deletescsihw {
3508 my ($conf, $vmid, $opt) = @_;
3510 my $device = parse_drive($opt, $conf->{$opt});
3512 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3513 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3517 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3519 my $devices_list = vm_devices_list($vmid);
3520 foreach my $opt (keys %{$devices_list}) {
3521 if (PVE::QemuServer::valid_drivename($opt)) {
3522 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3523 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3529 my $scsihwid="scsihw
$controller";
3531 vm_deviceunplug($vmid, $conf, $scsihwid);
3536 sub qemu_add_pci_bridge {
3537 my ($storecfg, $conf, $vmid, $device) = @_;
3543 print_pci_addr($device, $bridges);
3545 while (my ($k, $v) = each %$bridges) {
3548 return 1 if !defined($bridgeid) || $bridgeid < 1;
3550 my $bridge = "pci
.$bridgeid";
3551 my $devices_list = vm_devices_list($vmid);
3553 if (!defined($devices_list->{$bridge})) {
3554 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3560 sub qemu_set_link_status {
3561 my ($vmid, $device, $up) = @_;
3563 vm_mon_cmd($vmid, "set_link
", name => $device,
3564 up => $up ? JSON::true : JSON::false);
3567 sub qemu_netdevadd {
3568 my ($vmid, $conf, $device, $deviceid) = @_;
3570 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3571 my %options = split(/[=,]/, $netdev);
3573 vm_mon_cmd($vmid, "netdev_add
", %options);
3577 sub qemu_netdevdel {
3578 my ($vmid, $deviceid) = @_;
3580 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3583 sub qemu_cpu_hotplug {
3584 my ($vmid, $conf, $vcpus) = @_;
3587 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3588 $sockets = $conf->{sockets} if $conf->{sockets};
3589 my $cores = $conf->{cores} || 1;
3590 my $maxcpus = $sockets * $cores;
3592 $vcpus = $maxcpus if !$vcpus;
3594 die "you can
't add more vcpus than maxcpus\n"
3595 if $vcpus > $maxcpus;
3597 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3598 die "online cpu unplug is not yet possible\n"
3599 if $vcpus < $currentvcpus;
3601 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3602 die "vcpus in running vm is different than configuration\n"
3603 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3605 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3606 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3610 sub qemu_memory_hotplug {
3611 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3613 return $value if !check_running($vmid);
3615 my $memory = $conf->{memory} || $defaults->{memory};
3616 $value = $defaults->{memory} if !$value;
3617 return $value if $value == $memory;
3619 my $static_memory = $STATICMEM;
3620 my $dimm_memory = $memory - $static_memory;
3622 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3623 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3627 $sockets = $conf->{sockets} if $conf->{sockets};
3629 if($value > $memory) {
3631 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3632 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3634 return if $current_size <= $conf->{memory};
3636 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3638 eval { qemu_objectdel($vmid, "mem-
$name"); };
3642 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3644 eval { qemu_objectdel($vmid, "mem-
$name"); };
3647 #update conf after each succesful module hotplug
3648 $conf->{memory} = $current_size;
3649 update_config_nolock($vmid, $conf, 1);
3654 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3655 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3657 return if $current_size >= $conf->{memory};
3658 print "try to unplug memory dimm
$name\n";
3662 eval { qemu_devicedel($vmid, $name) };
3664 my $dimm_list = qemu_dimm_list($vmid);
3665 last if !$dimm_list->{$name};
3666 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3670 #update conf after each succesful module unplug
3671 $conf->{memory} = $current_size;
3673 eval { qemu_objectdel($vmid, "mem-
$name"); };
3674 update_config_nolock($vmid, $conf, 1);
3679 sub qemu_dimm_list {
3682 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3685 foreach my $dimm (@$dimmarray) {
3687 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3688 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3689 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3690 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3691 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3696 sub qemu_block_set_io_throttle {
3697 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3699 return if !check_running($vmid) ;
3701 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));
3705 # old code, only used to shutdown old VM after update
3707 my ($fh, $timeout) = @_;
3709 my $sel = new IO::Select;
3716 while (scalar (@ready = $sel->can_read($timeout))) {
3718 if ($count = $fh->sysread($buf, 8192)) {
3719 if ($buf =~ /^(.*)\(qemu\) $/s) {
3726 if (!defined($count)) {
3733 die "monitor
read timeout
\n" if !scalar(@ready);
3738 # old code, only used to shutdown old VM after update
3739 sub vm_monitor_command {
3740 my ($vmid, $cmdstr, $nocheck) = @_;
3745 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3747 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3749 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3750 die "unable to
connect to VM
$vmid socket - $!\n";
3754 # hack: migrate sometime blocks the monitor (when migrate_downtime
3756 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3757 $timeout = 60*60; # 1 hour
3761 my $data = __read_avail($sock, $timeout);
3763 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3764 die "got unexpected qemu monitor banner
\n";
3767 my $sel = new IO::Select;
3770 if (!scalar(my @ready = $sel->can_write($timeout))) {
3771 die "monitor
write error
- timeout
";
3774 my $fullcmd = "$cmdstr\r";
3776 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3779 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3780 die "monitor
write error
- $!";
3783 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3787 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3788 $timeout = 60*60; # 1 hour
3789 } elsif ($cmdstr =~ m/^(eject|change)/) {
3790 $timeout = 60; # note: cdrom mount command is slow
3792 if ($res = __read_avail($sock, $timeout)) {
3794 my @lines = split("\r?
\n", $res);
3796 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3798 $res = join("\n", @lines);
3806 syslog("err
", "VM
$vmid monitor command failed
- $err");
3813 sub qemu_block_resize {
3814 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3816 my $running = check_running($vmid);
3818 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3820 return if !$running;
3822 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3826 sub qemu_volume_snapshot {
3827 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3829 my $running = check_running($vmid);
3831 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3832 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3834 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3838 sub qemu_volume_snapshot_delete {
3839 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3841 my $running = check_running($vmid);
3843 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3845 return if !$running;
3847 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3850 sub set_migration_caps {
3856 "auto-converge
" => 1,
3858 "x-rdma-pin-all
" => 0,
3863 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3865 for my $supported_capability (@$supported_capabilities) {
3867 capability => $supported_capability->{capability},
3868 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3872 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3875 my $fast_plug_option = {
3884 # hotplug changes in [PENDING]
3885 # $selection hash can be used to only apply specified options, for
3886 # example: { cores => 1 } (only apply changed 'cores')
3887 # $errors ref is used to return error messages
3888 sub vmconfig_hotplug_pending {
3889 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3891 my $defaults = load_defaults();
3893 # commit values which do not have any impact on running VM first
3894 # Note: those option cannot raise errors, we we do not care about
3895 # $selection and always apply them.
3897 my $add_error = sub {
3898 my ($opt, $msg) = @_;
3899 $errors->{$opt} = "hotplug problem
- $msg";
3903 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3904 if ($fast_plug_option->{$opt}) {
3905 $conf->{$opt} = $conf->{pending}->{$opt};
3906 delete $conf->{pending}->{$opt};
3912 update_config_nolock($vmid, $conf, 1);
3913 $conf = load_config($vmid); # update/reload
3916 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3918 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3919 while (my ($opt, $force) = each %$pending_delete_hash) {
3920 next if $selection && !$selection->{$opt};
3922 if ($opt eq 'hotplug') {
3923 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3924 } elsif ($opt eq 'tablet') {
3925 die "skip
\n" if !$hotplug_features->{usb};
3926 if ($defaults->{tablet}) {
3927 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3929 vm_deviceunplug($vmid, $conf, $opt);
3931 } elsif ($opt eq 'vcpus') {
3932 die "skip
\n" if !$hotplug_features->{cpu};
3933 qemu_cpu_hotplug($vmid, $conf, undef);
3934 } elsif ($opt eq 'balloon') {
3935 # enable balloon device is not hotpluggable
3936 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3937 } elsif ($fast_plug_option->{$opt}) {
3939 } elsif ($opt =~ m/^net(\d+)$/) {
3940 die "skip
\n" if !$hotplug_features->{network};
3941 vm_deviceunplug($vmid, $conf, $opt);
3942 } elsif (valid_drivename($opt)) {
3943 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3944 vm_deviceunplug($vmid, $conf, $opt);
3945 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3946 } elsif ($opt =~ m/^memory$/) {
3947 die "skip
\n" if !$hotplug_features->{memory};
3948 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3949 } elsif ($opt eq 'cpuunits') {
3950 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3951 } elsif ($opt eq 'cpulimit') {
3952 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3958 &$add_error($opt, $err) if $err ne "skip
\n";
3960 # save new config if hotplug was successful
3961 delete $conf->{$opt};
3962 vmconfig_undelete_pending_option($conf, $opt);
3963 update_config_nolock($vmid, $conf, 1);
3964 $conf = load_config($vmid); # update/reload
3968 foreach my $opt (keys %{$conf->{pending}}) {
3969 next if $selection && !$selection->{$opt};
3970 my $value = $conf->{pending}->{$opt};
3972 if ($opt eq 'hotplug') {
3973 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3974 } elsif ($opt eq 'tablet') {
3975 die "skip
\n" if !$hotplug_features->{usb};
3977 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3978 } elsif ($value == 0) {
3979 vm_deviceunplug($vmid, $conf, $opt);
3981 } elsif ($opt eq 'vcpus') {
3982 die "skip
\n" if !$hotplug_features->{cpu};
3983 qemu_cpu_hotplug($vmid, $conf, $value);
3984 } elsif ($opt eq 'balloon') {
3985 # enable/disable balloning device is not hotpluggable
3986 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3987 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3988 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3990 # allow manual ballooning if shares is set to zero
3991 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3992 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3993 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3995 } elsif ($opt =~ m/^net(\d+)$/) {
3996 # some changes can be done without hotplug
3997 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3998 $vmid, $opt, $value);
3999 } elsif (valid_drivename($opt)) {
4000 # some changes can be done without hotplug
4001 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4002 $vmid, $opt, $value, 1);
4003 } elsif ($opt =~ m/^memory$/) { #dimms
4004 die "skip
\n" if !$hotplug_features->{memory};
4005 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4006 } elsif ($opt eq 'cpuunits') {
4007 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4008 } elsif ($opt eq 'cpulimit') {
4009 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4010 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4012 die "skip
\n"; # skip non-hot-pluggable options
4016 &$add_error($opt, $err) if $err ne "skip
\n";
4018 # save new config if hotplug was successful
4019 $conf->{$opt} = $value;
4020 delete $conf->{pending}->{$opt};
4021 update_config_nolock($vmid, $conf, 1);
4022 $conf = load_config($vmid); # update/reload
4027 sub try_deallocate_drive {
4028 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4030 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4031 my $volid = $drive->{file};
4032 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4033 my $sid = PVE::Storage::parse_volume_id($volid);
4034 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4036 # check if the disk is really unused
4037 my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
4038 my $path = PVE::Storage::path($storecfg, $volid);
4039 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4040 if $used_paths->{$path};
4041 PVE::Storage::vdisk_free($storecfg, $volid);
4044 # If vm is not owner of this disk remove from config
4052 sub vmconfig_delete_or_detach_drive {
4053 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4055 my $drive = parse_drive($opt, $conf->{$opt});
4057 my $rpcenv = PVE::RPCEnvironment::get();
4058 my $authuser = $rpcenv->get_user();
4061 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4062 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4064 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4068 sub vmconfig_apply_pending {
4069 my ($vmid, $conf, $storecfg) = @_;
4073 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4074 while (my ($opt, $force) = each %$pending_delete_hash) {
4075 die "internal error
" if $opt =~ m/^unused/;
4076 $conf = load_config($vmid); # update/reload
4077 if (!defined($conf->{$opt})) {
4078 vmconfig_undelete_pending_option($conf, $opt);
4079 update_config_nolock($vmid, $conf, 1);
4080 } elsif (valid_drivename($opt)) {
4081 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4082 vmconfig_undelete_pending_option($conf, $opt);
4083 delete $conf->{$opt};
4084 update_config_nolock($vmid, $conf, 1);
4086 vmconfig_undelete_pending_option($conf, $opt);
4087 delete $conf->{$opt};
4088 update_config_nolock($vmid, $conf, 1);
4092 $conf = load_config($vmid); # update/reload
4094 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4095 $conf = load_config($vmid); # update/reload
4097 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4098 # skip if nothing changed
4099 } elsif (valid_drivename($opt)) {
4100 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4101 if defined($conf->{$opt});
4102 $conf->{$opt} = $conf->{pending}->{$opt};
4104 $conf->{$opt} = $conf->{pending}->{$opt};
4107 delete $conf->{pending}->{$opt};
4108 update_config_nolock($vmid, $conf, 1);
4112 my $safe_num_ne = sub {
4115 return 0 if !defined($a) && !defined($b);
4116 return 1 if !defined($a);
4117 return 1 if !defined($b);
4122 my $safe_string_ne = sub {
4125 return 0 if !defined($a) && !defined($b);
4126 return 1 if !defined($a);
4127 return 1 if !defined($b);
4132 sub vmconfig_update_net {
4133 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4135 my $newnet = parse_net($value);
4137 if ($conf->{$opt}) {
4138 my $oldnet = parse_net($conf->{$opt});
4140 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4141 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4142 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4143 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4145 # for non online change, we try to hot-unplug
4146 die "skip
\n" if !$hotplug;
4147 vm_deviceunplug($vmid, $conf, $opt);
4150 die "internal error
" if $opt !~ m/net(\d+)/;
4151 my $iface = "tap
${vmid
}i
$1";
4153 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4154 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4157 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4158 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4159 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4160 PVE::Network::tap_unplug($iface);
4161 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4164 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4165 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4173 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4179 sub vmconfig_update_disk {
4180 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4182 # fixme: do we need force?
4184 my $drive = parse_drive($opt, $value);
4186 if ($conf->{$opt}) {
4188 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4190 my $media = $drive->{media} || 'disk';
4191 my $oldmedia = $old_drive->{media} || 'disk';
4192 die "unable to change media type
\n" if $media ne $oldmedia;
4194 if (!drive_is_cdrom($old_drive)) {
4196 if ($drive->{file} ne $old_drive->{file}) {
4198 die "skip
\n" if !$hotplug;
4200 # unplug and register as unused
4201 vm_deviceunplug($vmid, $conf, $opt);
4202 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4205 # update existing disk
4207 # skip non hotpluggable value
4208 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4209 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4210 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4211 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4216 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4217 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4218 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4219 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4220 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4221 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4222 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4223 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4224 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4225 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4226 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4227 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4229 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4230 ($drive->{mbps} || 0)*1024*1024,
4231 ($drive->{mbps_rd} || 0)*1024*1024,
4232 ($drive->{mbps_wr} || 0)*1024*1024,
4233 $drive->{iops} || 0,
4234 $drive->{iops_rd} || 0,
4235 $drive->{iops_wr} || 0,
4236 ($drive->{mbps_max} || 0)*1024*1024,
4237 ($drive->{mbps_rd_max} || 0)*1024*1024,
4238 ($drive->{mbps_wr_max} || 0)*1024*1024,
4239 $drive->{iops_max} || 0,
4240 $drive->{iops_rd_max} || 0,
4241 $drive->{iops_wr_max} || 0);
4250 if ($drive->{file} eq 'none') {
4251 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4253 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4254 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4255 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4263 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4265 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4269 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4271 lock_config($vmid, sub {
4272 my $conf = load_config($vmid, $migratedfrom);
4274 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4276 check_lock($conf) if !$skiplock;
4278 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4280 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4281 vmconfig_apply_pending($vmid, $conf, $storecfg);
4282 $conf = load_config($vmid); # update/reload
4285 my $defaults = load_defaults();
4287 # set environment variable useful inside network script
4288 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4290 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4292 my $migrate_port = 0;
4295 if ($statefile eq 'tcp') {
4296 my $localip = "localhost
";
4297 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4298 my $nodename = PVE::INotify::nodename();
4299 if ($datacenterconf->{migration_unsecure}) {
4300 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4302 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4303 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4304 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4305 push @$cmd, '-incoming', $migrate_uri;
4308 push @$cmd, '-loadstate', $statefile;
4315 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4316 my $d = parse_hostpci($conf->{"hostpci
$i"});
4318 my $pcidevices = $d->{pciid};
4319 foreach my $pcidevice (@$pcidevices) {
4320 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4322 my $info = pci_device_info("0000:$pciid");
4323 die "IOMMU
not present
\n" if !check_iommu_support();
4324 die "no pci device info
for device
'$pciid'\n" if !$info;
4325 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4326 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4330 PVE::Storage::activate_volumes($storecfg, $vollist);
4332 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4335 die "start failed
: $err" if $err;
4337 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4339 if ($statefile && $statefile ne 'tcp') {
4340 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4344 if ($migratedfrom) {
4347 set_migration_caps($vmid);
4352 print "spice listens on port
$spice_port\n";
4353 if ($spice_ticket) {
4354 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4355 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4361 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4362 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4363 if $conf->{balloon};
4366 foreach my $opt (keys %$conf) {
4367 next if $opt !~ m/^net\d+$/;
4368 my $nicconf = parse_net($conf->{$opt});
4369 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4373 vm_mon_cmd_nocheck($vmid, 'qom-set',
4374 path => "machine
/peripheral/balloon0
",
4375 property => "guest-stats-polling-interval
",
4376 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4382 my ($vmid, $execute, %params) = @_;
4384 my $cmd = { execute => $execute, arguments => \%params };
4385 vm_qmp_command($vmid, $cmd);
4388 sub vm_mon_cmd_nocheck {
4389 my ($vmid, $execute, %params) = @_;
4391 my $cmd = { execute => $execute, arguments => \%params };
4392 vm_qmp_command($vmid, $cmd, 1);
4395 sub vm_qmp_command {
4396 my ($vmid, $cmd, $nocheck) = @_;
4401 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4402 $timeout = $cmd->{arguments}->{timeout};
4403 delete $cmd->{arguments}->{timeout};
4407 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4408 my $sname = qmp_socket($vmid);
4409 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4410 my $qmpclient = PVE::QMPClient->new();
4412 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4413 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4414 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4415 if scalar(%{$cmd->{arguments}});
4416 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4418 die "unable to open monitor socket\n";
4422 syslog("err", "VM $vmid qmp command failed - $err");
4429 sub vm_human_monitor_command {
4430 my ($vmid, $cmdline) = @_;
4435 execute => 'human-monitor-command
',
4436 arguments => { 'command-line
' => $cmdline},
4439 return vm_qmp_command($vmid, $cmd);
4442 sub vm_commandline {
4443 my ($storecfg, $vmid) = @_;
4445 my $conf = load_config($vmid);
4447 my $defaults = load_defaults();
4449 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4451 return join(' ', @$cmd);
4455 my ($vmid, $skiplock) = @_;
4457 lock_config($vmid, sub {
4459 my $conf = load_config($vmid);
4461 check_lock($conf) if !$skiplock;
4463 vm_mon_cmd($vmid, "system_reset");
4467 sub get_vm_volumes {
4471 foreach_volid($conf, sub {
4472 my ($volid, $is_cdrom) = @_;
4474 return if $volid =~ m|^/|;
4476 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4479 push @$vollist, $volid;
4485 sub vm_stop_cleanup {
4486 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4491 my $vollist = get_vm_volumes($conf);
4492 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4495 foreach my $ext (qw(mon qmp pid vnc qga)) {
4496 unlink "/var/run/qemu-server/${vmid}.$ext";
4499 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4501 warn $@ if $@; # avoid errors - just warn
4504 # Note: use $nockeck to skip tests if VM configuration file exists.
4505 # We need that when migration VMs to other nodes (files already moved)
4506 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4508 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4510 $force = 1 if !defined($force) && !$shutdown;
4513 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4514 kill 15, $pid if $pid;
4515 my $conf = load_config
($vmid, $migratedfrom);
4516 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4520 lock_config
($vmid, sub {
4522 my $pid = check_running
($vmid, $nocheck);
4527 $conf = load_config
($vmid);
4528 check_lock
($conf) if !$skiplock;
4529 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4530 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4531 $timeout = $opts->{down
} if $opts->{down
};
4535 $timeout = 60 if !defined($timeout);
4539 if (defined($conf) && $conf->{agent
}) {
4540 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4542 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4545 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4552 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4557 if ($count >= $timeout) {
4559 warn "VM still running - terminating now with SIGTERM\n";
4562 die "VM quit/powerdown failed - got timeout\n";
4565 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4570 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4573 die "VM quit/powerdown failed\n";
4581 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4586 if ($count >= $timeout) {
4587 warn "VM still running - terminating now with SIGKILL\n";
4592 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4597 my ($vmid, $skiplock) = @_;
4599 lock_config
($vmid, sub {
4601 my $conf = load_config
($vmid);
4603 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4605 vm_mon_cmd
($vmid, "stop");
4610 my ($vmid, $skiplock) = @_;
4612 lock_config
($vmid, sub {
4614 my $conf = load_config
($vmid);
4616 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4618 vm_mon_cmd
($vmid, "cont");
4623 my ($vmid, $skiplock, $key) = @_;
4625 lock_config
($vmid, sub {
4627 my $conf = load_config
($vmid);
4629 # there is no qmp command, so we use the human monitor command
4630 vm_human_monitor_command
($vmid, "sendkey $key");
4635 my ($storecfg, $vmid, $skiplock) = @_;
4637 lock_config
($vmid, sub {
4639 my $conf = load_config
($vmid);
4641 check_lock
($conf) if !$skiplock;
4643 if (!check_running
($vmid)) {
4644 destroy_vm
($storecfg, $vmid);
4646 die "VM $vmid is running - destroy failed\n";
4654 my ($filename, $buf) = @_;
4656 my $fh = IO
::File-
>new($filename, "w");
4657 return undef if !$fh;
4659 my $res = print $fh $buf;
4666 sub pci_device_info
{
4671 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4672 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4674 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4675 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4677 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4678 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4680 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4681 return undef if !defined($product) || $product !~ s/^0x//;
4686 product
=> $product,
4692 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4701 my $name = $dev->{name
};
4703 my $fn = "$pcisysfs/devices/$name/reset";
4705 return file_write
($fn, "1");
4708 sub pci_dev_bind_to_vfio
{
4711 my $name = $dev->{name
};
4713 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4715 if (!-d
$vfio_basedir) {
4716 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4718 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4720 my $testdir = "$vfio_basedir/$name";
4721 return 1 if -d
$testdir;
4723 my $data = "$dev->{vendor} $dev->{product}";
4724 return undef if !file_write
("$vfio_basedir/new_id", $data);
4726 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4727 if (!file_write
($fn, $name)) {
4728 return undef if -f
$fn;
4731 $fn = "$vfio_basedir/bind";
4732 if (! -d
$testdir) {
4733 return undef if !file_write
($fn, $name);
4739 sub pci_dev_group_bind_to_vfio
{
4742 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4744 if (!-d
$vfio_basedir) {
4745 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4747 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4749 # get IOMMU group devices
4750 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4751 my @devs = grep /^0000:/, readdir($D);
4754 foreach my $pciid (@devs) {
4755 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4757 # pci bridges, switches or root ports are not supported
4758 # they have a pci_bus subdirectory so skip them
4759 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4761 my $info = pci_device_info
($1);
4762 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4768 sub print_pci_addr
{
4769 my ($id, $bridges) = @_;
4773 piix3
=> { bus
=> 0, addr
=> 1 },
4774 #addr2 : first videocard
4775 balloon0
=> { bus
=> 0, addr
=> 3 },
4776 watchdog
=> { bus
=> 0, addr
=> 4 },
4777 scsihw0
=> { bus
=> 0, addr
=> 5 },
4778 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4779 scsihw1
=> { bus
=> 0, addr
=> 6 },
4780 ahci0
=> { bus
=> 0, addr
=> 7 },
4781 qga0
=> { bus
=> 0, addr
=> 8 },
4782 spice
=> { bus
=> 0, addr
=> 9 },
4783 virtio0
=> { bus
=> 0, addr
=> 10 },
4784 virtio1
=> { bus
=> 0, addr
=> 11 },
4785 virtio2
=> { bus
=> 0, addr
=> 12 },
4786 virtio3
=> { bus
=> 0, addr
=> 13 },
4787 virtio4
=> { bus
=> 0, addr
=> 14 },
4788 virtio5
=> { bus
=> 0, addr
=> 15 },
4789 hostpci0
=> { bus
=> 0, addr
=> 16 },
4790 hostpci1
=> { bus
=> 0, addr
=> 17 },
4791 net0
=> { bus
=> 0, addr
=> 18 },
4792 net1
=> { bus
=> 0, addr
=> 19 },
4793 net2
=> { bus
=> 0, addr
=> 20 },
4794 net3
=> { bus
=> 0, addr
=> 21 },
4795 net4
=> { bus
=> 0, addr
=> 22 },
4796 net5
=> { bus
=> 0, addr
=> 23 },
4797 vga1
=> { bus
=> 0, addr
=> 24 },
4798 vga2
=> { bus
=> 0, addr
=> 25 },
4799 vga3
=> { bus
=> 0, addr
=> 26 },
4800 hostpci2
=> { bus
=> 0, addr
=> 27 },
4801 hostpci3
=> { bus
=> 0, addr
=> 28 },
4802 #addr29 : usb-host (pve-usb.cfg)
4803 'pci.1' => { bus
=> 0, addr
=> 30 },
4804 'pci.2' => { bus
=> 0, addr
=> 31 },
4805 'net6' => { bus
=> 1, addr
=> 1 },
4806 'net7' => { bus
=> 1, addr
=> 2 },
4807 'net8' => { bus
=> 1, addr
=> 3 },
4808 'net9' => { bus
=> 1, addr
=> 4 },
4809 'net10' => { bus
=> 1, addr
=> 5 },
4810 'net11' => { bus
=> 1, addr
=> 6 },
4811 'net12' => { bus
=> 1, addr
=> 7 },
4812 'net13' => { bus
=> 1, addr
=> 8 },
4813 'net14' => { bus
=> 1, addr
=> 9 },
4814 'net15' => { bus
=> 1, addr
=> 10 },
4815 'net16' => { bus
=> 1, addr
=> 11 },
4816 'net17' => { bus
=> 1, addr
=> 12 },
4817 'net18' => { bus
=> 1, addr
=> 13 },
4818 'net19' => { bus
=> 1, addr
=> 14 },
4819 'net20' => { bus
=> 1, addr
=> 15 },
4820 'net21' => { bus
=> 1, addr
=> 16 },
4821 'net22' => { bus
=> 1, addr
=> 17 },
4822 'net23' => { bus
=> 1, addr
=> 18 },
4823 'net24' => { bus
=> 1, addr
=> 19 },
4824 'net25' => { bus
=> 1, addr
=> 20 },
4825 'net26' => { bus
=> 1, addr
=> 21 },
4826 'net27' => { bus
=> 1, addr
=> 22 },
4827 'net28' => { bus
=> 1, addr
=> 23 },
4828 'net29' => { bus
=> 1, addr
=> 24 },
4829 'net30' => { bus
=> 1, addr
=> 25 },
4830 'net31' => { bus
=> 1, addr
=> 26 },
4831 'virtio6' => { bus
=> 2, addr
=> 1 },
4832 'virtio7' => { bus
=> 2, addr
=> 2 },
4833 'virtio8' => { bus
=> 2, addr
=> 3 },
4834 'virtio9' => { bus
=> 2, addr
=> 4 },
4835 'virtio10' => { bus
=> 2, addr
=> 5 },
4836 'virtio11' => { bus
=> 2, addr
=> 6 },
4837 'virtio12' => { bus
=> 2, addr
=> 7 },
4838 'virtio13' => { bus
=> 2, addr
=> 8 },
4839 'virtio14' => { bus
=> 2, addr
=> 9 },
4840 'virtio15' => { bus
=> 2, addr
=> 10 },
4841 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4842 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4843 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4844 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4845 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4846 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4847 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4848 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4849 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4850 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4851 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4852 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4853 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4854 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4855 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4856 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4857 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4858 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4859 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4860 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4861 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4862 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4863 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4864 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4865 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4866 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4867 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4868 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4869 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4870 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4871 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4875 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4876 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4877 my $bus = $devices->{$id}->{bus
};
4878 $res = ",bus=pci.$bus,addr=$addr";
4879 $bridges->{$bus} = 1 if $bridges;
4885 sub print_pcie_addr
{
4890 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4891 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4892 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4893 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4896 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4897 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4898 my $bus = $devices->{$id}->{bus
};
4899 $res = ",bus=$bus,addr=$addr";
4905 # vzdump restore implementaion
4907 sub tar_archive_read_firstfile
{
4908 my $archive = shift;
4910 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4912 # try to detect archive type first
4913 my $pid = open (TMP
, "tar tf '$archive'|") ||
4914 die "unable to open file '$archive'\n";
4915 my $firstfile = <TMP
>;
4919 die "ERROR: archive contaions no data\n" if !$firstfile;
4925 sub tar_restore_cleanup
{
4926 my ($storecfg, $statfile) = @_;
4928 print STDERR
"starting cleanup\n";
4930 if (my $fd = IO
::File-
>new($statfile, "r")) {
4931 while (defined(my $line = <$fd>)) {
4932 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4935 if ($volid =~ m
|^/|) {
4936 unlink $volid || die 'unlink failed\n';
4938 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4940 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4942 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4944 print STDERR
"unable to parse line in statfile - $line";
4951 sub restore_archive
{
4952 my ($archive, $vmid, $user, $opts) = @_;
4954 my $format = $opts->{format
};
4957 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4958 $format = 'tar' if !$format;
4960 } elsif ($archive =~ m/\.tar$/) {
4961 $format = 'tar' if !$format;
4962 } elsif ($archive =~ m/.tar.lzo$/) {
4963 $format = 'tar' if !$format;
4965 } elsif ($archive =~ m/\.vma$/) {
4966 $format = 'vma' if !$format;
4967 } elsif ($archive =~ m/\.vma\.gz$/) {
4968 $format = 'vma' if !$format;
4970 } elsif ($archive =~ m/\.vma\.lzo$/) {
4971 $format = 'vma' if !$format;
4974 $format = 'vma' if !$format; # default
4977 # try to detect archive format
4978 if ($format eq 'tar') {
4979 return restore_tar_archive
($archive, $vmid, $user, $opts);
4981 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4985 sub restore_update_config_line
{
4986 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4988 return if $line =~ m/^\#qmdump\#/;
4989 return if $line =~ m/^\#vzdump\#/;
4990 return if $line =~ m/^lock:/;
4991 return if $line =~ m/^unused\d+:/;
4992 return if $line =~ m/^parent:/;
4993 return if $line =~ m/^template:/; # restored VM is never a template
4995 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4996 # try to convert old 1.X settings
4997 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4998 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4999 my ($model, $macaddr) = split(/\=/, $devconfig);
5000 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5003 bridge
=> "vmbr$ind",
5004 macaddr
=> $macaddr,
5006 my $netstr = print_net
($net);
5008 print $outfd "net$cookie->{netcount}: $netstr\n";
5009 $cookie->{netcount
}++;
5011 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5012 my ($id, $netstr) = ($1, $2);
5013 my $net = parse_net
($netstr);
5014 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5015 $netstr = print_net
($net);
5016 print $outfd "$id: $netstr\n";
5017 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5020 if ($line =~ m/backup=no/) {
5021 print $outfd "#$line";
5022 } elsif ($virtdev && $map->{$virtdev}) {
5023 my $di = parse_drive
($virtdev, $value);
5024 delete $di->{format
}; # format can change on restore
5025 $di->{file
} = $map->{$virtdev};
5026 $value = print_drive
($vmid, $di);
5027 print $outfd "$virtdev: $value\n";
5037 my ($cfg, $vmid) = @_;
5039 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5041 my $volid_hash = {};
5042 foreach my $storeid (keys %$info) {
5043 foreach my $item (@{$info->{$storeid}}) {
5044 next if !($item->{volid
} && $item->{size
});
5045 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5046 $volid_hash->{$item->{volid
}} = $item;
5053 sub get_used_paths
{
5054 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5058 my $scan_config = sub {
5059 my ($cref, $snapname) = @_;
5061 foreach my $key (keys %$cref) {
5062 my $value = $cref->{$key};
5063 if (valid_drivename
($key)) {
5064 next if $skip_drive && $key eq $skip_drive;
5065 my $drive = parse_drive
($key, $value);
5066 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5067 if ($drive->{file
} =~ m!^/!) {
5068 $used_path->{$drive->{file
}}++; # = 1;
5070 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5072 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5074 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5075 $used_path->{$path}++; # = 1;
5081 &$scan_config($conf);
5085 if ($scan_snapshots) {
5086 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5087 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5094 sub update_disksize
{
5095 my ($vmid, $conf, $volid_hash) = @_;
5101 # Note: it is allowed to define multiple storages with same path (alias), so
5102 # we need to check both 'volid' and real 'path' (two different volid can point
5103 # to the same path).
5108 foreach my $opt (keys %$conf) {
5109 if (valid_drivename
($opt)) {
5110 my $drive = parse_drive
($opt, $conf->{$opt});
5111 my $volid = $drive->{file
};
5114 $used->{$volid} = 1;
5115 if ($volid_hash->{$volid} &&
5116 (my $path = $volid_hash->{$volid}->{path
})) {
5117 $usedpath->{$path} = 1;
5120 next if drive_is_cdrom
($drive);
5121 next if !$volid_hash->{$volid};
5123 $drive->{size
} = $volid_hash->{$volid}->{size
};
5124 my $new = print_drive
($vmid, $drive);
5125 if ($new ne $conf->{$opt}) {
5127 $conf->{$opt} = $new;
5132 # remove 'unusedX' entry if volume is used
5133 foreach my $opt (keys %$conf) {
5134 next if $opt !~ m/^unused\d+$/;
5135 my $volid = $conf->{$opt};
5136 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5137 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5139 delete $conf->{$opt};
5143 foreach my $volid (sort keys %$volid_hash) {
5144 next if $volid =~ m/vm-$vmid-state-/;
5145 next if $used->{$volid};
5146 my $path = $volid_hash->{$volid}->{path
};
5147 next if !$path; # just to be sure
5148 next if $usedpath->{$path};
5150 add_unused_volume
($conf, $volid);
5151 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5158 my ($vmid, $nolock) = @_;
5160 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5162 my $volid_hash = scan_volids
($cfg, $vmid);
5164 my $updatefn = sub {
5167 my $conf = load_config
($vmid);
5172 foreach my $volid (keys %$volid_hash) {
5173 my $info = $volid_hash->{$volid};
5174 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5177 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5179 update_config_nolock
($vmid, $conf, 1) if $changes;
5182 if (defined($vmid)) {
5186 lock_config
($vmid, $updatefn, $vmid);
5189 my $vmlist = config_list
();
5190 foreach my $vmid (keys %$vmlist) {
5194 lock_config
($vmid, $updatefn, $vmid);
5200 sub restore_vma_archive
{
5201 my ($archive, $vmid, $user, $opts, $comp) = @_;
5203 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5204 my $readfrom = $archive;
5209 my $qarchive = PVE
::Tools
::shellquote
($archive);
5210 if ($comp eq 'gzip') {
5211 $uncomp = "zcat $qarchive|";
5212 } elsif ($comp eq 'lzop') {
5213 $uncomp = "lzop -d -c $qarchive|";
5215 die "unknown compression method '$comp'\n";
5220 my $tmpdir = "/var/tmp/vzdumptmp$$";
5223 # disable interrupts (always do cleanups)
5224 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5225 warn "got interrupt - ignored\n";
5228 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5229 POSIX
::mkfifo
($mapfifo, 0600);
5232 my $openfifo = sub {
5233 open($fifofh, '>', $mapfifo) || die $!;
5236 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5243 my $rpcenv = PVE
::RPCEnvironment
::get
();
5245 my $conffile = config_file
($vmid);
5246 my $tmpfn = "$conffile.$$.tmp";
5248 # Note: $oldconf is undef if VM does not exists
5249 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5251 my $print_devmap = sub {
5252 my $virtdev_hash = {};
5254 my $cfgfn = "$tmpdir/qemu-server.conf";
5256 # we can read the config - that is already extracted
5257 my $fh = IO
::File-
>new($cfgfn, "r") ||
5258 "unable to read qemu-server.conf - $!\n";
5260 while (defined(my $line = <$fh>)) {
5261 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5262 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5263 die "archive does not contain data for drive '$virtdev'\n"
5264 if !$devinfo->{$devname};
5265 if (defined($opts->{storage
})) {
5266 $storeid = $opts->{storage
} || 'local';
5267 } elsif (!$storeid) {
5270 $format = 'raw' if !$format;
5271 $devinfo->{$devname}->{devname
} = $devname;
5272 $devinfo->{$devname}->{virtdev
} = $virtdev;
5273 $devinfo->{$devname}->{format
} = $format;
5274 $devinfo->{$devname}->{storeid
} = $storeid;
5276 # check permission on storage
5277 my $pool = $opts->{pool
}; # todo: do we need that?
5278 if ($user ne 'root@pam') {
5279 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5282 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5286 foreach my $devname (keys %$devinfo) {
5287 die "found no device mapping information for device '$devname'\n"
5288 if !$devinfo->{$devname}->{virtdev
};
5291 my $cfg = cfs_read_file
('storage.cfg');
5293 # create empty/temp config
5295 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5296 foreach_drive
($oldconf, sub {
5297 my ($ds, $drive) = @_;
5299 return if drive_is_cdrom
($drive);
5301 my $volid = $drive->{file
};
5303 return if !$volid || $volid =~ m
|^/|;
5305 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5306 return if !$path || !$owner || ($owner != $vmid);
5308 # Note: only delete disk we want to restore
5309 # other volumes will become unused
5310 if ($virtdev_hash->{$ds}) {
5311 PVE
::Storage
::vdisk_free
($cfg, $volid);
5317 foreach my $virtdev (sort keys %$virtdev_hash) {
5318 my $d = $virtdev_hash->{$virtdev};
5319 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5320 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5322 # test if requested format is supported
5323 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5324 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5325 $d->{format
} = $defFormat if !$supported;
5327 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5328 $d->{format
}, undef, $alloc_size);
5329 print STDERR
"new volume ID is '$volid'\n";
5330 $d->{volid
} = $volid;
5331 my $path = PVE
::Storage
::path
($cfg, $volid);
5333 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5335 my $write_zeros = 1;
5336 # fixme: what other storages types initialize volumes with zero?
5337 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5338 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5342 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5344 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5345 $map->{$virtdev} = $volid;
5348 $fh->seek(0, 0) || die "seek failed - $!\n";
5350 my $outfd = new IO
::File
($tmpfn, "w") ||
5351 die "unable to write config for VM $vmid\n";
5353 my $cookie = { netcount
=> 0 };
5354 while (defined(my $line = <$fh>)) {
5355 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5364 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5365 die "interrupted by signal\n";
5367 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5369 $oldtimeout = alarm($timeout);
5376 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5377 my ($dev_id, $size, $devname) = ($1, $2, $3);
5378 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5379 } elsif ($line =~ m/^CTIME: /) {
5380 # we correctly received the vma config, so we can disable
5381 # the timeout now for disk allocation (set to 10 minutes, so
5382 # that we always timeout if something goes wrong)
5385 print $fifofh "done\n";
5386 my $tmp = $oldtimeout || 0;
5387 $oldtimeout = undef;
5393 print "restore vma archive: $cmd\n";
5394 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5398 alarm($oldtimeout) if $oldtimeout;
5401 foreach my $devname (keys %$devinfo) {
5402 my $volid = $devinfo->{$devname}->{volid
};
5403 push @$vollist, $volid if $volid;
5406 my $cfg = cfs_read_file
('storage.cfg');
5407 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5415 foreach my $devname (keys %$devinfo) {
5416 my $volid = $devinfo->{$devname}->{volid
};
5419 if ($volid =~ m
|^/|) {
5420 unlink $volid || die 'unlink failed\n';
5422 PVE
::Storage
::vdisk_free
($cfg, $volid);
5424 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5426 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5433 rename($tmpfn, $conffile) ||
5434 die "unable to commit configuration file '$conffile'\n";
5436 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5438 eval { rescan
($vmid, 1); };
5442 sub restore_tar_archive
{
5443 my ($archive, $vmid, $user, $opts) = @_;
5445 if ($archive ne '-') {
5446 my $firstfile = tar_archive_read_firstfile
($archive);
5447 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5448 if $firstfile ne 'qemu-server.conf';
5451 my $storecfg = cfs_read_file
('storage.cfg');
5453 # destroy existing data - keep empty config
5454 my $vmcfgfn = config_file
($vmid);
5455 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5457 my $tocmd = "/usr/lib/qemu-server/qmextract";
5459 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5460 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5461 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5462 $tocmd .= ' --info' if $opts->{info
};
5464 # tar option "xf" does not autodetect compression when read from STDIN,
5465 # so we pipe to zcat
5466 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5467 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5469 my $tmpdir = "/var/tmp/vzdumptmp$$";
5472 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5473 local $ENV{VZDUMP_VMID
} = $vmid;
5474 local $ENV{VZDUMP_USER
} = $user;
5476 my $conffile = config_file
($vmid);
5477 my $tmpfn = "$conffile.$$.tmp";
5479 # disable interrupts (always do cleanups)
5480 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5481 print STDERR
"got interrupt - ignored\n";
5486 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5487 die "interrupted by signal\n";
5490 if ($archive eq '-') {
5491 print "extracting archive from STDIN\n";
5492 run_command
($cmd, input
=> "<&STDIN");
5494 print "extracting archive '$archive'\n";
5498 return if $opts->{info
};
5502 my $statfile = "$tmpdir/qmrestore.stat";
5503 if (my $fd = IO
::File-
>new($statfile, "r")) {
5504 while (defined (my $line = <$fd>)) {
5505 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5506 $map->{$1} = $2 if $1;
5508 print STDERR
"unable to parse line in statfile - $line\n";
5514 my $confsrc = "$tmpdir/qemu-server.conf";
5516 my $srcfd = new IO
::File
($confsrc, "r") ||
5517 die "unable to open file '$confsrc'\n";
5519 my $outfd = new IO
::File
($tmpfn, "w") ||
5520 die "unable to write config for VM $vmid\n";
5522 my $cookie = { netcount
=> 0 };
5523 while (defined (my $line = <$srcfd>)) {
5524 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5536 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5543 rename $tmpfn, $conffile ||
5544 die "unable to commit configuration file '$conffile'\n";
5546 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5548 eval { rescan
($vmid, 1); };
5553 # Internal snapshots
5555 # NOTE: Snapshot create/delete involves several non-atomic
5556 # action, and can take a long time.
5557 # So we try to avoid locking the file and use 'lock' variable
5558 # inside the config file instead.
5560 my $snapshot_copy_config = sub {
5561 my ($source, $dest) = @_;
5563 foreach my $k (keys %$source) {
5564 next if $k eq 'snapshots';
5565 next if $k eq 'snapstate';
5566 next if $k eq 'snaptime';
5567 next if $k eq 'vmstate';
5568 next if $k eq 'lock';
5569 next if $k eq 'digest';
5570 next if $k eq 'description';
5571 next if $k =~ m/^unused\d+$/;
5573 $dest->{$k} = $source->{$k};
5577 my $snapshot_apply_config = sub {
5578 my ($conf, $snap) = @_;
5580 # copy snapshot list
5582 snapshots
=> $conf->{snapshots
},
5585 # keep description and list of unused disks
5586 foreach my $k (keys %$conf) {
5587 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5588 $newconf->{$k} = $conf->{$k};
5591 &$snapshot_copy_config($snap, $newconf);
5596 sub foreach_writable_storage
{
5597 my ($conf, $func) = @_;
5601 foreach my $ds (keys %$conf) {
5602 next if !valid_drivename
($ds);
5604 my $drive = parse_drive
($ds, $conf->{$ds});
5606 next if drive_is_cdrom
($drive);
5608 my $volid = $drive->{file
};
5610 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5611 $sidhash->{$sid} = $sid if $sid;
5614 foreach my $sid (sort keys %$sidhash) {
5619 my $alloc_vmstate_volid = sub {
5620 my ($storecfg, $vmid, $conf, $snapname) = @_;
5622 # Note: we try to be smart when selecting a $target storage
5626 # search shared storage first
5627 foreach_writable_storage
($conf, sub {
5629 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5630 return if !$scfg->{shared
};
5632 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5636 # now search local storage
5637 foreach_writable_storage
($conf, sub {
5639 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5640 return if $scfg->{shared
};
5642 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5646 $target = 'local' if !$target;
5648 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5649 # we abort live save after $conf->{memory}, so we need at max twice that space
5650 my $size = $conf->{memory
}*2 + $driver_state_size;
5652 my $name = "vm-$vmid-state-$snapname";
5653 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5654 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5655 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5660 my $snapshot_prepare = sub {
5661 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5665 my $updatefn = sub {
5667 my $conf = load_config
($vmid);
5669 die "you can't take a snapshot if it's a template\n"
5670 if is_template
($conf);
5674 $conf->{lock} = 'snapshot';
5676 die "snapshot name '$snapname' already used\n"
5677 if defined($conf->{snapshots
}->{$snapname});
5679 my $storecfg = PVE
::Storage
::config
();
5680 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5682 $snap = $conf->{snapshots
}->{$snapname} = {};
5684 if ($save_vmstate && check_running
($vmid)) {
5685 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5688 &$snapshot_copy_config($conf, $snap);
5690 $snap->{snapstate
} = "prepare";
5691 $snap->{snaptime
} = time();
5692 $snap->{description
} = $comment if $comment;
5694 # always overwrite machine if we save vmstate. This makes sure we
5695 # can restore it later using correct machine type
5696 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5698 update_config_nolock
($vmid, $conf, 1);
5701 lock_config
($vmid, $updatefn);
5706 my $snapshot_commit = sub {
5707 my ($vmid, $snapname) = @_;
5709 my $updatefn = sub {
5711 my $conf = load_config
($vmid);
5713 die "missing snapshot lock\n"
5714 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5716 my $has_machine_config = defined($conf->{machine
});
5718 my $snap = $conf->{snapshots
}->{$snapname};
5720 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5722 die "wrong snapshot state\n"
5723 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5725 delete $snap->{snapstate
};
5726 delete $conf->{lock};
5728 my $newconf = &$snapshot_apply_config($conf, $snap);
5730 delete $newconf->{machine
} if !$has_machine_config;
5732 $newconf->{parent
} = $snapname;
5734 update_config_nolock
($vmid, $newconf, 1);
5737 lock_config
($vmid, $updatefn);
5740 sub snapshot_rollback
{
5741 my ($vmid, $snapname) = @_;
5745 my $storecfg = PVE
::Storage
::config
();
5747 my $conf = load_config
($vmid);
5749 my $get_snapshot_config = sub {
5751 die "you can't rollback if vm is a template\n" if is_template
($conf);
5753 my $res = $conf->{snapshots
}->{$snapname};
5755 die "snapshot '$snapname' does not exist\n" if !defined($res);
5760 my $snap = &$get_snapshot_config();
5762 foreach_drive
($snap, sub {
5763 my ($ds, $drive) = @_;
5765 return if drive_is_cdrom
($drive);
5767 my $volid = $drive->{file
};
5769 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5772 my $updatefn = sub {
5774 $conf = load_config
($vmid);
5776 $snap = &$get_snapshot_config();
5778 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5779 if $snap->{snapstate
};
5783 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5786 die "unable to rollback vm $vmid: vm is running\n"
5787 if check_running
($vmid);
5790 $conf->{lock} = 'rollback';
5792 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5793 delete $conf->{lock};
5799 my $has_machine_config = defined($conf->{machine
});
5801 # copy snapshot config to current config
5802 $conf = &$snapshot_apply_config($conf, $snap);
5803 $conf->{parent
} = $snapname;
5805 # Note: old code did not store 'machine', so we try to be smart
5806 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5807 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5808 # we remove the 'machine' configuration if not explicitly specified
5809 # in the original config.
5810 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5813 update_config_nolock
($vmid, $conf, 1);
5815 if (!$prepare && $snap->{vmstate
}) {
5816 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5817 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5821 lock_config
($vmid, $updatefn);
5823 foreach_drive
($snap, sub {
5824 my ($ds, $drive) = @_;
5826 return if drive_is_cdrom
($drive);
5828 my $volid = $drive->{file
};
5829 my $device = "drive-$ds";
5831 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5835 lock_config
($vmid, $updatefn);
5838 my $savevm_wait = sub {
5842 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5843 if (!$stat->{status
}) {
5844 die "savevm not active\n";
5845 } elsif ($stat->{status
} eq 'active') {
5848 } elsif ($stat->{status
} eq 'completed') {
5851 die "query-savevm returned status '$stat->{status}'\n";
5856 sub do_snapshots_with_qemu
{
5857 my ($storecfg, $volid) = @_;
5859 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5861 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5862 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5866 if ($volid =~ m/\.(qcow2|qed)$/){
5873 sub snapshot_create
{
5874 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5876 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5878 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5880 my $config = load_config
($vmid);
5882 my $running = check_running
($vmid);
5884 my $freezefs = $running && $config->{agent
};
5885 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5890 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5891 warn "guest-fsfreeze-freeze problems - $@" if $@;
5895 # create internal snapshots of all drives
5897 my $storecfg = PVE
::Storage
::config
();
5900 if ($snap->{vmstate
}) {
5901 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5902 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5903 &$savevm_wait($vmid);
5905 vm_mon_cmd
($vmid, "savevm-start");
5909 foreach_drive
($snap, sub {
5910 my ($ds, $drive) = @_;
5912 return if drive_is_cdrom
($drive);
5914 my $volid = $drive->{file
};
5915 my $device = "drive-$ds";
5917 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5918 $drivehash->{$ds} = 1;
5924 eval { vm_mon_cmd
($vmid, "savevm-end") };
5928 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5929 warn "guest-fsfreeze-thaw problems - $@" if $@;
5932 # savevm-end is async, we need to wait
5934 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5935 if (!$stat->{bytes
}) {
5938 print "savevm not yet finished\n";
5946 warn "snapshot create failed: starting cleanup\n";
5947 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5952 &$snapshot_commit($vmid, $snapname);
5955 # Note: $drivehash is only set when called from snapshot_create.
5956 sub snapshot_delete
{
5957 my ($vmid, $snapname, $force, $drivehash) = @_;
5964 my $unlink_parent = sub {
5965 my ($confref, $new_parent) = @_;
5967 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5969 $confref->{parent
} = $new_parent;
5971 delete $confref->{parent
};
5976 my $updatefn = sub {
5977 my ($remove_drive) = @_;
5979 my $conf = load_config
($vmid);
5983 die "you can't delete a snapshot if vm is a template\n"
5984 if is_template
($conf);
5987 $snap = $conf->{snapshots
}->{$snapname};
5989 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5991 # remove parent refs
5993 &$unlink_parent($conf, $snap->{parent
});
5994 foreach my $sn (keys %{$conf->{snapshots
}}) {
5995 next if $sn eq $snapname;
5996 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6000 if ($remove_drive) {
6001 if ($remove_drive eq 'vmstate') {
6002 delete $snap->{$remove_drive};
6004 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6005 my $volid = $drive->{file
};
6006 delete $snap->{$remove_drive};
6007 add_unused_volume
($conf, $volid);
6012 $snap->{snapstate
} = 'delete';
6014 delete $conf->{snapshots
}->{$snapname};
6015 delete $conf->{lock} if $drivehash;
6016 foreach my $volid (@$unused) {
6017 add_unused_volume
($conf, $volid);
6021 update_config_nolock
($vmid, $conf, 1);
6024 lock_config
($vmid, $updatefn);
6026 # now remove vmstate file
6028 my $storecfg = PVE
::Storage
::config
();
6030 if ($snap->{vmstate
}) {
6031 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6033 die $err if !$force;
6036 # save changes (remove vmstate from snapshot)
6037 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6040 # now remove all internal snapshots
6041 foreach_drive
($snap, sub {
6042 my ($ds, $drive) = @_;
6044 return if drive_is_cdrom
($drive);
6046 my $volid = $drive->{file
};
6047 my $device = "drive-$ds";
6049 if (!$drivehash || $drivehash->{$ds}) {
6050 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6052 die $err if !$force;
6057 # save changes (remove drive fron snapshot)
6058 lock_config
($vmid, $updatefn, $ds) if !$force;
6059 push @$unused, $volid;
6062 # now cleanup config
6064 lock_config
($vmid, $updatefn);
6068 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6071 foreach_drive
($conf, sub {
6072 my ($ds, $drive) = @_;
6074 return if drive_is_cdrom
($drive);
6075 my $volid = $drive->{file
};
6076 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6079 return $err ?
0 : 1;
6082 sub template_create
{
6083 my ($vmid, $conf, $disk) = @_;
6085 my $storecfg = PVE
::Storage
::config
();
6087 foreach_drive
($conf, sub {
6088 my ($ds, $drive) = @_;
6090 return if drive_is_cdrom
($drive);
6091 return if $disk && $ds ne $disk;
6093 my $volid = $drive->{file
};
6094 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6096 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6097 $drive->{file
} = $voliddst;
6098 $conf->{$ds} = print_drive
($vmid, $drive);
6099 update_config_nolock
($vmid, $conf, 1);
6106 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6109 sub qemu_img_convert
{
6110 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6112 my $storecfg = PVE
::Storage
::config
();
6113 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6114 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6116 if ($src_storeid && $dst_storeid) {
6117 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6118 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6120 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6121 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6123 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6124 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6127 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6128 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6129 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6133 if($line =~ m/\((\S+)\/100\
%\)/){
6135 my $transferred = int($size * $percent / 100);
6136 my $remaining = $size - $transferred;
6138 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6143 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6145 die "copy failed: $err" if $err;
6149 sub qemu_img_format
{
6150 my ($scfg, $volname) = @_;
6152 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6159 sub qemu_drive_mirror
{
6160 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6162 my $storecfg = PVE
::Storage
::config
();
6163 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6165 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6167 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6169 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6171 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6172 $opts->{format
} = $format if $format;
6174 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6177 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6179 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6180 my $stat = @$stats[0];
6181 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6182 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6184 my $busy = $stat->{busy
};
6185 my $ready = $stat->{ready
};
6187 if (my $total = $stat->{len
}) {
6188 my $transferred = $stat->{offset
} || 0;
6189 my $remaining = $total - $transferred;
6190 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6192 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6196 if ($stat->{ready
} eq 'true') {
6198 last if $vmiddst != $vmid;
6200 # try to switch the disk if source and destination are on the same guest
6201 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6203 die $@ if $@ !~ m/cannot be completed/;
6212 my $cancel_job = sub {
6213 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6215 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6216 my $stat = @$stats[0];
6223 eval { &$cancel_job(); };
6224 die "mirroring error: $err";
6227 if ($vmiddst != $vmid) {
6228 # if we clone a disk for a new target vm, we don't switch the disk
6229 &$cancel_job(); # so we call block-job-cancel
6234 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6235 $newvmid, $storage, $format, $full, $newvollist) = @_;
6240 print "create linked clone of drive $drivename ($drive->{file})\n";
6241 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6242 push @$newvollist, $newvolid;
6244 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6245 $storeid = $storage if $storage;
6247 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6249 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6250 $format = qemu_img_format
($scfg, $volname);
6253 # test if requested format is supported - else use default
6254 my $supported = grep { $_ eq $format } @$validFormats;
6255 $format = $defFormat if !$supported;
6257 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6259 print "create full clone of drive $drivename ($drive->{file})\n";
6260 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6261 push @$newvollist, $newvolid;
6263 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6265 if (!$running || $snapname) {
6266 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6268 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6272 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6275 $disk->{format
} = undef;
6276 $disk->{file
} = $newvolid;
6277 $disk->{size
} = $size;
6282 # this only works if VM is running
6283 sub get_current_qemu_machine
{
6286 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6287 my $res = vm_qmp_command
($vmid, $cmd);
6289 my ($current, $default);
6290 foreach my $e (@$res) {
6291 $default = $e->{name
} if $e->{'is-default'};
6292 $current = $e->{name
} if $e->{'is-current'};
6295 # fallback to the default machine if current is not supported by qemu
6296 return $current || $default || 'pc';
6299 sub qemu_machine_feature_enabled
{
6300 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6305 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6307 $current_major = $3;
6308 $current_minor = $4;
6310 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6312 $current_major = $1;
6313 $current_minor = $2;
6316 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6325 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6326 my (undef, $id, $function) = @_;
6327 my $res = { id
=> $id, function
=> $function};
6328 push @{$devices->{$id}}, $res;
6334 sub vm_iothreads_list
{
6337 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6340 foreach my $iothread (@$res) {
6341 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6348 my ($conf, $drive) = @_;
6352 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6354 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6360 my $controller = int($drive->{index} / $maxdev);
6361 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6363 return ($maxdev, $controller, $controller_prefix);
6366 # bash completion helper
6368 sub complete_backup_archives
{
6369 my ($cmdname, $pname, $cvalue) = @_;
6371 my $cfg = PVE
::Storage
::config
();
6375 if ($cvalue =~ m/^([^:]+):/) {
6379 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6382 foreach my $id (keys %$data) {
6383 foreach my $item (@{$data->{$id}}) {
6384 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6385 push @$res, $item->{volid
} if defined($item->{volid
});
6392 my $complete_vmid_full = sub {
6395 my $idlist = vmstatus
();
6399 foreach my $id (keys %$idlist) {
6400 my $d = $idlist->{$id};
6401 if (defined($running)) {
6402 next if $d->{template
};
6403 next if $running && $d->{status
} ne 'running';
6404 next if !$running && $d->{status
} eq 'running';
6413 return &$complete_vmid_full();
6416 sub complete_vmid_stopped
{
6417 return &$complete_vmid_full(0);
6420 sub complete_vmid_running
{
6421 return &$complete_vmid_full(1);
6424 sub complete_storage
{
6426 my $cfg = PVE
::Storage
::config
();
6427 my $ids = $cfg->{ids
};
6430 foreach my $sid (keys %$ids) {
6431 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);