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);
33 use File
::Copy
qw(copy);
35 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
37 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
39 # Note about locking: we use flock on the config file protect
40 # against concurent actions.
41 # Aditionaly, we have a 'lock' setting in the config file. This
42 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
43 # allowed when such lock is set. But you can ignore this kind of
44 # lock with the --skiplock flag.
46 cfs_register_file
('/qemu-server/',
50 PVE
::JSONSchema
::register_standard_option
('skiplock', {
51 description
=> "Ignore locks - only root is allowed to use this option.",
56 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
57 description
=> "Some command save/restore state from this location.",
63 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
64 description
=> "The name of the snapshot.",
65 type
=> 'string', format
=> 'pve-configid',
69 #no warnings 'redefine';
72 my ($controller, $vmid, $option, $value) = @_;
74 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
75 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
79 my $nodename = PVE
::INotify
::nodename
();
81 mkdir "/etc/pve/nodes/$nodename";
82 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
85 my $var_run_tmpdir = "/var/run/qemu-server";
86 mkdir $var_run_tmpdir;
88 my $lock_dir = "/var/lock/qemu-server";
91 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Specifies whether a VM will be started during system bootup.",
103 description
=> "Automatic restart after crash (currently ignored).",
108 type
=> 'string', format
=> 'pve-hotplug-features',
109 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'.",
110 default => 'network,disk,usb',
115 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
121 description
=> "Lock/unlock the VM.",
122 enum
=> [qw(migrate backup snapshot rollback)],
127 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.",
135 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.",
143 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
150 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
156 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",
164 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
165 enum
=> PVE
::Tools
::kvmkeymaplist
(),
170 type
=> 'string', format
=> 'dns-name',
171 description
=> "Set a name for the VM. Only used on the configuration web interface.",
176 description
=> "scsi controller model",
177 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
183 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
188 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
189 description
=> <<EODESC,
190 Used to enable special optimization/features for specific
193 other => unspecified OS
194 wxp => Microsoft Windows XP
195 w2k => Microsoft Windows 2000
196 w2k3 => Microsoft Windows 2003
197 w2k8 => Microsoft Windows 2008
198 wvista => Microsoft Windows Vista
199 win7 => Microsoft Windows 7
200 win8 => Microsoft Windows 8/2012
201 l24 => Linux 2.4 Kernel
202 l26 => Linux 2.6/3.X Kernel
203 solaris => solaris/opensolaris/openindiania kernel
205 other|l24|l26|solaris ... no special behaviour
206 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
212 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
213 pattern
=> '[acdn]{1,4}',
218 type
=> 'string', format
=> 'pve-qm-bootdisk',
219 description
=> "Enable booting from specified disk.",
220 pattern
=> '(ide|sata|scsi|virtio)\d+',
225 description
=> "The number of CPUs. Please use option -sockets instead.",
232 description
=> "The number of CPU sockets.",
239 description
=> "The number of cores per socket.",
246 description
=> "Enable/disable Numa.",
252 description
=> "Number of hotplugged vcpus.",
259 description
=> "Enable/disable ACPI.",
265 description
=> "Enable/disable Qemu GuestAgent.",
271 description
=> "Enable/disable KVM hardware virtualization.",
277 description
=> "Enable/disable time drift fix.",
283 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
288 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
293 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.",
294 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
298 type
=> 'string', format
=> 'pve-qm-watchdog',
299 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
300 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)",
305 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
306 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'.",
307 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
310 startup
=> get_standard_option
('pve-startup-order'),
314 description
=> "Enable/disable Template.",
320 description
=> <<EODESCR,
321 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
323 args: -no-reboot -no-hpet
330 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).",
335 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
339 migrate_downtime
=> {
342 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
348 type
=> 'string', format
=> 'pve-qm-drive',
349 typetext
=> 'volume',
350 description
=> "This is an alias for option -ide2",
354 description
=> "Emulated CPU type.",
356 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) ],
359 parent
=> get_standard_option
('pve-snapshot-name', {
361 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
365 description
=> "Timestamp for snapshots.",
371 type
=> 'string', format
=> 'pve-volume-id',
372 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
375 description
=> "Specific the Qemu machine type.",
377 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
382 description
=> "Specify SMBIOS type 1 fields.",
383 type
=> 'string', format
=> 'pve-qm-smbios1',
384 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
391 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
397 enum
=> [ qw(seabios ovmf) ],
398 description
=> "Select BIOS implementation.",
399 default => 'seabios',
403 # what about other qemu settings ?
405 #machine => 'string',
418 ##soundhw => 'string',
420 while (my ($k, $v) = each %$confdesc) {
421 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
424 my $MAX_IDE_DISKS = 4;
425 my $MAX_SCSI_DISKS = 14;
426 my $MAX_VIRTIO_DISKS = 16;
427 my $MAX_SATA_DISKS = 6;
428 my $MAX_USB_DEVICES = 5;
430 my $MAX_UNUSED_DISKS = 8;
431 my $MAX_HOSTPCI_DEVICES = 4;
432 my $MAX_SERIAL_PORTS = 4;
433 my $MAX_PARALLEL_PORTS = 3;
435 my $MAX_MEM = 4194304;
436 my $STATICMEM = 1024;
440 type
=> 'string', format
=> 'pve-qm-numanode',
441 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
442 description
=> "numa topology",
444 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
446 for (my $i = 0; $i < $MAX_NUMA; $i++) {
447 $confdesc->{"numa$i"} = $numadesc;
450 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
451 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
452 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
453 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
457 type
=> 'string', format
=> 'pve-qm-net',
458 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
459 description
=> <<EODESCR,
460 Specify network devices.
462 MODEL is one of: $nic_model_list_txt
464 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
465 automatically generated if not specified.
467 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
469 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'.
471 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
477 The DHCP server assign addresses to the guest starting from 10.0.2.15.
481 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
483 for (my $i = 0; $i < $MAX_NETS; $i++) {
484 $confdesc->{"net$i"} = $netdesc;
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] [,serial=serial][,model=model]',
493 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
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] [,iothread=on] [,queues=<nbqueues>] [,serial=serial]',
501 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
503 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
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] [,serial=serial]',
509 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
511 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
515 type
=> 'string', format
=> 'pve-qm-drive',
516 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,serial=serial]',
517 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
519 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
523 type
=> 'string', format
=> 'pve-qm-usb-device',
524 typetext
=> 'host=HOSTUSBDEVICE|spice',
525 description
=> <<EODESCR,
526 Configure an USB device (n is 0 to 4). This can be used to
527 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
529 'bus-port(.port)*' (decimal numbers) or
530 'vendor_id:product_id' (hexadeciaml numbers)
532 You can use the 'lsusb -t' command to list existing usb devices.
534 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
536 The value 'spice' can be used to add a usb redirection devices for spice.
540 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
544 type
=> 'string', format
=> 'pve-qm-hostpci',
545 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
546 description
=> <<EODESCR,
547 Map host pci devices. HOSTPCIDEVICE syntax is:
549 'bus:dev.func' (hexadecimal numbers)
551 You can us the 'lspci' command to list existing pci devices.
553 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
555 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
557 Experimental: user reported problems with this option.
560 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
565 pattern
=> '(/dev/.+|socket)',
566 description
=> <<EODESCR,
567 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).
569 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
571 Experimental: user reported problems with this option.
578 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
579 description
=> <<EODESCR,
580 Map host parallel devices (n is 0 to 2).
582 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
584 Experimental: user reported problems with this option.
588 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
589 $confdesc->{"parallel$i"} = $paralleldesc;
592 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
593 $confdesc->{"serial$i"} = $serialdesc;
596 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
597 $confdesc->{"hostpci$i"} = $hostpcidesc;
600 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
601 $drivename_hash->{"ide$i"} = 1;
602 $confdesc->{"ide$i"} = $idedesc;
605 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
606 $drivename_hash->{"sata$i"} = 1;
607 $confdesc->{"sata$i"} = $satadesc;
610 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
611 $drivename_hash->{"scsi$i"} = 1;
612 $confdesc->{"scsi$i"} = $scsidesc ;
615 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
616 $drivename_hash->{"virtio$i"} = 1;
617 $confdesc->{"virtio$i"} = $virtiodesc;
620 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
621 $confdesc->{"usb$i"} = $usbdesc;
626 type
=> 'string', format
=> 'pve-volume-id',
627 description
=> "Reference to unused volumes.",
630 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
631 $confdesc->{"unused$i"} = $unuseddesc;
634 my $kvm_api_version = 0;
638 return $kvm_api_version if $kvm_api_version;
640 my $fh = IO
::File-
>new("</dev/kvm") ||
643 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
644 $kvm_api_version = $v;
649 return $kvm_api_version;
652 my $kvm_user_version;
654 sub kvm_user_version
{
656 return $kvm_user_version if $kvm_user_version;
658 $kvm_user_version = 'unknown';
660 my $tmp = `kvm -help 2>/dev/null`;
662 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
663 $kvm_user_version = $2;
666 return $kvm_user_version;
670 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
673 # order is important - used to autoselect boot disk
674 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
675 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
676 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
677 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
680 sub valid_drivename
{
683 return defined($drivename_hash->{$dev});
688 return defined($confdesc->{$key});
692 return $nic_model_list;
695 sub os_list_description
{
700 w2k
=> 'Windows 2000',
701 w2k3
=>, 'Windows 2003',
702 w2k8
=> 'Windows 2008',
703 wvista
=> 'Windows Vista',
705 win8
=> 'Windows 8/2012',
715 return $cdrom_path if $cdrom_path;
717 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
718 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
719 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
723 my ($storecfg, $vmid, $cdrom) = @_;
725 if ($cdrom eq 'cdrom') {
726 return get_cdrom_path
();
727 } elsif ($cdrom eq 'none') {
729 } elsif ($cdrom =~ m
|^/|) {
732 return PVE
::Storage
::path
($storecfg, $cdrom);
736 # try to convert old style file names to volume IDs
737 sub filename_to_volume_id
{
738 my ($vmid, $file, $media) = @_;
740 if (!($file eq 'none' || $file eq 'cdrom' ||
741 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
743 return undef if $file =~ m
|/|;
745 if ($media && $media eq 'cdrom') {
746 $file = "local:iso/$file";
748 $file = "local:$vmid/$file";
755 sub verify_media_type
{
756 my ($opt, $vtype, $media) = @_;
761 if ($media eq 'disk') {
763 } elsif ($media eq 'cdrom') {
766 die "internal error";
769 return if ($vtype eq $etype);
771 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
774 sub cleanup_drive_path
{
775 my ($opt, $storecfg, $drive) = @_;
777 # try to convert filesystem paths to volume IDs
779 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
780 ($drive->{file
} !~ m
|^/dev/.+|) &&
781 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
782 ($drive->{file
} !~ m/^\d+$/)) {
783 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
784 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
785 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
786 verify_media_type
($opt, $vtype, $drive->{media
});
787 $drive->{file
} = $volid;
790 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
793 sub create_conf_nolock
{
794 my ($vmid, $settings) = @_;
796 my $filename = config_file
($vmid);
798 die "configuration file '$filename' already exists\n" if -f
$filename;
800 my $defaults = load_defaults
();
802 $settings->{name
} = "vm$vmid" if !$settings->{name
};
803 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
806 foreach my $opt (keys %$settings) {
807 next if !$confdesc->{$opt};
809 my $value = $settings->{$opt};
812 $data .= "$opt: $value\n";
815 PVE
::Tools
::file_set_contents
($filename, $data);
818 sub parse_hotplug_features
{
823 return $res if $data eq '0';
825 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
827 foreach my $feature (PVE
::Tools
::split_list
($data)) {
828 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
831 warn "ignoring unknown hotplug feature '$feature'\n";
837 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
838 sub pve_verify_hotplug_features
{
839 my ($value, $noerr) = @_;
841 return $value if parse_hotplug_features
($value);
843 return undef if $noerr;
845 die "unable to parse hotplug option\n";
848 my $parse_size = sub {
851 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
852 my ($size, $unit) = ($1, $3);
855 $size = $size * 1024;
856 } elsif ($unit eq 'M') {
857 $size = $size * 1024 * 1024;
858 } elsif ($unit eq 'G') {
859 $size = $size * 1024 * 1024 * 1024;
865 my $format_size = sub {
870 my $kb = int($size/1024);
871 return $size if $kb*1024 != $size;
873 my $mb = int($kb/1024);
874 return "${kb}K" if $mb*1024 != $kb;
876 my $gb = int($mb/1024);
877 return "${mb}M" if $gb*1024 != $mb;
882 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
883 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
884 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
885 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
886 # [,serial=serial][,model=model]
889 my ($key, $data) = @_;
893 # $key may be undefined - used to verify JSON parameters
894 if (!defined($key)) {
895 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
897 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
898 $res->{interface
} = $1;
904 foreach my $p (split (/,/, $data)) {
905 next if $p =~ m/^\s*$/;
907 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues|serial|model)=(.+)$/) {
908 my ($k, $v) = ($1, $2);
910 $k = 'file' if $k eq 'volume';
912 return undef if defined $res->{$k};
914 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
915 return undef if !$v || $v !~ m/^\d+/;
917 $v = sprintf("%.3f", $v / (1024*1024));
921 if (!$res->{file
} && $p !~ m/=/) {
929 return undef if !$res->{file
};
931 return undef if $res->{cache
} &&
932 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
933 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
934 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
935 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
936 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
937 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
938 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
939 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
940 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
941 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
942 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
943 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
944 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
945 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
946 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
948 return undef if $res->{mbps_rd
} && $res->{mbps
};
949 return undef if $res->{mbps_wr
} && $res->{mbps
};
951 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
953 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
955 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
956 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
958 return undef if $res->{iops_rd
} && $res->{iops
};
959 return undef if $res->{iops_wr
} && $res->{iops
};
962 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
963 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
964 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
965 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
966 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
967 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
970 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
973 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
974 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
975 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
976 return undef if $res->{interface
} eq 'virtio';
979 # rerror does not work with scsi drives
980 if ($res->{rerror
}) {
981 return undef if $res->{interface
} eq 'scsi';
987 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
990 my ($vmid, $drive) = @_;
993 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
994 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
997 if ($drive->{size
}) {
998 $opts .= ",size=" . &$format_size($drive->{size
});
1001 if (my $model = $drive->{model
}) {
1002 $opts .= ",model=$model";
1005 return "$drive->{file}$opts";
1009 my($fh, $noerr) = @_;
1012 my $SG_GET_VERSION_NUM = 0x2282;
1014 my $versionbuf = "\x00" x
8;
1015 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1017 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1020 my $version = unpack("I", $versionbuf);
1021 if ($version < 30000) {
1022 die "scsi generic interface too old\n" if !$noerr;
1026 my $buf = "\x00" x
36;
1027 my $sensebuf = "\x00" x
8;
1028 my $cmd = pack("C x3 C x1", 0x12, 36);
1030 # see /usr/include/scsi/sg.h
1031 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";
1033 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1034 length($sensebuf), 0, length($buf), $buf,
1035 $cmd, $sensebuf, 6000);
1037 $ret = ioctl($fh, $SG_IO, $packet);
1039 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1043 my @res = unpack($sg_io_hdr_t, $packet);
1044 if ($res[17] || $res[18]) {
1045 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1050 (my $byte0, my $byte1, $res->{vendor
},
1051 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1053 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1054 $res->{type
} = $byte0 & 31;
1062 my $fh = IO
::File-
>new("+<$path") || return undef;
1063 my $res = scsi_inquiry
($fh, 1);
1069 sub machine_type_is_q35
{
1072 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1075 sub print_tabletdevice_full
{
1078 my $q35 = machine_type_is_q35
($conf);
1080 # we use uhci for old VMs because tablet driver was buggy in older qemu
1081 my $usbbus = $q35 ?
"ehci" : "uhci";
1083 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1086 sub print_drivedevice_full
{
1087 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1092 if ($drive->{interface
} eq 'virtio') {
1093 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1094 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1095 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1096 } elsif ($drive->{interface
} eq 'scsi') {
1098 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1099 my $unit = $drive->{index} % $maxdev;
1100 my $devicetype = 'hd';
1102 if (drive_is_cdrom
($drive)) {
1105 if ($drive->{file
} =~ m
|^/|) {
1106 $path = $drive->{file
};
1108 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1111 if($path =~ m/^iscsi\:\/\
//){
1112 $devicetype = 'generic';
1114 if (my $info = path_is_scsi
($path)) {
1115 if ($info->{type
} == 0) {
1116 $devicetype = 'block';
1117 } elsif ($info->{type
} == 1) { # tape
1118 $devicetype = 'generic';
1124 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1125 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1127 $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}";
1130 } elsif ($drive->{interface
} eq 'ide'){
1132 my $controller = int($drive->{index} / $maxdev);
1133 my $unit = $drive->{index} % $maxdev;
1134 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1136 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1137 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1138 $device .= ",model=$model";
1140 } elsif ($drive->{interface
} eq 'sata'){
1141 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1142 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1143 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1144 } elsif ($drive->{interface
} eq 'usb') {
1146 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1148 die "unsupported interface type";
1151 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1156 sub get_initiator_name
{
1159 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1160 while (defined(my $line = <$fh>)) {
1161 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1170 sub print_drive_full
{
1171 my ($storecfg, $vmid, $drive) = @_;
1174 my $volid = $drive->{file
};
1177 if (drive_is_cdrom
($drive)) {
1178 $path = get_iso_path
($storecfg, $vmid, $volid);
1180 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1182 $path = PVE
::Storage
::path
($storecfg, $volid);
1183 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1184 $format = qemu_img_format
($scfg, $volname);
1191 foreach my $o (@qemu_drive_options) {
1192 next if $o eq 'bootindex';
1193 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1196 $opts .= ",format=$format" if $format && !$drive->{format
};
1198 foreach my $o (qw(bps bps_rd bps_wr)) {
1199 my $v = $drive->{"m$o"};
1200 $opts .= ",$o=" . int($v*1024*1024) if $v;
1203 my $cache_direct = 0;
1205 if (my $cache = $drive->{cache
}) {
1206 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1207 } elsif (!drive_is_cdrom
($drive)) {
1208 $opts .= ",cache=none";
1212 # aio native works only with O_DIRECT
1213 if (!$drive->{aio
}) {
1215 $opts .= ",aio=native";
1217 $opts .= ",aio=threads";
1221 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1222 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1224 my $pathinfo = $path ?
"file=$path," : '';
1226 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1229 sub print_netdevice_full
{
1230 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1232 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1234 my $device = $net->{model
};
1235 if ($net->{model
} eq 'virtio') {
1236 $device = 'virtio-net-pci';
1239 my $pciaddr = print_pci_addr
("$netid", $bridges);
1240 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1241 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1242 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1243 my $vectors = $net->{queues
} * 2 + 2;
1244 $tmpstr .= ",vectors=$vectors,mq=on";
1246 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1248 if ($use_old_bios_files) {
1250 if ($device eq 'virtio-net-pci') {
1251 $romfile = 'pxe-virtio.rom';
1252 } elsif ($device eq 'e1000') {
1253 $romfile = 'pxe-e1000.rom';
1254 } elsif ($device eq 'ne2k') {
1255 $romfile = 'pxe-ne2k_pci.rom';
1256 } elsif ($device eq 'pcnet') {
1257 $romfile = 'pxe-pcnet.rom';
1258 } elsif ($device eq 'rtl8139') {
1259 $romfile = 'pxe-rtl8139.rom';
1261 $tmpstr .= ",romfile=$romfile" if $romfile;
1267 sub print_netdev_full
{
1268 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1271 if ($netid =~ m/^net(\d+)$/) {
1275 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1277 my $ifname = "tap${vmid}i$i";
1279 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1280 die "interface name '$ifname' is too long (max 15 character)\n"
1281 if length($ifname) >= 16;
1283 my $vhostparam = '';
1284 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1286 my $vmname = $conf->{name
} || "vm$vmid";
1289 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1291 if ($net->{bridge
}) {
1292 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1294 $netdev = "type=user,id=$netid,hostname=$vmname";
1297 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1302 sub drive_is_cdrom
{
1305 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1314 foreach my $kvp (split(/,/, $data)) {
1316 if ($kvp =~ m/^memory=(\S+)$/) {
1317 $res->{memory
} = $1;
1318 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1319 $res->{policy
} = $1;
1320 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1321 $res->{cpus
}->{start
} = $1;
1322 $res->{cpus
}->{end
} = $3;
1323 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1324 $res->{hostnodes
}->{start
} = $1;
1325 $res->{hostnodes
}->{end
} = $3;
1337 return undef if !$value;
1340 my @list = split(/,/, $value);
1344 foreach my $kv (@list) {
1346 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1349 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1352 my $pcidevices = lspci
($2);
1353 $res->{pciid
} = $pcidevices->{$2};
1355 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1356 $res->{rombar
} = $1;
1357 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1358 $res->{'x-vga'} = $1;
1359 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1360 $res->{pcie
} = 1 if $1 == 1;
1362 warn "unknown hostpci setting '$kv'\n";
1366 return undef if !$found;
1371 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1377 foreach my $kvp (split(/,/, $data)) {
1379 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) {
1381 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1382 $res->{model
} = $model;
1383 $res->{macaddr
} = $mac;
1384 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1385 $res->{bridge
} = $1;
1386 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1387 $res->{queues
} = $1;
1388 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1390 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1392 } elsif ($kvp =~ m/^firewall=([01])$/) {
1393 $res->{firewall
} = $1;
1394 } elsif ($kvp =~ m/^link_down=([01])$/) {
1395 $res->{link_down
} = $1;
1402 return undef if !$res->{model
};
1410 my $res = "$net->{model}";
1411 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1412 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1413 $res .= ",rate=$net->{rate}" if $net->{rate
};
1414 $res .= ",tag=$net->{tag}" if $net->{tag
};
1415 $res .= ",firewall=1" if $net->{firewall
};
1416 $res .= ",link_down=1" if $net->{link_down
};
1417 $res .= ",queues=$net->{queues}" if $net->{queues
};
1422 sub add_random_macs
{
1423 my ($settings) = @_;
1425 foreach my $opt (keys %$settings) {
1426 next if $opt !~ m/^net(\d+)$/;
1427 my $net = parse_net
($settings->{$opt});
1429 $settings->{$opt} = print_net
($net);
1433 sub add_unused_volume
{
1434 my ($config, $volid) = @_;
1437 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1438 my $test = "unused$ind";
1439 if (my $vid = $config->{$test}) {
1440 return if $vid eq $volid; # do not add duplicates
1446 die "To many unused volume - please delete them first.\n" if !$key;
1448 $config->{$key} = $volid;
1453 sub vm_is_volid_owner
{
1454 my ($storecfg, $vmid, $volid) = @_;
1456 if ($volid !~ m
|^/|) {
1458 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1459 if ($owner && ($owner == $vmid)) {
1467 sub split_flagged_list
{
1468 my $text = shift || '';
1469 $text =~ s/[,;]/ /g;
1471 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1474 sub join_flagged_list
{
1475 my ($how, $lst) = @_;
1476 join $how, map { $lst->{$_} . $_ } keys %$lst;
1479 sub vmconfig_delete_pending_option
{
1480 my ($conf, $key, $force) = @_;
1482 delete $conf->{pending
}->{$key};
1483 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1484 $pending_delete_hash->{$key} = $force ?
'!' : '';
1485 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1488 sub vmconfig_undelete_pending_option
{
1489 my ($conf, $key) = @_;
1491 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1492 delete $pending_delete_hash->{$key};
1494 if (%$pending_delete_hash) {
1495 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1497 delete $conf->{pending
}->{delete};
1501 sub vmconfig_register_unused_drive
{
1502 my ($storecfg, $vmid, $conf, $drive) = @_;
1504 if (!drive_is_cdrom
($drive)) {
1505 my $volid = $drive->{file
};
1506 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1507 add_unused_volume
($conf, $volid, $vmid);
1512 sub vmconfig_cleanup_pending
{
1515 # remove pending changes when nothing changed
1517 foreach my $opt (keys %{$conf->{pending
}}) {
1518 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1520 delete $conf->{pending
}->{$opt};
1524 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1525 my $pending_delete_hash = {};
1526 while (my ($opt, $force) = each %$current_delete_hash) {
1527 if (defined($conf->{$opt})) {
1528 $pending_delete_hash->{$opt} = $force;
1534 if (%$pending_delete_hash) {
1535 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1537 delete $conf->{pending
}->{delete};
1543 my $valid_smbios1_options = {
1544 manufacturer
=> '\S+',
1548 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1553 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1559 foreach my $kvp (split(/,/, $data)) {
1560 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1561 my ($k, $v) = split(/=/, $kvp);
1562 return undef if !defined($k) || !defined($v);
1563 return undef if !$valid_smbios1_options->{$k};
1564 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1575 foreach my $k (keys %$smbios1) {
1576 next if !defined($smbios1->{$k});
1577 next if !$valid_smbios1_options->{$k};
1578 $data .= ',' if $data;
1579 $data .= "$k=$smbios1->{$k}";
1584 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1585 sub verify_smbios1
{
1586 my ($value, $noerr) = @_;
1588 return $value if parse_smbios1
($value);
1590 return undef if $noerr;
1592 die "unable to parse smbios (type 1) options\n";
1595 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1596 sub verify_bootdisk
{
1597 my ($value, $noerr) = @_;
1599 return $value if valid_drivename
($value);
1601 return undef if $noerr;
1603 die "invalid boot disk '$value'\n";
1606 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1608 my ($value, $noerr) = @_;
1610 return $value if parse_numa
($value);
1612 return undef if $noerr;
1614 die "unable to parse numa options\n";
1617 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1619 my ($value, $noerr) = @_;
1621 return $value if parse_net
($value);
1623 return undef if $noerr;
1625 die "unable to parse network options\n";
1628 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1630 my ($value, $noerr) = @_;
1632 return $value if parse_drive
(undef, $value);
1634 return undef if $noerr;
1636 die "unable to parse drive options\n";
1639 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1640 sub verify_hostpci
{
1641 my ($value, $noerr) = @_;
1643 return $value if parse_hostpci
($value);
1645 return undef if $noerr;
1647 die "unable to parse pci id\n";
1650 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1651 sub verify_watchdog
{
1652 my ($value, $noerr) = @_;
1654 return $value if parse_watchdog
($value);
1656 return undef if $noerr;
1658 die "unable to parse watchdog options\n";
1661 sub parse_watchdog
{
1664 return undef if !$value;
1668 foreach my $p (split(/,/, $value)) {
1669 next if $p =~ m/^\s*$/;
1671 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1673 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1674 $res->{action
} = $2;
1683 sub parse_usb_device
{
1686 return undef if !$value;
1688 my @dl = split(/,/, $value);
1692 foreach my $v (@dl) {
1693 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1695 $res->{vendorid
} = $2;
1696 $res->{productid
} = $4;
1697 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1699 $res->{hostbus
} = $1;
1700 $res->{hostport
} = $2;
1701 } elsif ($v =~ m/^spice$/) {
1708 return undef if !$found;
1713 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1714 sub verify_usb_device
{
1715 my ($value, $noerr) = @_;
1717 return $value if parse_usb_device
($value);
1719 return undef if $noerr;
1721 die "unable to parse usb device\n";
1724 # add JSON properties for create and set function
1725 sub json_config_properties
{
1728 foreach my $opt (keys %$confdesc) {
1729 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1730 $prop->{$opt} = $confdesc->{$opt};
1737 my ($key, $value) = @_;
1739 die "unknown setting '$key'\n" if !$confdesc->{$key};
1741 my $type = $confdesc->{$key}->{type
};
1743 if (!defined($value)) {
1744 die "got undefined value\n";
1747 if ($value =~ m/[\n\r]/) {
1748 die "property contains a line feed\n";
1751 if ($type eq 'boolean') {
1752 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1753 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1754 die "type check ('boolean') failed - got '$value'\n";
1755 } elsif ($type eq 'integer') {
1756 return int($1) if $value =~ m/^(\d+)$/;
1757 die "type check ('integer') failed - got '$value'\n";
1758 } elsif ($type eq 'number') {
1759 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1760 die "type check ('number') failed - got '$value'\n";
1761 } elsif ($type eq 'string') {
1762 if (my $fmt = $confdesc->{$key}->{format
}) {
1763 if ($fmt eq 'pve-qm-drive') {
1764 # special case - we need to pass $key to parse_drive()
1765 my $drive = parse_drive
($key, $value);
1766 return $value if $drive;
1767 die "unable to parse drive options\n";
1769 PVE
::JSONSchema
::check_format
($fmt, $value);
1772 $value =~ s/^\"(.*)\"$/$1/;
1775 die "internal error"
1779 sub lock_config_full
{
1780 my ($vmid, $timeout, $code, @param) = @_;
1782 my $filename = config_file_lock
($vmid);
1784 my $res = lock_file
($filename, $timeout, $code, @param);
1791 sub lock_config_mode
{
1792 my ($vmid, $timeout, $shared, $code, @param) = @_;
1794 my $filename = config_file_lock
($vmid);
1796 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1804 my ($vmid, $code, @param) = @_;
1806 return lock_config_full
($vmid, 10, $code, @param);
1809 sub cfs_config_path
{
1810 my ($vmid, $node) = @_;
1812 $node = $nodename if !$node;
1813 return "nodes/$node/qemu-server/$vmid.conf";
1816 sub check_iommu_support
{
1817 #fixme : need to check IOMMU support
1818 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1826 my ($vmid, $node) = @_;
1828 my $cfspath = cfs_config_path
($vmid, $node);
1829 return "/etc/pve/$cfspath";
1832 sub config_file_lock
{
1835 return "$lock_dir/lock-$vmid.conf";
1841 my $conf = config_file
($vmid);
1842 utime undef, undef, $conf;
1846 my ($storecfg, $vmid, $keep_empty_config) = @_;
1848 my $conffile = config_file
($vmid);
1850 my $conf = load_config
($vmid);
1854 # only remove disks owned by this VM
1855 foreach_drive
($conf, sub {
1856 my ($ds, $drive) = @_;
1858 return if drive_is_cdrom
($drive);
1860 my $volid = $drive->{file
};
1862 return if !$volid || $volid =~ m
|^/|;
1864 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1865 return if !$path || !$owner || ($owner != $vmid);
1867 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1870 if ($keep_empty_config) {
1871 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1876 # also remove unused disk
1878 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1881 PVE
::Storage
::foreach_volid
($dl, sub {
1882 my ($volid, $sid, $volname, $d) = @_;
1883 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1893 my ($vmid, $node) = @_;
1895 my $cfspath = cfs_config_path
($vmid, $node);
1897 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1899 die "no such VM ('$vmid')\n" if !defined($conf);
1904 sub parse_vm_config
{
1905 my ($filename, $raw) = @_;
1907 return undef if !defined($raw);
1910 digest
=> Digest
::SHA
::sha1_hex
($raw),
1915 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1916 || die "got strange filename '$filename'";
1924 my @lines = split(/\n/, $raw);
1925 foreach my $line (@lines) {
1926 next if $line =~ m/^\s*$/;
1928 if ($line =~ m/^\[PENDING\]\s*$/i) {
1929 $section = 'pending';
1930 if (defined($descr)) {
1932 $conf->{description
} = $descr;
1935 $conf = $res->{$section} = {};
1938 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1940 if (defined($descr)) {
1942 $conf->{description
} = $descr;
1945 $conf = $res->{snapshots
}->{$section} = {};
1949 if ($line =~ m/^\#(.*)\s*$/) {
1950 $descr = '' if !defined($descr);
1951 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1955 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1956 $descr = '' if !defined($descr);
1957 $descr .= PVE
::Tools
::decode_text
($2);
1958 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1959 $conf->{snapstate
} = $1;
1960 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1963 $conf->{$key} = $value;
1964 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1966 if ($section eq 'pending') {
1967 $conf->{delete} = $value; # we parse this later
1969 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1971 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1974 eval { $value = check_type
($key, $value); };
1976 warn "vm $vmid - unable to parse value of '$key' - $@";
1978 my $fmt = $confdesc->{$key}->{format
};
1979 if ($fmt && $fmt eq 'pve-qm-drive') {
1980 my $v = parse_drive
($key, $value);
1981 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1982 $v->{file
} = $volid;
1983 $value = print_drive
($vmid, $v);
1985 warn "vm $vmid - unable to parse value of '$key'\n";
1990 if ($key eq 'cdrom') {
1991 $conf->{ide2
} = $value;
1993 $conf->{$key} = $value;
1999 if (defined($descr)) {
2001 $conf->{description
} = $descr;
2003 delete $res->{snapstate
}; # just to be sure
2008 sub write_vm_config
{
2009 my ($filename, $conf) = @_;
2011 delete $conf->{snapstate
}; # just to be sure
2013 if ($conf->{cdrom
}) {
2014 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2015 $conf->{ide2
} = $conf->{cdrom
};
2016 delete $conf->{cdrom
};
2019 # we do not use 'smp' any longer
2020 if ($conf->{sockets
}) {
2021 delete $conf->{smp
};
2022 } elsif ($conf->{smp
}) {
2023 $conf->{sockets
} = $conf->{smp
};
2024 delete $conf->{cores
};
2025 delete $conf->{smp
};
2028 my $used_volids = {};
2030 my $cleanup_config = sub {
2031 my ($cref, $pending, $snapname) = @_;
2033 foreach my $key (keys %$cref) {
2034 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2035 $key eq 'snapstate' || $key eq 'pending';
2036 my $value = $cref->{$key};
2037 if ($key eq 'delete') {
2038 die "propertry 'delete' is only allowed in [PENDING]\n"
2040 # fixme: check syntax?
2043 eval { $value = check_type
($key, $value); };
2044 die "unable to parse value of '$key' - $@" if $@;
2046 $cref->{$key} = $value;
2048 if (!$snapname && valid_drivename
($key)) {
2049 my $drive = parse_drive
($key, $value);
2050 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2055 &$cleanup_config($conf);
2057 &$cleanup_config($conf->{pending
}, 1);
2059 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2060 die "internal error" if $snapname eq 'pending';
2061 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2064 # remove 'unusedX' settings if we re-add a volume
2065 foreach my $key (keys %$conf) {
2066 my $value = $conf->{$key};
2067 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2068 delete $conf->{$key};
2072 my $generate_raw_config = sub {
2073 my ($conf, $pending) = @_;
2077 # add description as comment to top of file
2078 if (defined(my $descr = $conf->{description
})) {
2080 foreach my $cl (split(/\n/, $descr)) {
2081 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2084 $raw .= "#\n" if $pending;
2088 foreach my $key (sort keys %$conf) {
2089 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2090 $raw .= "$key: $conf->{$key}\n";
2095 my $raw = &$generate_raw_config($conf);
2097 if (scalar(keys %{$conf->{pending
}})){
2098 $raw .= "\n[PENDING]\n";
2099 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2102 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2103 $raw .= "\n[$snapname]\n";
2104 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2110 sub update_config_nolock
{
2111 my ($vmid, $conf, $skiplock) = @_;
2113 check_lock
($conf) if !$skiplock;
2115 my $cfspath = cfs_config_path
($vmid);
2117 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2121 my ($vmid, $conf, $skiplock) = @_;
2123 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2130 # we use static defaults from our JSON schema configuration
2131 foreach my $key (keys %$confdesc) {
2132 if (defined(my $default = $confdesc->{$key}->{default})) {
2133 $res->{$key} = $default;
2137 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2138 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2144 my $vmlist = PVE
::Cluster
::get_vmlist
();
2146 return $res if !$vmlist || !$vmlist->{ids
};
2147 my $ids = $vmlist->{ids
};
2149 foreach my $vmid (keys %$ids) {
2150 my $d = $ids->{$vmid};
2151 next if !$d->{node
} || $d->{node
} ne $nodename;
2152 next if !$d->{type
} || $d->{type
} ne 'qemu';
2153 $res->{$vmid}->{exists} = 1;
2158 # test if VM uses local resources (to prevent migration)
2159 sub check_local_resources
{
2160 my ($conf, $noerr) = @_;
2164 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2165 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2167 foreach my $k (keys %$conf) {
2168 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2169 # sockets are safe: they will recreated be on the target side post-migrate
2170 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2171 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2174 die "VM uses local resources\n" if $loc_res && !$noerr;
2179 # check if used storages are available on all nodes (use by migrate)
2180 sub check_storage_availability
{
2181 my ($storecfg, $conf, $node) = @_;
2183 foreach_drive
($conf, sub {
2184 my ($ds, $drive) = @_;
2186 my $volid = $drive->{file
};
2189 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2192 # check if storage is available on both nodes
2193 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2194 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2198 # list nodes where all VM images are available (used by has_feature API)
2200 my ($conf, $storecfg) = @_;
2202 my $nodelist = PVE
::Cluster
::get_nodelist
();
2203 my $nodehash = { map { $_ => 1 } @$nodelist };
2204 my $nodename = PVE
::INotify
::nodename
();
2206 foreach_drive
($conf, sub {
2207 my ($ds, $drive) = @_;
2209 my $volid = $drive->{file
};
2212 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2214 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2215 if ($scfg->{disable
}) {
2217 } elsif (my $avail = $scfg->{nodes
}) {
2218 foreach my $node (keys %$nodehash) {
2219 delete $nodehash->{$node} if !$avail->{$node};
2221 } elsif (!$scfg->{shared
}) {
2222 foreach my $node (keys %$nodehash) {
2223 delete $nodehash->{$node} if $node ne $nodename
2235 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2239 my ($pidfile, $pid) = @_;
2241 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2245 return undef if !$line;
2246 my @param = split(/\0/, $line);
2248 my $cmd = $param[0];
2249 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2251 for (my $i = 0; $i < scalar (@param); $i++) {
2254 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2255 my $p = $param[$i+1];
2256 return 1 if $p && ($p eq $pidfile);
2265 my ($vmid, $nocheck, $node) = @_;
2267 my $filename = config_file
($vmid, $node);
2269 die "unable to find configuration file for VM $vmid - no such machine\n"
2270 if !$nocheck && ! -f
$filename;
2272 my $pidfile = pidfile_name
($vmid);
2274 if (my $fd = IO
::File-
>new("<$pidfile")) {
2279 my $mtime = $st->mtime;
2280 if ($mtime > time()) {
2281 warn "file '$filename' modified in future\n";
2284 if ($line =~ m/^(\d+)$/) {
2286 if (check_cmdline
($pidfile, $pid)) {
2287 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2299 my $vzlist = config_list
();
2301 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2303 while (defined(my $de = $fd->read)) {
2304 next if $de !~ m/^(\d+)\.pid$/;
2306 next if !defined($vzlist->{$vmid});
2307 if (my $pid = check_running
($vmid)) {
2308 $vzlist->{$vmid}->{pid
} = $pid;
2316 my ($storecfg, $conf) = @_;
2318 my $bootdisk = $conf->{bootdisk
};
2319 return undef if !$bootdisk;
2320 return undef if !valid_drivename
($bootdisk);
2322 return undef if !$conf->{$bootdisk};
2324 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2325 return undef if !defined($drive);
2327 return undef if drive_is_cdrom
($drive);
2329 my $volid = $drive->{file
};
2330 return undef if !$volid;
2332 return $drive->{size
};
2335 my $last_proc_pid_stat;
2337 # get VM status information
2338 # This must be fast and should not block ($full == false)
2339 # We only query KVM using QMP if $full == true (this can be slow)
2341 my ($opt_vmid, $full) = @_;
2345 my $storecfg = PVE
::Storage
::config
();
2347 my $list = vzlist
();
2348 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2350 my $cpucount = $cpuinfo->{cpus
} || 1;
2352 foreach my $vmid (keys %$list) {
2353 next if $opt_vmid && ($vmid ne $opt_vmid);
2355 my $cfspath = cfs_config_path
($vmid);
2356 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2359 $d->{pid
} = $list->{$vmid}->{pid
};
2361 # fixme: better status?
2362 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2364 my $size = disksize
($storecfg, $conf);
2365 if (defined($size)) {
2366 $d->{disk
} = 0; # no info available
2367 $d->{maxdisk
} = $size;
2373 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2374 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2375 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2377 $d->{name
} = $conf->{name
} || "VM $vmid";
2378 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2380 if ($conf->{balloon
}) {
2381 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2382 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2393 $d->{diskwrite
} = 0;
2395 $d->{template
} = is_template
($conf);
2400 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2401 foreach my $dev (keys %$netdev) {
2402 next if $dev !~ m/^tap([1-9]\d*)i/;
2404 my $d = $res->{$vmid};
2407 $d->{netout
} += $netdev->{$dev}->{receive
};
2408 $d->{netin
} += $netdev->{$dev}->{transmit
};
2411 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2412 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2417 my $ctime = gettimeofday
;
2419 foreach my $vmid (keys %$list) {
2421 my $d = $res->{$vmid};
2422 my $pid = $d->{pid
};
2425 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2426 next if !$pstat; # not running
2428 my $used = $pstat->{utime} + $pstat->{stime
};
2430 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2432 if ($pstat->{vsize
}) {
2433 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2436 my $old = $last_proc_pid_stat->{$pid};
2438 $last_proc_pid_stat->{$pid} = {
2446 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2448 if ($dtime > 1000) {
2449 my $dutime = $used - $old->{used
};
2451 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2452 $last_proc_pid_stat->{$pid} = {
2458 $d->{cpu
} = $old->{cpu
};
2462 return $res if !$full;
2464 my $qmpclient = PVE
::QMPClient-
>new();
2466 my $ballooncb = sub {
2467 my ($vmid, $resp) = @_;
2469 my $info = $resp->{'return'};
2470 return if !$info->{max_mem
};
2472 my $d = $res->{$vmid};
2474 # use memory assigned to VM
2475 $d->{maxmem
} = $info->{max_mem
};
2476 $d->{balloon
} = $info->{actual
};
2478 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2479 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2480 $d->{freemem
} = $info->{free_mem
};
2483 $d->{ballooninfo
} = $info;
2486 my $blockstatscb = sub {
2487 my ($vmid, $resp) = @_;
2488 my $data = $resp->{'return'} || [];
2489 my $totalrdbytes = 0;
2490 my $totalwrbytes = 0;
2492 for my $blockstat (@$data) {
2493 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2494 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2496 $blockstat->{device
} =~ s/drive-//;
2497 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2499 $res->{$vmid}->{diskread
} = $totalrdbytes;
2500 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2503 my $statuscb = sub {
2504 my ($vmid, $resp) = @_;
2506 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2507 # this fails if ballon driver is not loaded, so this must be
2508 # the last commnand (following command are aborted if this fails).
2509 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2511 my $status = 'unknown';
2512 if (!defined($status = $resp->{'return'}->{status
})) {
2513 warn "unable to get VM status\n";
2517 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2520 foreach my $vmid (keys %$list) {
2521 next if $opt_vmid && ($vmid ne $opt_vmid);
2522 next if !$res->{$vmid}->{pid
}; # not running
2523 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2526 $qmpclient->queue_execute(undef, 1);
2528 foreach my $vmid (keys %$list) {
2529 next if $opt_vmid && ($vmid ne $opt_vmid);
2530 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2537 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2540 my $current_size = 1024;
2541 my $dimm_size = 512;
2542 return if $current_size == $memory;
2544 for (my $j = 0; $j < 8; $j++) {
2545 for (my $i = 0; $i < 32; $i++) {
2546 my $name = "dimm${dimm_id}";
2548 my $numanode = $i % $sockets;
2549 $current_size += $dimm_size;
2550 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2551 return $current_size if $current_size >= $memory;
2557 sub foreach_reverse_dimm
{
2558 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2561 my $current_size = 4177920;
2562 my $dimm_size = 65536;
2563 return if $current_size == $memory;
2565 for (my $j = 0; $j < 8; $j++) {
2566 for (my $i = 0; $i < 32; $i++) {
2567 my $name = "dimm${dimm_id}";
2569 my $numanode = $i % $sockets;
2570 $current_size -= $dimm_size;
2571 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2572 return $current_size if $current_size <= $memory;
2579 my ($conf, $func) = @_;
2581 foreach my $ds (keys %$conf) {
2582 next if !valid_drivename
($ds);
2584 my $drive = parse_drive
($ds, $conf->{$ds});
2587 &$func($ds, $drive);
2592 my ($conf, $func) = @_;
2596 my $test_volid = sub {
2597 my ($volid, $is_cdrom) = @_;
2601 $volhash->{$volid} = $is_cdrom || 0;
2604 foreach_drive
($conf, sub {
2605 my ($ds, $drive) = @_;
2606 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2609 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2610 my $snap = $conf->{snapshots
}->{$snapname};
2611 &$test_volid($snap->{vmstate
}, 0);
2612 foreach_drive
($snap, sub {
2613 my ($ds, $drive) = @_;
2614 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2618 foreach my $volid (keys %$volhash) {
2619 &$func($volid, $volhash->{$volid});
2623 sub vga_conf_has_spice
{
2626 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2631 sub config_to_command
{
2632 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2635 my $globalFlags = [];
2636 my $machineFlags = [];
2642 my $kvmver = kvm_user_version
();
2643 my $vernum = 0; # unknown
2644 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2645 $vernum = $1*1000000+$2*1000;
2646 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2647 $vernum = $1*1000000+$2*1000+$3;
2650 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2652 my $have_ovz = -f
'/proc/vz/vestat';
2654 my $q35 = machine_type_is_q35
($conf);
2655 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2656 my $machine_type = $forcemachine || $conf->{machine
};
2657 my $use_old_bios_files = undef;
2658 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2660 my $cpuunits = defined($conf->{cpuunits
}) ?
2661 $conf->{cpuunits
} : $defaults->{cpuunits
};
2663 push @$cmd, '/usr/bin/systemd-run';
2664 push @$cmd, '--scope';
2665 push @$cmd, '--slice', "qemu";
2666 push @$cmd, '--unit', $vmid;
2667 # set KillMode=none, so that systemd don't kill those scopes
2668 # at shutdown (pve-manager service should stop the VMs instead)
2669 push @$cmd, '-p', "KillMode=none";
2670 push @$cmd, '-p', "CPUShares=$cpuunits";
2671 if ($conf->{cpulimit
}) {
2672 my $cpulimit = int($conf->{cpulimit
} * 100);
2673 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2676 push @$cmd, '/usr/bin/kvm';
2678 push @$cmd, '-id', $vmid;
2682 my $qmpsocket = qmp_socket
($vmid);
2683 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2684 push @$cmd, '-mon', "chardev=qmp,mode=control";
2686 my $socket = vnc_socket
($vmid);
2687 push @$cmd, '-vnc', "unix:$socket,x509,password";
2689 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2691 push @$cmd, '-daemonize';
2693 if ($conf->{smbios1
}) {
2694 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2697 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2698 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2699 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2700 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2701 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2702 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2703 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2707 # the q35 chipset support native usb2, so we enable usb controller
2708 # by default for this machine type
2709 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2711 $pciaddr = print_pci_addr
("piix3", $bridges);
2712 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2715 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2716 next if !$conf->{"usb$i"};
2719 # include usb device config
2720 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2723 my $vga = $conf->{vga
};
2725 my $qxlnum = vga_conf_has_spice
($vga);
2726 $vga = 'qxl' if $qxlnum;
2729 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2730 $conf->{ostype
} eq 'win7' ||
2731 $conf->{ostype
} eq 'w2k8')) {
2738 # enable absolute mouse coordinates (needed by vnc)
2740 if (defined($conf->{tablet
})) {
2741 $tablet = $conf->{tablet
};
2743 $tablet = $defaults->{tablet
};
2744 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2745 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2748 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2751 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2752 my $d = parse_hostpci
($conf->{"hostpci$i"});
2755 my $pcie = $d->{pcie
};
2757 die "q35 machine model is not enabled" if !$q35;
2758 $pciaddr = print_pcie_addr
("hostpci$i");
2760 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2763 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2764 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2765 if ($xvga && $xvga ne '') {
2766 push @$cpuFlags, 'kvm=off';
2769 my $pcidevices = $d->{pciid
};
2770 my $multifunction = 1 if @$pcidevices > 1;
2773 foreach my $pcidevice (@$pcidevices) {
2775 my $id = "hostpci$i";
2776 $id .= ".$j" if $multifunction;
2777 my $addr = $pciaddr;
2778 $addr .= ".$j" if $multifunction;
2779 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2782 $devicestr .= "$rombar$xvga";
2783 $devicestr .= ",multifunction=on" if $multifunction;
2786 push @$devices, '-device', $devicestr;
2792 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2793 my $d = parse_usb_device
($conf->{"usb$i"});
2795 if ($d->{vendorid
} && $d->{productid
}) {
2796 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2797 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2798 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2799 } elsif ($d->{spice
}) {
2800 # usb redir support for spice
2801 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2802 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2807 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2808 if (my $path = $conf->{"serial$i"}) {
2809 if ($path eq 'socket') {
2810 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2811 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2812 push @$devices, '-device', "isa-serial,chardev=serial$i";
2814 die "no such serial device\n" if ! -c
$path;
2815 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2816 push @$devices, '-device', "isa-serial,chardev=serial$i";
2822 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2823 if (my $path = $conf->{"parallel$i"}) {
2824 die "no such parallel device\n" if ! -c
$path;
2825 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2826 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2827 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2831 my $vmname = $conf->{name
} || "vm$vmid";
2833 push @$cmd, '-name', $vmname;
2836 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2837 $sockets = $conf->{sockets
} if $conf->{sockets
};
2839 my $cores = $conf->{cores
} || 1;
2841 my $maxcpus = $sockets * $cores;
2843 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2845 my $allowed_vcpus = $cpuinfo->{cpus
};
2847 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2848 if ($allowed_vcpus < $maxcpus);
2850 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2852 push @$cmd, '-nodefaults';
2854 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2856 my $bootindex_hash = {};
2858 foreach my $o (split(//, $bootorder)) {
2859 $bootindex_hash->{$o} = $i*100;
2863 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2865 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2867 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2869 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2872 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2874 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2875 my $useLocaltime = $conf->{localtime};
2877 if (my $ost = $conf->{ostype
}) {
2878 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2880 if ($ost =~ m/^w/) { # windows
2881 $useLocaltime = 1 if !defined($conf->{localtime});
2883 # use time drift fix when acpi is enabled
2884 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2885 $tdf = 1 if !defined($conf->{tdf
});
2889 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2891 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2892 push @$cmd, '-no-hpet';
2893 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2894 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2895 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2896 push @$cpuFlags , 'hv_time' if !$nokvm;
2899 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2903 if ($ost eq 'win7' || $ost eq 'win8') {
2904 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2908 push @$rtcFlags, 'driftfix=slew' if $tdf;
2911 push @$machineFlags, 'accel=tcg';
2913 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2916 if ($machine_type) {
2917 push @$machineFlags, "type=${machine_type}";
2920 if ($conf->{startdate
}) {
2921 push @$rtcFlags, "base=$conf->{startdate}";
2922 } elsif ($useLocaltime) {
2923 push @$rtcFlags, 'base=localtime';
2926 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2927 $cpu = $conf->{cpu
} if $conf->{cpu
};
2929 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2931 push @$cpuFlags , '-x2apic'
2932 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2934 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2936 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2938 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2940 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2941 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2944 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2946 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2948 push @$cmd, '-cpu', $cpu;
2950 my $memory = $conf->{memory
} || $defaults->{memory
};
2951 my $static_memory = 0;
2952 my $dimm_memory = 0;
2954 if ($hotplug_features->{memory
}) {
2955 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2956 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2957 $static_memory = $STATICMEM;
2958 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2959 $dimm_memory = $memory - $static_memory;
2960 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2964 $static_memory = $memory;
2965 push @$cmd, '-m', $static_memory;
2968 if ($conf->{numa
}) {
2970 my $numa_totalmemory = undef;
2971 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2972 next if !$conf->{"numa$i"};
2973 my $numa = parse_numa
($conf->{"numa$i"});
2976 die "missing numa node$i memory value\n" if !$numa->{memory
};
2977 my $numa_memory = $numa->{memory
};
2978 $numa_totalmemory += $numa_memory;
2979 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2982 my $cpus_start = $numa->{cpus
}->{start
};
2983 die "missing numa node$i cpus\n" if !defined($cpus_start);
2984 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2985 my $cpus = $cpus_start;
2986 if (defined($cpus_end)) {
2987 $cpus .= "-$cpus_end";
2988 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2992 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2993 if (defined($hostnodes_start)) {
2994 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2995 my $hostnodes = $hostnodes_start;
2996 if (defined($hostnodes_end)) {
2997 $hostnodes .= "-$hostnodes_end";
2998 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3001 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3002 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3003 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3007 my $policy = $numa->{policy
};
3008 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3009 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3012 push @$cmd, '-object', $numa_object;
3013 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3016 die "total memory for NUMA nodes must be equal to vm static memory\n"
3017 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3019 #if no custom tology, we split memory and cores across numa nodes
3020 if(!$numa_totalmemory) {
3022 my $numa_memory = ($static_memory / $sockets) . "M";
3024 for (my $i = 0; $i < $sockets; $i++) {
3026 my $cpustart = ($cores * $i);
3027 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3028 my $cpus = $cpustart;
3029 $cpus .= "-$cpuend" if $cpuend;
3031 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3032 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3037 if ($hotplug_features->{memory
}) {
3038 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3039 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3040 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3041 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3043 #if dimm_memory is not aligned to dimm map
3044 if($current_size > $memory) {
3045 $conf->{memory
} = $current_size;
3046 update_config_nolock
($vmid, $conf, 1);
3051 push @$cmd, '-S' if $conf->{freeze
};
3053 # set keyboard layout
3054 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3055 push @$cmd, '-k', $kb if $kb;
3058 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3059 #push @$cmd, '-soundhw', 'es1370';
3060 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3062 if($conf->{agent
}) {
3063 my $qgasocket = qmp_socket
($vmid, 1);
3064 my $pciaddr = print_pci_addr
("qga0", $bridges);
3065 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3066 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3067 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3074 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3075 for(my $i = 1; $i < $qxlnum; $i++){
3076 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3077 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3080 # assume other OS works like Linux
3081 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3082 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3086 my $pciaddr = print_pci_addr
("spice", $bridges);
3088 my $nodename = PVE
::INotify
::nodename
();
3089 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3090 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3092 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3094 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3095 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3096 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3099 # enable balloon by default, unless explicitly disabled
3100 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3101 $pciaddr = print_pci_addr
("balloon0", $bridges);
3102 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3105 if ($conf->{watchdog
}) {
3106 my $wdopts = parse_watchdog
($conf->{watchdog
});
3107 $pciaddr = print_pci_addr
("watchdog", $bridges);
3108 my $watchdog = $wdopts->{model
} || 'i6300esb';
3109 push @$devices, '-device', "$watchdog$pciaddr";
3110 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3114 my $scsicontroller = {};
3115 my $ahcicontroller = {};
3116 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3118 # Add iscsi initiator name if available
3119 if (my $initiator = get_initiator_name
()) {
3120 push @$devices, '-iscsi', "initiator-name=$initiator";
3123 foreach_drive
($conf, sub {
3124 my ($ds, $drive) = @_;
3126 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3127 push @$vollist, $drive->{file
};
3130 $use_virtio = 1 if $ds =~ m/^virtio/;
3132 if (drive_is_cdrom
($drive)) {
3133 if ($bootindex_hash->{d
}) {
3134 $drive->{bootindex
} = $bootindex_hash->{d
};
3135 $bootindex_hash->{d
} += 1;
3138 if ($bootindex_hash->{c
}) {
3139 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3140 $bootindex_hash->{c
} += 1;
3144 if($drive->{interface
} eq 'virtio'){
3145 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3148 if ($drive->{interface
} eq 'scsi') {
3150 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3152 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3153 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3156 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3157 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3158 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3162 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3163 $queues = ",num_queues=$drive->{queues}";
3166 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3167 $scsicontroller->{$controller}=1;
3170 if ($drive->{interface
} eq 'sata') {
3171 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3172 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3173 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3174 $ahcicontroller->{$controller}=1;
3177 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3178 push @$devices, '-drive',$drive_cmd;
3179 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3182 for (my $i = 0; $i < $MAX_NETS; $i++) {
3183 next if !$conf->{"net$i"};
3184 my $d = parse_net
($conf->{"net$i"});
3187 $use_virtio = 1 if $d->{model
} eq 'virtio';
3189 if ($bootindex_hash->{n
}) {
3190 $d->{bootindex
} = $bootindex_hash->{n
};
3191 $bootindex_hash->{n
} += 1;
3194 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3195 push @$devices, '-netdev', $netdevfull;
3197 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3198 push @$devices, '-device', $netdevicefull;
3203 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3208 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3210 while (my ($k, $v) = each %$bridges) {
3211 $pciaddr = print_pci_addr
("pci.$k");
3212 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3217 if ($conf->{args
}) {
3218 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3222 push @$cmd, @$devices;
3223 push @$cmd, '-rtc', join(',', @$rtcFlags)
3224 if scalar(@$rtcFlags);
3225 push @$cmd, '-machine', join(',', @$machineFlags)
3226 if scalar(@$machineFlags);
3227 push @$cmd, '-global', join(',', @$globalFlags)
3228 if scalar(@$globalFlags);
3230 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3235 return "${var_run_tmpdir}/$vmid.vnc";
3241 my $res = vm_mon_cmd
($vmid, 'query-spice');
3243 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3247 my ($vmid, $qga) = @_;
3248 my $sockettype = $qga ?
'qga' : 'qmp';
3249 return "${var_run_tmpdir}/$vmid.$sockettype";
3254 return "${var_run_tmpdir}/$vmid.pid";
3257 sub vm_devices_list
{
3260 my $res = vm_mon_cmd
($vmid, 'query-pci');
3262 foreach my $pcibus (@$res) {
3263 foreach my $device (@{$pcibus->{devices
}}) {
3264 next if !$device->{'qdev_id'};
3265 if ($device->{'pci_bridge'}) {
3266 $devices->{$device->{'qdev_id'}} = 1;
3267 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3268 next if !$bridge_device->{'qdev_id'};
3269 $devices->{$bridge_device->{'qdev_id'}} = 1;
3270 $devices->{$device->{'qdev_id'}}++;
3273 $devices->{$device->{'qdev_id'}} = 1;
3278 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3279 foreach my $block (@$resblock) {
3280 if($block->{device
} =~ m/^drive-(\S+)/){
3285 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3286 foreach my $mice (@$resmice) {
3287 if ($mice->{name
} eq 'QEMU HID Tablet') {
3288 $devices->{tablet
} = 1;
3297 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3299 my $q35 = machine_type_is_q35
($conf);
3301 my $devices_list = vm_devices_list
($vmid);
3302 return 1 if defined($devices_list->{$deviceid});
3304 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3306 if ($deviceid eq 'tablet') {
3308 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3310 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3312 qemu_iothread_add
($vmid, $deviceid, $device);
3314 qemu_driveadd
($storecfg, $vmid, $device);
3315 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3317 qemu_deviceadd
($vmid, $devicefull);
3318 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3320 eval { qemu_drivedel
($vmid, $deviceid); };
3325 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3328 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3329 my $pciaddr = print_pci_addr
($deviceid);
3330 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3332 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3334 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3335 qemu_iothread_add
($vmid, $deviceid, $device);
3336 $devicefull .= ",iothread=iothread-$deviceid";
3339 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3340 $devicefull .= ",num_queues=$device->{queues}";
3343 qemu_deviceadd
($vmid, $devicefull);
3344 qemu_deviceaddverify
($vmid, $deviceid);
3346 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3348 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3349 qemu_driveadd
($storecfg, $vmid, $device);
3351 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3352 eval { qemu_deviceadd
($vmid, $devicefull); };
3354 eval { qemu_drivedel
($vmid, $deviceid); };
3359 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3361 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3363 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3364 my $use_old_bios_files = undef;
3365 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3367 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3368 qemu_deviceadd
($vmid, $netdevicefull);
3369 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3371 eval { qemu_netdevdel
($vmid, $deviceid); };
3376 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3379 my $pciaddr = print_pci_addr
($deviceid);
3380 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3382 qemu_deviceadd
($vmid, $devicefull);
3383 qemu_deviceaddverify
($vmid, $deviceid);
3386 die "can't hotplug device '$deviceid'\n";
3392 # fixme: this should raise exceptions on error!
3393 sub vm_deviceunplug
{
3394 my ($vmid, $conf, $deviceid) = @_;
3396 my $devices_list = vm_devices_list
($vmid);
3397 return 1 if !defined($devices_list->{$deviceid});
3399 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3401 if ($deviceid eq 'tablet') {
3403 qemu_devicedel
($vmid, $deviceid);
3405 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3407 qemu_devicedel
($vmid, $deviceid);
3408 qemu_devicedelverify
($vmid, $deviceid);
3409 qemu_drivedel
($vmid, $deviceid);
3410 qemu_iothread_del
($conf, $vmid, $deviceid);
3412 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3414 qemu_devicedel
($vmid, $deviceid);
3415 qemu_devicedelverify
($vmid, $deviceid);
3416 qemu_iothread_del
($conf, $vmid, $deviceid);
3418 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3420 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3421 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3422 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3424 qemu_devicedel
($vmid, $deviceid);
3425 qemu_drivedel
($vmid, $deviceid);
3426 qemu_deletescsihw
($conf, $vmid, $deviceid);
3428 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3430 qemu_devicedel
($vmid, $deviceid);
3431 qemu_devicedelverify
($vmid, $deviceid);
3432 qemu_netdevdel
($vmid, $deviceid);
3435 die "can't unplug device '$deviceid'\n";
3441 sub qemu_deviceadd
{
3442 my ($vmid, $devicefull) = @_;
3444 $devicefull = "driver=".$devicefull;
3445 my %options = split(/[=,]/, $devicefull);
3447 vm_mon_cmd
($vmid, "device_add" , %options);
3450 sub qemu_devicedel
{
3451 my ($vmid, $deviceid) = @_;
3453 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3456 sub qemu_iothread_add
{
3457 my($vmid, $deviceid, $device) = @_;
3459 if ($device->{iothread
}) {
3460 my $iothreads = vm_iothreads_list
($vmid);
3461 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3465 sub qemu_iothread_del
{
3466 my($conf, $vmid, $deviceid) = @_;
3468 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3469 if ($device->{iothread
}) {
3470 my $iothreads = vm_iothreads_list
($vmid);
3471 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3475 sub qemu_objectadd
{
3476 my($vmid, $objectid, $qomtype) = @_;
3478 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3483 sub qemu_objectdel
{
3484 my($vmid, $objectid) = @_;
3486 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3492 my ($storecfg, $vmid, $device) = @_;
3494 my $drive = print_drive_full
($storecfg, $vmid, $device);
3495 $drive =~ s/\\/\\\\/g;
3496 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3498 # If the command succeeds qemu prints: "OK
"
3499 return 1 if $ret =~ m/OK/s;
3501 die "adding drive failed
: $ret\n";
3505 my($vmid, $deviceid) = @_;
3507 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3510 return 1 if $ret eq "";
3512 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3513 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3515 die "deleting drive
$deviceid failed
: $ret\n";
3518 sub qemu_deviceaddverify {
3519 my ($vmid, $deviceid) = @_;
3521 for (my $i = 0; $i <= 5; $i++) {
3522 my $devices_list = vm_devices_list($vmid);
3523 return 1 if defined($devices_list->{$deviceid});
3527 die "error on hotplug device
'$deviceid'\n";
3531 sub qemu_devicedelverify {
3532 my ($vmid, $deviceid) = @_;
3534 # need to verify that the device is correctly removed as device_del
3535 # is async and empty return is not reliable
3537 for (my $i = 0; $i <= 5; $i++) {
3538 my $devices_list = vm_devices_list($vmid);
3539 return 1 if !defined($devices_list->{$deviceid});
3543 die "error on hot-unplugging device
'$deviceid'\n";
3546 sub qemu_findorcreatescsihw {
3547 my ($storecfg, $conf, $vmid, $device) = @_;
3549 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3551 my $scsihwid="$controller_prefix$controller";
3552 my $devices_list = vm_devices_list($vmid);
3554 if(!defined($devices_list->{$scsihwid})) {
3555 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3561 sub qemu_deletescsihw {
3562 my ($conf, $vmid, $opt) = @_;
3564 my $device = parse_drive($opt, $conf->{$opt});
3566 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3567 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3571 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3573 my $devices_list = vm_devices_list($vmid);
3574 foreach my $opt (keys %{$devices_list}) {
3575 if (PVE::QemuServer::valid_drivename($opt)) {
3576 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3577 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3583 my $scsihwid="scsihw
$controller";
3585 vm_deviceunplug($vmid, $conf, $scsihwid);
3590 sub qemu_add_pci_bridge {
3591 my ($storecfg, $conf, $vmid, $device) = @_;
3597 print_pci_addr($device, $bridges);
3599 while (my ($k, $v) = each %$bridges) {
3602 return 1 if !defined($bridgeid) || $bridgeid < 1;
3604 my $bridge = "pci
.$bridgeid";
3605 my $devices_list = vm_devices_list($vmid);
3607 if (!defined($devices_list->{$bridge})) {
3608 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3614 sub qemu_set_link_status {
3615 my ($vmid, $device, $up) = @_;
3617 vm_mon_cmd($vmid, "set_link
", name => $device,
3618 up => $up ? JSON::true : JSON::false);
3621 sub qemu_netdevadd {
3622 my ($vmid, $conf, $device, $deviceid) = @_;
3624 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3625 my %options = split(/[=,]/, $netdev);
3627 vm_mon_cmd($vmid, "netdev_add
", %options);
3631 sub qemu_netdevdel {
3632 my ($vmid, $deviceid) = @_;
3634 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3637 sub qemu_cpu_hotplug {
3638 my ($vmid, $conf, $vcpus) = @_;
3641 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3642 $sockets = $conf->{sockets} if $conf->{sockets};
3643 my $cores = $conf->{cores} || 1;
3644 my $maxcpus = $sockets * $cores;
3646 $vcpus = $maxcpus if !$vcpus;
3648 die "you can
't add more vcpus than maxcpus\n"
3649 if $vcpus > $maxcpus;
3651 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3652 die "online cpu unplug is not yet possible\n"
3653 if $vcpus < $currentvcpus;
3655 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3656 die "vcpus in running vm is different than configuration\n"
3657 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3659 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3660 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3664 sub qemu_memory_hotplug {
3665 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3667 return $value if !check_running($vmid);
3669 my $memory = $conf->{memory} || $defaults->{memory};
3670 $value = $defaults->{memory} if !$value;
3671 return $value if $value == $memory;
3673 my $static_memory = $STATICMEM;
3674 my $dimm_memory = $memory - $static_memory;
3676 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3677 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3681 $sockets = $conf->{sockets} if $conf->{sockets};
3683 if($value > $memory) {
3685 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3686 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3688 return if $current_size <= $conf->{memory};
3690 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3692 eval { qemu_objectdel($vmid, "mem-
$name"); };
3696 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3698 eval { qemu_objectdel($vmid, "mem-
$name"); };
3701 #update conf after each succesful module hotplug
3702 $conf->{memory} = $current_size;
3703 update_config_nolock($vmid, $conf, 1);
3708 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3709 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3711 return if $current_size >= $conf->{memory};
3712 print "try to unplug memory dimm
$name\n";
3716 eval { qemu_devicedel($vmid, $name) };
3718 my $dimm_list = qemu_dimm_list($vmid);
3719 last if !$dimm_list->{$name};
3720 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3724 #update conf after each succesful module unplug
3725 $conf->{memory} = $current_size;
3727 eval { qemu_objectdel($vmid, "mem-
$name"); };
3728 update_config_nolock($vmid, $conf, 1);
3733 sub qemu_dimm_list {
3736 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3739 foreach my $dimm (@$dimmarray) {
3741 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3742 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3743 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3744 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3745 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3750 sub qemu_block_set_io_throttle {
3751 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3753 return if !check_running($vmid) ;
3755 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));
3759 # old code, only used to shutdown old VM after update
3761 my ($fh, $timeout) = @_;
3763 my $sel = new IO::Select;
3770 while (scalar (@ready = $sel->can_read($timeout))) {
3772 if ($count = $fh->sysread($buf, 8192)) {
3773 if ($buf =~ /^(.*)\(qemu\) $/s) {
3780 if (!defined($count)) {
3787 die "monitor
read timeout
\n" if !scalar(@ready);
3792 # old code, only used to shutdown old VM after update
3793 sub vm_monitor_command {
3794 my ($vmid, $cmdstr, $nocheck) = @_;
3799 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3801 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3803 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3804 die "unable to
connect to VM
$vmid socket - $!\n";
3808 # hack: migrate sometime blocks the monitor (when migrate_downtime
3810 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3811 $timeout = 60*60; # 1 hour
3815 my $data = __read_avail($sock, $timeout);
3817 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3818 die "got unexpected qemu monitor banner
\n";
3821 my $sel = new IO::Select;
3824 if (!scalar(my @ready = $sel->can_write($timeout))) {
3825 die "monitor
write error
- timeout
";
3828 my $fullcmd = "$cmdstr\r";
3830 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3833 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3834 die "monitor
write error
- $!";
3837 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3841 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3842 $timeout = 60*60; # 1 hour
3843 } elsif ($cmdstr =~ m/^(eject|change)/) {
3844 $timeout = 60; # note: cdrom mount command is slow
3846 if ($res = __read_avail($sock, $timeout)) {
3848 my @lines = split("\r?
\n", $res);
3850 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3852 $res = join("\n", @lines);
3860 syslog("err
", "VM
$vmid monitor command failed
- $err");
3867 sub qemu_block_resize {
3868 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3870 my $running = check_running($vmid);
3872 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3874 return if !$running;
3876 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3880 sub qemu_volume_snapshot {
3881 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3883 my $running = check_running($vmid);
3885 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3886 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3888 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3892 sub qemu_volume_snapshot_delete {
3893 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3895 my $running = check_running($vmid);
3897 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3899 return if !$running;
3901 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3904 sub set_migration_caps {
3910 "auto-converge
" => 1,
3912 "x-rdma-pin-all
" => 0,
3917 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3919 for my $supported_capability (@$supported_capabilities) {
3921 capability => $supported_capability->{capability},
3922 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3926 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3929 my $fast_plug_option = {
3938 # hotplug changes in [PENDING]
3939 # $selection hash can be used to only apply specified options, for
3940 # example: { cores => 1 } (only apply changed 'cores')
3941 # $errors ref is used to return error messages
3942 sub vmconfig_hotplug_pending {
3943 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3945 my $defaults = load_defaults();
3947 # commit values which do not have any impact on running VM first
3948 # Note: those option cannot raise errors, we we do not care about
3949 # $selection and always apply them.
3951 my $add_error = sub {
3952 my ($opt, $msg) = @_;
3953 $errors->{$opt} = "hotplug problem
- $msg";
3957 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3958 if ($fast_plug_option->{$opt}) {
3959 $conf->{$opt} = $conf->{pending}->{$opt};
3960 delete $conf->{pending}->{$opt};
3966 update_config_nolock($vmid, $conf, 1);
3967 $conf = load_config($vmid); # update/reload
3970 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3972 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3973 while (my ($opt, $force) = each %$pending_delete_hash) {
3974 next if $selection && !$selection->{$opt};
3976 if ($opt eq 'hotplug') {
3977 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3978 } elsif ($opt eq 'tablet') {
3979 die "skip
\n" if !$hotplug_features->{usb};
3980 if ($defaults->{tablet}) {
3981 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3983 vm_deviceunplug($vmid, $conf, $opt);
3985 } elsif ($opt eq 'vcpus') {
3986 die "skip
\n" if !$hotplug_features->{cpu};
3987 qemu_cpu_hotplug($vmid, $conf, undef);
3988 } elsif ($opt eq 'balloon') {
3989 # enable balloon device is not hotpluggable
3990 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3991 } elsif ($fast_plug_option->{$opt}) {
3993 } elsif ($opt =~ m/^net(\d+)$/) {
3994 die "skip
\n" if !$hotplug_features->{network};
3995 vm_deviceunplug($vmid, $conf, $opt);
3996 } elsif (valid_drivename($opt)) {
3997 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3998 vm_deviceunplug($vmid, $conf, $opt);
3999 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4000 } elsif ($opt =~ m/^memory$/) {
4001 die "skip
\n" if !$hotplug_features->{memory};
4002 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4003 } elsif ($opt eq 'cpuunits') {
4004 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4005 } elsif ($opt eq 'cpulimit') {
4006 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4012 &$add_error($opt, $err) if $err ne "skip
\n";
4014 # save new config if hotplug was successful
4015 delete $conf->{$opt};
4016 vmconfig_undelete_pending_option($conf, $opt);
4017 update_config_nolock($vmid, $conf, 1);
4018 $conf = load_config($vmid); # update/reload
4022 foreach my $opt (keys %{$conf->{pending}}) {
4023 next if $selection && !$selection->{$opt};
4024 my $value = $conf->{pending}->{$opt};
4026 if ($opt eq 'hotplug') {
4027 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4028 } elsif ($opt eq 'tablet') {
4029 die "skip
\n" if !$hotplug_features->{usb};
4031 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4032 } elsif ($value == 0) {
4033 vm_deviceunplug($vmid, $conf, $opt);
4035 } elsif ($opt eq 'vcpus') {
4036 die "skip
\n" if !$hotplug_features->{cpu};
4037 qemu_cpu_hotplug($vmid, $conf, $value);
4038 } elsif ($opt eq 'balloon') {
4039 # enable/disable balloning device is not hotpluggable
4040 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4041 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4042 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4044 # allow manual ballooning if shares is set to zero
4045 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4046 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4047 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4049 } elsif ($opt =~ m/^net(\d+)$/) {
4050 # some changes can be done without hotplug
4051 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4052 $vmid, $opt, $value);
4053 } elsif (valid_drivename($opt)) {
4054 # some changes can be done without hotplug
4055 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4056 $vmid, $opt, $value, 1);
4057 } elsif ($opt =~ m/^memory$/) { #dimms
4058 die "skip
\n" if !$hotplug_features->{memory};
4059 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4060 } elsif ($opt eq 'cpuunits') {
4061 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4062 } elsif ($opt eq 'cpulimit') {
4063 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4064 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4066 die "skip
\n"; # skip non-hot-pluggable options
4070 &$add_error($opt, $err) if $err ne "skip
\n";
4072 # save new config if hotplug was successful
4073 $conf->{$opt} = $value;
4074 delete $conf->{pending}->{$opt};
4075 update_config_nolock($vmid, $conf, 1);
4076 $conf = load_config($vmid); # update/reload
4081 sub try_deallocate_drive {
4082 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4084 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4085 my $volid = $drive->{file};
4086 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4087 my $sid = PVE::Storage::parse_volume_id($volid);
4088 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4090 # check if the disk is really unused
4091 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4092 if is_volume_in_use($storecfg, $conf, $key, $volid);
4093 PVE::Storage::vdisk_free($storecfg, $volid);
4096 # If vm is not owner of this disk remove from config
4104 sub vmconfig_delete_or_detach_drive {
4105 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4107 my $drive = parse_drive($opt, $conf->{$opt});
4109 my $rpcenv = PVE::RPCEnvironment::get();
4110 my $authuser = $rpcenv->get_user();
4113 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4114 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4116 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4120 sub vmconfig_apply_pending {
4121 my ($vmid, $conf, $storecfg) = @_;
4125 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4126 while (my ($opt, $force) = each %$pending_delete_hash) {
4127 die "internal error
" if $opt =~ m/^unused/;
4128 $conf = load_config($vmid); # update/reload
4129 if (!defined($conf->{$opt})) {
4130 vmconfig_undelete_pending_option($conf, $opt);
4131 update_config_nolock($vmid, $conf, 1);
4132 } elsif (valid_drivename($opt)) {
4133 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4134 vmconfig_undelete_pending_option($conf, $opt);
4135 delete $conf->{$opt};
4136 update_config_nolock($vmid, $conf, 1);
4138 vmconfig_undelete_pending_option($conf, $opt);
4139 delete $conf->{$opt};
4140 update_config_nolock($vmid, $conf, 1);
4144 $conf = load_config($vmid); # update/reload
4146 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4147 $conf = load_config($vmid); # update/reload
4149 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4150 # skip if nothing changed
4151 } elsif (valid_drivename($opt)) {
4152 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4153 if defined($conf->{$opt});
4154 $conf->{$opt} = $conf->{pending}->{$opt};
4156 $conf->{$opt} = $conf->{pending}->{$opt};
4159 delete $conf->{pending}->{$opt};
4160 update_config_nolock($vmid, $conf, 1);
4164 my $safe_num_ne = sub {
4167 return 0 if !defined($a) && !defined($b);
4168 return 1 if !defined($a);
4169 return 1 if !defined($b);
4174 my $safe_string_ne = sub {
4177 return 0 if !defined($a) && !defined($b);
4178 return 1 if !defined($a);
4179 return 1 if !defined($b);
4184 sub vmconfig_update_net {
4185 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4187 my $newnet = parse_net($value);
4189 if ($conf->{$opt}) {
4190 my $oldnet = parse_net($conf->{$opt});
4192 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4193 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4194 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4195 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4197 # for non online change, we try to hot-unplug
4198 die "skip
\n" if !$hotplug;
4199 vm_deviceunplug($vmid, $conf, $opt);
4202 die "internal error
" if $opt !~ m/net(\d+)/;
4203 my $iface = "tap
${vmid
}i
$1";
4205 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4206 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4209 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4210 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4211 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4212 PVE::Network::tap_unplug($iface);
4213 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4216 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4217 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4225 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4231 sub vmconfig_update_disk {
4232 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4234 # fixme: do we need force?
4236 my $drive = parse_drive($opt, $value);
4238 if ($conf->{$opt}) {
4240 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4242 my $media = $drive->{media} || 'disk';
4243 my $oldmedia = $old_drive->{media} || 'disk';
4244 die "unable to change media type
\n" if $media ne $oldmedia;
4246 if (!drive_is_cdrom($old_drive)) {
4248 if ($drive->{file} ne $old_drive->{file}) {
4250 die "skip
\n" if !$hotplug;
4252 # unplug and register as unused
4253 vm_deviceunplug($vmid, $conf, $opt);
4254 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4257 # update existing disk
4259 # skip non hotpluggable value
4260 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4261 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4262 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4263 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4268 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4269 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4270 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4271 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4272 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4273 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4274 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4275 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4276 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4277 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4278 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4279 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4281 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4282 ($drive->{mbps} || 0)*1024*1024,
4283 ($drive->{mbps_rd} || 0)*1024*1024,
4284 ($drive->{mbps_wr} || 0)*1024*1024,
4285 $drive->{iops} || 0,
4286 $drive->{iops_rd} || 0,
4287 $drive->{iops_wr} || 0,
4288 ($drive->{mbps_max} || 0)*1024*1024,
4289 ($drive->{mbps_rd_max} || 0)*1024*1024,
4290 ($drive->{mbps_wr_max} || 0)*1024*1024,
4291 $drive->{iops_max} || 0,
4292 $drive->{iops_rd_max} || 0,
4293 $drive->{iops_wr_max} || 0);
4302 if ($drive->{file} eq 'none') {
4303 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4305 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4306 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4307 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4315 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4317 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
4318 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4322 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4323 $forcemachine, $spice_ticket) = @_;
4325 lock_config($vmid, sub {
4326 my $conf = load_config($vmid, $migratedfrom);
4328 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4330 check_lock($conf) if !$skiplock;
4332 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4334 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4335 vmconfig_apply_pending($vmid, $conf, $storecfg);
4336 $conf = load_config($vmid); # update/reload
4339 my $defaults = load_defaults();
4341 # set environment variable useful inside network script
4342 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4344 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4346 my $migrate_port = 0;
4349 if ($statefile eq 'tcp') {
4350 my $localip = "localhost
";
4351 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4352 my $nodename = PVE::INotify::nodename();
4353 if ($datacenterconf->{migration_unsecure}) {
4354 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4355 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4357 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4358 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4359 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4360 push @$cmd, '-incoming', $migrate_uri;
4363 push @$cmd, '-loadstate', $statefile;
4370 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4371 my $d = parse_hostpci($conf->{"hostpci
$i"});
4373 my $pcidevices = $d->{pciid};
4374 foreach my $pcidevice (@$pcidevices) {
4375 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4377 my $info = pci_device_info("0000:$pciid");
4378 die "IOMMU
not present
\n" if !check_iommu_support();
4379 die "no pci device info
for device
'$pciid'\n" if !$info;
4380 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4381 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4385 PVE::Storage::activate_volumes($storecfg, $vollist);
4387 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4390 die "start failed
: $err" if $err;
4392 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4394 if ($statefile && $statefile ne 'tcp') {
4395 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4399 if ($migratedfrom) {
4402 set_migration_caps($vmid);
4407 print "spice listens on port
$spice_port\n";
4408 if ($spice_ticket) {
4409 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4410 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4416 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4417 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4418 if $conf->{balloon};
4421 foreach my $opt (keys %$conf) {
4422 next if $opt !~ m/^net\d+$/;
4423 my $nicconf = parse_net($conf->{$opt});
4424 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4428 vm_mon_cmd_nocheck($vmid, 'qom-set',
4429 path => "machine
/peripheral/balloon0
",
4430 property => "guest-stats-polling-interval
",
4431 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4437 my ($vmid, $execute, %params) = @_;
4439 my $cmd = { execute => $execute, arguments => \%params };
4440 vm_qmp_command($vmid, $cmd);
4443 sub vm_mon_cmd_nocheck {
4444 my ($vmid, $execute, %params) = @_;
4446 my $cmd = { execute => $execute, arguments => \%params };
4447 vm_qmp_command($vmid, $cmd, 1);
4450 sub vm_qmp_command {
4451 my ($vmid, $cmd, $nocheck) = @_;
4456 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4457 $timeout = $cmd->{arguments}->{timeout};
4458 delete $cmd->{arguments}->{timeout};
4462 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4463 my $sname = qmp_socket($vmid);
4464 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4465 my $qmpclient = PVE::QMPClient->new();
4467 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4468 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4469 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4470 if scalar(%{$cmd->{arguments}});
4471 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4473 die "unable to open monitor socket\n";
4477 syslog("err", "VM $vmid qmp command failed - $err");
4484 sub vm_human_monitor_command {
4485 my ($vmid, $cmdline) = @_;
4490 execute => 'human-monitor-command
',
4491 arguments => { 'command-line
' => $cmdline},
4494 return vm_qmp_command($vmid, $cmd);
4497 sub vm_commandline {
4498 my ($storecfg, $vmid) = @_;
4500 my $conf = load_config($vmid);
4502 my $defaults = load_defaults();
4504 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4506 return join(' ', @$cmd);
4510 my ($vmid, $skiplock) = @_;
4512 lock_config($vmid, sub {
4514 my $conf = load_config($vmid);
4516 check_lock($conf) if !$skiplock;
4518 vm_mon_cmd($vmid, "system_reset");
4522 sub get_vm_volumes {
4526 foreach_volid($conf, sub {
4527 my ($volid, $is_cdrom) = @_;
4529 return if $volid =~ m|^/|;
4531 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4534 push @$vollist, $volid;
4540 sub vm_stop_cleanup {
4541 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4546 my $vollist = get_vm_volumes($conf);
4547 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4550 foreach my $ext (qw(mon qmp pid vnc qga)) {
4551 unlink "/var/run/qemu-server/${vmid}.$ext";
4554 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4556 warn $@ if $@; # avoid errors - just warn
4559 # Note: use $nockeck to skip tests if VM configuration file exists.
4560 # We need that when migration VMs to other nodes (files already moved)
4561 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4563 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4565 $force = 1 if !defined($force) && !$shutdown;
4568 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4569 kill 15, $pid if $pid;
4570 my $conf = load_config
($vmid, $migratedfrom);
4571 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4575 lock_config
($vmid, sub {
4577 my $pid = check_running
($vmid, $nocheck);
4582 $conf = load_config
($vmid);
4583 check_lock
($conf) if !$skiplock;
4584 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4585 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4586 $timeout = $opts->{down
} if $opts->{down
};
4590 $timeout = 60 if !defined($timeout);
4594 if (defined($conf) && $conf->{agent
}) {
4595 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4597 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4600 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4607 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4612 if ($count >= $timeout) {
4614 warn "VM still running - terminating now with SIGTERM\n";
4617 die "VM quit/powerdown failed - got timeout\n";
4620 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4625 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4628 die "VM quit/powerdown failed\n";
4636 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4641 if ($count >= $timeout) {
4642 warn "VM still running - terminating now with SIGKILL\n";
4647 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4652 my ($vmid, $skiplock) = @_;
4654 lock_config
($vmid, sub {
4656 my $conf = load_config
($vmid);
4658 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4660 vm_mon_cmd
($vmid, "stop");
4665 my ($vmid, $skiplock, $nocheck) = @_;
4667 lock_config
($vmid, sub {
4671 my $conf = load_config
($vmid);
4673 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4675 vm_mon_cmd
($vmid, "cont");
4678 vm_mon_cmd_nocheck
($vmid, "cont");
4684 my ($vmid, $skiplock, $key) = @_;
4686 lock_config
($vmid, sub {
4688 my $conf = load_config
($vmid);
4690 # there is no qmp command, so we use the human monitor command
4691 vm_human_monitor_command
($vmid, "sendkey $key");
4696 my ($storecfg, $vmid, $skiplock) = @_;
4698 lock_config
($vmid, sub {
4700 my $conf = load_config
($vmid);
4702 check_lock
($conf) if !$skiplock;
4704 if (!check_running
($vmid)) {
4705 destroy_vm
($storecfg, $vmid);
4707 die "VM $vmid is running - destroy failed\n";
4715 my ($filename, $buf) = @_;
4717 my $fh = IO
::File-
>new($filename, "w");
4718 return undef if !$fh;
4720 my $res = print $fh $buf;
4727 sub pci_device_info
{
4732 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4733 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4735 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4736 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4738 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4739 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4741 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4742 return undef if !defined($product) || $product !~ s/^0x//;
4747 product
=> $product,
4753 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4762 my $name = $dev->{name
};
4764 my $fn = "$pcisysfs/devices/$name/reset";
4766 return file_write
($fn, "1");
4769 sub pci_dev_bind_to_vfio
{
4772 my $name = $dev->{name
};
4774 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4776 if (!-d
$vfio_basedir) {
4777 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4779 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4781 my $testdir = "$vfio_basedir/$name";
4782 return 1 if -d
$testdir;
4784 my $data = "$dev->{vendor} $dev->{product}";
4785 return undef if !file_write
("$vfio_basedir/new_id", $data);
4787 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4788 if (!file_write
($fn, $name)) {
4789 return undef if -f
$fn;
4792 $fn = "$vfio_basedir/bind";
4793 if (! -d
$testdir) {
4794 return undef if !file_write
($fn, $name);
4800 sub pci_dev_group_bind_to_vfio
{
4803 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4805 if (!-d
$vfio_basedir) {
4806 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4808 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4810 # get IOMMU group devices
4811 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4812 my @devs = grep /^0000:/, readdir($D);
4815 foreach my $pciid (@devs) {
4816 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4818 # pci bridges, switches or root ports are not supported
4819 # they have a pci_bus subdirectory so skip them
4820 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4822 my $info = pci_device_info
($1);
4823 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4829 sub print_pci_addr
{
4830 my ($id, $bridges) = @_;
4834 piix3
=> { bus
=> 0, addr
=> 1 },
4835 #addr2 : first videocard
4836 balloon0
=> { bus
=> 0, addr
=> 3 },
4837 watchdog
=> { bus
=> 0, addr
=> 4 },
4838 scsihw0
=> { bus
=> 0, addr
=> 5 },
4839 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4840 scsihw1
=> { bus
=> 0, addr
=> 6 },
4841 ahci0
=> { bus
=> 0, addr
=> 7 },
4842 qga0
=> { bus
=> 0, addr
=> 8 },
4843 spice
=> { bus
=> 0, addr
=> 9 },
4844 virtio0
=> { bus
=> 0, addr
=> 10 },
4845 virtio1
=> { bus
=> 0, addr
=> 11 },
4846 virtio2
=> { bus
=> 0, addr
=> 12 },
4847 virtio3
=> { bus
=> 0, addr
=> 13 },
4848 virtio4
=> { bus
=> 0, addr
=> 14 },
4849 virtio5
=> { bus
=> 0, addr
=> 15 },
4850 hostpci0
=> { bus
=> 0, addr
=> 16 },
4851 hostpci1
=> { bus
=> 0, addr
=> 17 },
4852 net0
=> { bus
=> 0, addr
=> 18 },
4853 net1
=> { bus
=> 0, addr
=> 19 },
4854 net2
=> { bus
=> 0, addr
=> 20 },
4855 net3
=> { bus
=> 0, addr
=> 21 },
4856 net4
=> { bus
=> 0, addr
=> 22 },
4857 net5
=> { bus
=> 0, addr
=> 23 },
4858 vga1
=> { bus
=> 0, addr
=> 24 },
4859 vga2
=> { bus
=> 0, addr
=> 25 },
4860 vga3
=> { bus
=> 0, addr
=> 26 },
4861 hostpci2
=> { bus
=> 0, addr
=> 27 },
4862 hostpci3
=> { bus
=> 0, addr
=> 28 },
4863 #addr29 : usb-host (pve-usb.cfg)
4864 'pci.1' => { bus
=> 0, addr
=> 30 },
4865 'pci.2' => { bus
=> 0, addr
=> 31 },
4866 'net6' => { bus
=> 1, addr
=> 1 },
4867 'net7' => { bus
=> 1, addr
=> 2 },
4868 'net8' => { bus
=> 1, addr
=> 3 },
4869 'net9' => { bus
=> 1, addr
=> 4 },
4870 'net10' => { bus
=> 1, addr
=> 5 },
4871 'net11' => { bus
=> 1, addr
=> 6 },
4872 'net12' => { bus
=> 1, addr
=> 7 },
4873 'net13' => { bus
=> 1, addr
=> 8 },
4874 'net14' => { bus
=> 1, addr
=> 9 },
4875 'net15' => { bus
=> 1, addr
=> 10 },
4876 'net16' => { bus
=> 1, addr
=> 11 },
4877 'net17' => { bus
=> 1, addr
=> 12 },
4878 'net18' => { bus
=> 1, addr
=> 13 },
4879 'net19' => { bus
=> 1, addr
=> 14 },
4880 'net20' => { bus
=> 1, addr
=> 15 },
4881 'net21' => { bus
=> 1, addr
=> 16 },
4882 'net22' => { bus
=> 1, addr
=> 17 },
4883 'net23' => { bus
=> 1, addr
=> 18 },
4884 'net24' => { bus
=> 1, addr
=> 19 },
4885 'net25' => { bus
=> 1, addr
=> 20 },
4886 'net26' => { bus
=> 1, addr
=> 21 },
4887 'net27' => { bus
=> 1, addr
=> 22 },
4888 'net28' => { bus
=> 1, addr
=> 23 },
4889 'net29' => { bus
=> 1, addr
=> 24 },
4890 'net30' => { bus
=> 1, addr
=> 25 },
4891 'net31' => { bus
=> 1, addr
=> 26 },
4892 'virtio6' => { bus
=> 2, addr
=> 1 },
4893 'virtio7' => { bus
=> 2, addr
=> 2 },
4894 'virtio8' => { bus
=> 2, addr
=> 3 },
4895 'virtio9' => { bus
=> 2, addr
=> 4 },
4896 'virtio10' => { bus
=> 2, addr
=> 5 },
4897 'virtio11' => { bus
=> 2, addr
=> 6 },
4898 'virtio12' => { bus
=> 2, addr
=> 7 },
4899 'virtio13' => { bus
=> 2, addr
=> 8 },
4900 'virtio14' => { bus
=> 2, addr
=> 9 },
4901 'virtio15' => { bus
=> 2, addr
=> 10 },
4902 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4903 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4904 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4905 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4906 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4907 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4908 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4909 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4910 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4911 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4912 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4913 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4914 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4915 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4916 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4917 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4918 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4919 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4920 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4921 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4922 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4923 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4924 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4925 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4926 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4927 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4928 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4929 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4930 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4931 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4932 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4936 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4937 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4938 my $bus = $devices->{$id}->{bus
};
4939 $res = ",bus=pci.$bus,addr=$addr";
4940 $bridges->{$bus} = 1 if $bridges;
4946 sub print_pcie_addr
{
4951 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4952 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4953 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4954 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4957 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4958 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4959 my $bus = $devices->{$id}->{bus
};
4960 $res = ",bus=$bus,addr=$addr";
4966 # vzdump restore implementaion
4968 sub tar_archive_read_firstfile
{
4969 my $archive = shift;
4971 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4973 # try to detect archive type first
4974 my $pid = open (TMP
, "tar tf '$archive'|") ||
4975 die "unable to open file '$archive'\n";
4976 my $firstfile = <TMP
>;
4980 die "ERROR: archive contaions no data\n" if !$firstfile;
4986 sub tar_restore_cleanup
{
4987 my ($storecfg, $statfile) = @_;
4989 print STDERR
"starting cleanup\n";
4991 if (my $fd = IO
::File-
>new($statfile, "r")) {
4992 while (defined(my $line = <$fd>)) {
4993 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4996 if ($volid =~ m
|^/|) {
4997 unlink $volid || die 'unlink failed\n';
4999 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5001 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5003 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5005 print STDERR
"unable to parse line in statfile - $line";
5012 sub restore_archive
{
5013 my ($archive, $vmid, $user, $opts) = @_;
5015 my $format = $opts->{format
};
5018 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5019 $format = 'tar' if !$format;
5021 } elsif ($archive =~ m/\.tar$/) {
5022 $format = 'tar' if !$format;
5023 } elsif ($archive =~ m/.tar.lzo$/) {
5024 $format = 'tar' if !$format;
5026 } elsif ($archive =~ m/\.vma$/) {
5027 $format = 'vma' if !$format;
5028 } elsif ($archive =~ m/\.vma\.gz$/) {
5029 $format = 'vma' if !$format;
5031 } elsif ($archive =~ m/\.vma\.lzo$/) {
5032 $format = 'vma' if !$format;
5035 $format = 'vma' if !$format; # default
5038 # try to detect archive format
5039 if ($format eq 'tar') {
5040 return restore_tar_archive
($archive, $vmid, $user, $opts);
5042 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5046 sub restore_update_config_line
{
5047 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5049 return if $line =~ m/^\#qmdump\#/;
5050 return if $line =~ m/^\#vzdump\#/;
5051 return if $line =~ m/^lock:/;
5052 return if $line =~ m/^unused\d+:/;
5053 return if $line =~ m/^parent:/;
5054 return if $line =~ m/^template:/; # restored VM is never a template
5056 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5057 # try to convert old 1.X settings
5058 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5059 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5060 my ($model, $macaddr) = split(/\=/, $devconfig);
5061 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5064 bridge
=> "vmbr$ind",
5065 macaddr
=> $macaddr,
5067 my $netstr = print_net
($net);
5069 print $outfd "net$cookie->{netcount}: $netstr\n";
5070 $cookie->{netcount
}++;
5072 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5073 my ($id, $netstr) = ($1, $2);
5074 my $net = parse_net
($netstr);
5075 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5076 $netstr = print_net
($net);
5077 print $outfd "$id: $netstr\n";
5078 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5081 if ($line =~ m/backup=no/) {
5082 print $outfd "#$line";
5083 } elsif ($virtdev && $map->{$virtdev}) {
5084 my $di = parse_drive
($virtdev, $value);
5085 delete $di->{format
}; # format can change on restore
5086 $di->{file
} = $map->{$virtdev};
5087 $value = print_drive
($vmid, $di);
5088 print $outfd "$virtdev: $value\n";
5098 my ($cfg, $vmid) = @_;
5100 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5102 my $volid_hash = {};
5103 foreach my $storeid (keys %$info) {
5104 foreach my $item (@{$info->{$storeid}}) {
5105 next if !($item->{volid
} && $item->{size
});
5106 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5107 $volid_hash->{$item->{volid
}} = $item;
5114 sub is_volume_in_use
{
5115 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5117 my $path = PVE
::Storage
::path
($storecfg, $volid);
5119 my $scan_config = sub {
5120 my ($cref, $snapname) = @_;
5122 foreach my $key (keys %$cref) {
5123 my $value = $cref->{$key};
5124 if (valid_drivename
($key)) {
5125 next if $skip_drive && $key eq $skip_drive;
5126 my $drive = parse_drive
($key, $value);
5127 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5128 return 1 if $volid eq $drive->{file
};
5129 if ($drive->{file
} =~ m!^/!) {
5130 return 1 if $drive->{file
} eq $path;
5132 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5134 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5136 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5144 return 1 if &$scan_config($conf);
5148 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5149 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5155 sub update_disksize
{
5156 my ($vmid, $conf, $volid_hash) = @_;
5162 # Note: it is allowed to define multiple storages with same path (alias), so
5163 # we need to check both 'volid' and real 'path' (two different volid can point
5164 # to the same path).
5169 foreach my $opt (keys %$conf) {
5170 if (valid_drivename
($opt)) {
5171 my $drive = parse_drive
($opt, $conf->{$opt});
5172 my $volid = $drive->{file
};
5175 $used->{$volid} = 1;
5176 if ($volid_hash->{$volid} &&
5177 (my $path = $volid_hash->{$volid}->{path
})) {
5178 $usedpath->{$path} = 1;
5181 next if drive_is_cdrom
($drive);
5182 next if !$volid_hash->{$volid};
5184 $drive->{size
} = $volid_hash->{$volid}->{size
};
5185 my $new = print_drive
($vmid, $drive);
5186 if ($new ne $conf->{$opt}) {
5188 $conf->{$opt} = $new;
5193 # remove 'unusedX' entry if volume is used
5194 foreach my $opt (keys %$conf) {
5195 next if $opt !~ m/^unused\d+$/;
5196 my $volid = $conf->{$opt};
5197 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5198 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5200 delete $conf->{$opt};
5204 foreach my $volid (sort keys %$volid_hash) {
5205 next if $volid =~ m/vm-$vmid-state-/;
5206 next if $used->{$volid};
5207 my $path = $volid_hash->{$volid}->{path
};
5208 next if !$path; # just to be sure
5209 next if $usedpath->{$path};
5211 add_unused_volume
($conf, $volid);
5212 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5219 my ($vmid, $nolock) = @_;
5221 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5223 my $volid_hash = scan_volids
($cfg, $vmid);
5225 my $updatefn = sub {
5228 my $conf = load_config
($vmid);
5233 foreach my $volid (keys %$volid_hash) {
5234 my $info = $volid_hash->{$volid};
5235 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5238 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5240 update_config_nolock
($vmid, $conf, 1) if $changes;
5243 if (defined($vmid)) {
5247 lock_config
($vmid, $updatefn, $vmid);
5250 my $vmlist = config_list
();
5251 foreach my $vmid (keys %$vmlist) {
5255 lock_config
($vmid, $updatefn, $vmid);
5261 sub restore_vma_archive
{
5262 my ($archive, $vmid, $user, $opts, $comp) = @_;
5264 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5265 my $readfrom = $archive;
5270 my $qarchive = PVE
::Tools
::shellquote
($archive);
5271 if ($comp eq 'gzip') {
5272 $uncomp = "zcat $qarchive|";
5273 } elsif ($comp eq 'lzop') {
5274 $uncomp = "lzop -d -c $qarchive|";
5276 die "unknown compression method '$comp'\n";
5281 my $tmpdir = "/var/tmp/vzdumptmp$$";
5284 # disable interrupts (always do cleanups)
5285 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5286 warn "got interrupt - ignored\n";
5289 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5290 POSIX
::mkfifo
($mapfifo, 0600);
5293 my $openfifo = sub {
5294 open($fifofh, '>', $mapfifo) || die $!;
5297 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5304 my $rpcenv = PVE
::RPCEnvironment
::get
();
5306 my $conffile = config_file
($vmid);
5307 my $tmpfn = "$conffile.$$.tmp";
5309 # Note: $oldconf is undef if VM does not exists
5310 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5312 my $print_devmap = sub {
5313 my $virtdev_hash = {};
5315 my $cfgfn = "$tmpdir/qemu-server.conf";
5317 # we can read the config - that is already extracted
5318 my $fh = IO
::File-
>new($cfgfn, "r") ||
5319 "unable to read qemu-server.conf - $!\n";
5321 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5322 PVE
::Tools
::file_copy
($fwcfgfn, "/etc/pve/firewall/$vmid.fw")
5325 while (defined(my $line = <$fh>)) {
5326 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5327 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5328 die "archive does not contain data for drive '$virtdev'\n"
5329 if !$devinfo->{$devname};
5330 if (defined($opts->{storage
})) {
5331 $storeid = $opts->{storage
} || 'local';
5332 } elsif (!$storeid) {
5335 $format = 'raw' if !$format;
5336 $devinfo->{$devname}->{devname
} = $devname;
5337 $devinfo->{$devname}->{virtdev
} = $virtdev;
5338 $devinfo->{$devname}->{format
} = $format;
5339 $devinfo->{$devname}->{storeid
} = $storeid;
5341 # check permission on storage
5342 my $pool = $opts->{pool
}; # todo: do we need that?
5343 if ($user ne 'root@pam') {
5344 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5347 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5351 foreach my $devname (keys %$devinfo) {
5352 die "found no device mapping information for device '$devname'\n"
5353 if !$devinfo->{$devname}->{virtdev
};
5356 my $cfg = cfs_read_file
('storage.cfg');
5358 # create empty/temp config
5360 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5361 foreach_drive
($oldconf, sub {
5362 my ($ds, $drive) = @_;
5364 return if drive_is_cdrom
($drive);
5366 my $volid = $drive->{file
};
5368 return if !$volid || $volid =~ m
|^/|;
5370 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5371 return if !$path || !$owner || ($owner != $vmid);
5373 # Note: only delete disk we want to restore
5374 # other volumes will become unused
5375 if ($virtdev_hash->{$ds}) {
5376 PVE
::Storage
::vdisk_free
($cfg, $volid);
5382 foreach my $virtdev (sort keys %$virtdev_hash) {
5383 my $d = $virtdev_hash->{$virtdev};
5384 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5385 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5387 # test if requested format is supported
5388 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5389 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5390 $d->{format
} = $defFormat if !$supported;
5392 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5393 $d->{format
}, undef, $alloc_size);
5394 print STDERR
"new volume ID is '$volid'\n";
5395 $d->{volid
} = $volid;
5396 my $path = PVE
::Storage
::path
($cfg, $volid);
5398 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5400 my $write_zeros = 1;
5401 # fixme: what other storages types initialize volumes with zero?
5402 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5403 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5407 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5409 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5410 $map->{$virtdev} = $volid;
5413 $fh->seek(0, 0) || die "seek failed - $!\n";
5415 my $outfd = new IO
::File
($tmpfn, "w") ||
5416 die "unable to write config for VM $vmid\n";
5418 my $cookie = { netcount
=> 0 };
5419 while (defined(my $line = <$fh>)) {
5420 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5429 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5430 die "interrupted by signal\n";
5432 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5434 $oldtimeout = alarm($timeout);
5441 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5442 my ($dev_id, $size, $devname) = ($1, $2, $3);
5443 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5444 } elsif ($line =~ m/^CTIME: /) {
5445 # we correctly received the vma config, so we can disable
5446 # the timeout now for disk allocation (set to 10 minutes, so
5447 # that we always timeout if something goes wrong)
5450 print $fifofh "done\n";
5451 my $tmp = $oldtimeout || 0;
5452 $oldtimeout = undef;
5458 print "restore vma archive: $cmd\n";
5459 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5463 alarm($oldtimeout) if $oldtimeout;
5466 foreach my $devname (keys %$devinfo) {
5467 my $volid = $devinfo->{$devname}->{volid
};
5468 push @$vollist, $volid if $volid;
5471 my $cfg = cfs_read_file
('storage.cfg');
5472 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5480 foreach my $devname (keys %$devinfo) {
5481 my $volid = $devinfo->{$devname}->{volid
};
5484 if ($volid =~ m
|^/|) {
5485 unlink $volid || die 'unlink failed\n';
5487 PVE
::Storage
::vdisk_free
($cfg, $volid);
5489 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5491 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5498 rename($tmpfn, $conffile) ||
5499 die "unable to commit configuration file '$conffile'\n";
5501 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5503 eval { rescan
($vmid, 1); };
5507 sub restore_tar_archive
{
5508 my ($archive, $vmid, $user, $opts) = @_;
5510 if ($archive ne '-') {
5511 my $firstfile = tar_archive_read_firstfile
($archive);
5512 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5513 if $firstfile ne 'qemu-server.conf';
5516 my $storecfg = cfs_read_file
('storage.cfg');
5518 # destroy existing data - keep empty config
5519 my $vmcfgfn = config_file
($vmid);
5520 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5522 my $tocmd = "/usr/lib/qemu-server/qmextract";
5524 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5525 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5526 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5527 $tocmd .= ' --info' if $opts->{info
};
5529 # tar option "xf" does not autodetect compression when read from STDIN,
5530 # so we pipe to zcat
5531 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5532 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5534 my $tmpdir = "/var/tmp/vzdumptmp$$";
5537 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5538 local $ENV{VZDUMP_VMID
} = $vmid;
5539 local $ENV{VZDUMP_USER
} = $user;
5541 my $conffile = config_file
($vmid);
5542 my $tmpfn = "$conffile.$$.tmp";
5544 # disable interrupts (always do cleanups)
5545 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5546 print STDERR
"got interrupt - ignored\n";
5551 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5552 die "interrupted by signal\n";
5555 if ($archive eq '-') {
5556 print "extracting archive from STDIN\n";
5557 run_command
($cmd, input
=> "<&STDIN");
5559 print "extracting archive '$archive'\n";
5563 return if $opts->{info
};
5567 my $statfile = "$tmpdir/qmrestore.stat";
5568 if (my $fd = IO
::File-
>new($statfile, "r")) {
5569 while (defined (my $line = <$fd>)) {
5570 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5571 $map->{$1} = $2 if $1;
5573 print STDERR
"unable to parse line in statfile - $line\n";
5579 my $confsrc = "$tmpdir/qemu-server.conf";
5581 my $srcfd = new IO
::File
($confsrc, "r") ||
5582 die "unable to open file '$confsrc'\n";
5584 my $outfd = new IO
::File
($tmpfn, "w") ||
5585 die "unable to write config for VM $vmid\n";
5587 my $cookie = { netcount
=> 0 };
5588 while (defined (my $line = <$srcfd>)) {
5589 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5601 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5608 rename $tmpfn, $conffile ||
5609 die "unable to commit configuration file '$conffile'\n";
5611 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5613 eval { rescan
($vmid, 1); };
5618 # Internal snapshots
5620 # NOTE: Snapshot create/delete involves several non-atomic
5621 # action, and can take a long time.
5622 # So we try to avoid locking the file and use 'lock' variable
5623 # inside the config file instead.
5625 my $snapshot_copy_config = sub {
5626 my ($source, $dest) = @_;
5628 foreach my $k (keys %$source) {
5629 next if $k eq 'snapshots';
5630 next if $k eq 'snapstate';
5631 next if $k eq 'snaptime';
5632 next if $k eq 'vmstate';
5633 next if $k eq 'lock';
5634 next if $k eq 'digest';
5635 next if $k eq 'description';
5636 next if $k =~ m/^unused\d+$/;
5638 $dest->{$k} = $source->{$k};
5642 my $snapshot_apply_config = sub {
5643 my ($conf, $snap) = @_;
5645 # copy snapshot list
5647 snapshots
=> $conf->{snapshots
},
5650 # keep description and list of unused disks
5651 foreach my $k (keys %$conf) {
5652 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5653 $newconf->{$k} = $conf->{$k};
5656 &$snapshot_copy_config($snap, $newconf);
5661 sub foreach_writable_storage
{
5662 my ($conf, $func) = @_;
5666 foreach my $ds (keys %$conf) {
5667 next if !valid_drivename
($ds);
5669 my $drive = parse_drive
($ds, $conf->{$ds});
5671 next if drive_is_cdrom
($drive);
5673 my $volid = $drive->{file
};
5675 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5676 $sidhash->{$sid} = $sid if $sid;
5679 foreach my $sid (sort keys %$sidhash) {
5684 my $alloc_vmstate_volid = sub {
5685 my ($storecfg, $vmid, $conf, $snapname) = @_;
5687 # Note: we try to be smart when selecting a $target storage
5691 # search shared storage first
5692 foreach_writable_storage
($conf, sub {
5694 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5695 return if !$scfg->{shared
};
5697 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5701 # now search local storage
5702 foreach_writable_storage
($conf, sub {
5704 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5705 return if $scfg->{shared
};
5707 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5711 $target = 'local' if !$target;
5713 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5714 # we abort live save after $conf->{memory}, so we need at max twice that space
5715 my $size = $conf->{memory
}*2 + $driver_state_size;
5717 my $name = "vm-$vmid-state-$snapname";
5718 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5719 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5720 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5725 my $snapshot_prepare = sub {
5726 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5730 my $updatefn = sub {
5732 my $conf = load_config
($vmid);
5734 die "you can't take a snapshot if it's a template\n"
5735 if is_template
($conf);
5739 $conf->{lock} = 'snapshot';
5741 die "snapshot name '$snapname' already used\n"
5742 if defined($conf->{snapshots
}->{$snapname});
5744 my $storecfg = PVE
::Storage
::config
();
5745 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5747 $snap = $conf->{snapshots
}->{$snapname} = {};
5749 if ($save_vmstate && check_running
($vmid)) {
5750 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5753 &$snapshot_copy_config($conf, $snap);
5755 $snap->{snapstate
} = "prepare";
5756 $snap->{snaptime
} = time();
5757 $snap->{description
} = $comment if $comment;
5759 # always overwrite machine if we save vmstate. This makes sure we
5760 # can restore it later using correct machine type
5761 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5763 update_config_nolock
($vmid, $conf, 1);
5766 lock_config
($vmid, $updatefn);
5771 my $snapshot_commit = sub {
5772 my ($vmid, $snapname) = @_;
5774 my $updatefn = sub {
5776 my $conf = load_config
($vmid);
5778 die "missing snapshot lock\n"
5779 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5781 my $has_machine_config = defined($conf->{machine
});
5783 my $snap = $conf->{snapshots
}->{$snapname};
5785 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5787 die "wrong snapshot state\n"
5788 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5790 delete $snap->{snapstate
};
5791 delete $conf->{lock};
5793 my $newconf = &$snapshot_apply_config($conf, $snap);
5795 delete $newconf->{machine
} if !$has_machine_config;
5797 $newconf->{parent
} = $snapname;
5799 update_config_nolock
($vmid, $newconf, 1);
5802 lock_config
($vmid, $updatefn);
5805 sub snapshot_rollback
{
5806 my ($vmid, $snapname) = @_;
5810 my $storecfg = PVE
::Storage
::config
();
5812 my $conf = load_config
($vmid);
5814 my $get_snapshot_config = sub {
5816 die "you can't rollback if vm is a template\n" if is_template
($conf);
5818 my $res = $conf->{snapshots
}->{$snapname};
5820 die "snapshot '$snapname' does not exist\n" if !defined($res);
5825 my $snap = &$get_snapshot_config();
5827 foreach_drive
($snap, sub {
5828 my ($ds, $drive) = @_;
5830 return if drive_is_cdrom
($drive);
5832 my $volid = $drive->{file
};
5834 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5837 my $updatefn = sub {
5839 $conf = load_config
($vmid);
5841 $snap = &$get_snapshot_config();
5843 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5844 if $snap->{snapstate
};
5848 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5851 die "unable to rollback vm $vmid: vm is running\n"
5852 if check_running
($vmid);
5855 $conf->{lock} = 'rollback';
5857 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5858 delete $conf->{lock};
5864 my $has_machine_config = defined($conf->{machine
});
5866 # copy snapshot config to current config
5867 $conf = &$snapshot_apply_config($conf, $snap);
5868 $conf->{parent
} = $snapname;
5870 # Note: old code did not store 'machine', so we try to be smart
5871 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5872 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5873 # we remove the 'machine' configuration if not explicitly specified
5874 # in the original config.
5875 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5878 update_config_nolock
($vmid, $conf, 1);
5880 if (!$prepare && $snap->{vmstate
}) {
5881 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5882 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5886 lock_config
($vmid, $updatefn);
5888 foreach_drive
($snap, sub {
5889 my ($ds, $drive) = @_;
5891 return if drive_is_cdrom
($drive);
5893 my $volid = $drive->{file
};
5894 my $device = "drive-$ds";
5896 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5900 lock_config
($vmid, $updatefn);
5903 my $savevm_wait = sub {
5907 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5908 if (!$stat->{status
}) {
5909 die "savevm not active\n";
5910 } elsif ($stat->{status
} eq 'active') {
5913 } elsif ($stat->{status
} eq 'completed') {
5916 die "query-savevm returned status '$stat->{status}'\n";
5921 sub do_snapshots_with_qemu
{
5922 my ($storecfg, $volid) = @_;
5924 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5926 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5927 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5931 if ($volid =~ m/\.(qcow2|qed)$/){
5938 sub snapshot_create
{
5939 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5941 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5943 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5945 my $config = load_config
($vmid);
5947 my $running = check_running
($vmid);
5949 my $freezefs = $running && $config->{agent
};
5950 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5955 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5956 warn "guest-fsfreeze-freeze problems - $@" if $@;
5960 # create internal snapshots of all drives
5962 my $storecfg = PVE
::Storage
::config
();
5965 if ($snap->{vmstate
}) {
5966 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5967 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5968 &$savevm_wait($vmid);
5970 vm_mon_cmd
($vmid, "savevm-start");
5974 foreach_drive
($snap, sub {
5975 my ($ds, $drive) = @_;
5977 return if drive_is_cdrom
($drive);
5979 my $volid = $drive->{file
};
5980 my $device = "drive-$ds";
5982 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5983 $drivehash->{$ds} = 1;
5989 eval { vm_mon_cmd
($vmid, "savevm-end") };
5993 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5994 warn "guest-fsfreeze-thaw problems - $@" if $@;
5997 # savevm-end is async, we need to wait
5999 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6000 if (!$stat->{bytes
}) {
6003 print "savevm not yet finished\n";
6011 warn "snapshot create failed: starting cleanup\n";
6012 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6017 &$snapshot_commit($vmid, $snapname);
6020 # Note: $drivehash is only set when called from snapshot_create.
6021 sub snapshot_delete
{
6022 my ($vmid, $snapname, $force, $drivehash) = @_;
6029 my $unlink_parent = sub {
6030 my ($confref, $new_parent) = @_;
6032 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6034 $confref->{parent
} = $new_parent;
6036 delete $confref->{parent
};
6041 my $updatefn = sub {
6042 my ($remove_drive) = @_;
6044 my $conf = load_config
($vmid);
6048 die "you can't delete a snapshot if vm is a template\n"
6049 if is_template
($conf);
6052 $snap = $conf->{snapshots
}->{$snapname};
6054 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6056 # remove parent refs
6058 &$unlink_parent($conf, $snap->{parent
});
6059 foreach my $sn (keys %{$conf->{snapshots
}}) {
6060 next if $sn eq $snapname;
6061 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6065 if ($remove_drive) {
6066 if ($remove_drive eq 'vmstate') {
6067 delete $snap->{$remove_drive};
6069 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6070 my $volid = $drive->{file
};
6071 delete $snap->{$remove_drive};
6072 add_unused_volume
($conf, $volid);
6077 $snap->{snapstate
} = 'delete';
6079 delete $conf->{snapshots
}->{$snapname};
6080 delete $conf->{lock} if $drivehash;
6081 foreach my $volid (@$unused) {
6082 add_unused_volume
($conf, $volid);
6086 update_config_nolock
($vmid, $conf, 1);
6089 lock_config
($vmid, $updatefn);
6091 # now remove vmstate file
6093 my $storecfg = PVE
::Storage
::config
();
6095 if ($snap->{vmstate
}) {
6096 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6098 die $err if !$force;
6101 # save changes (remove vmstate from snapshot)
6102 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6105 # now remove all internal snapshots
6106 foreach_drive
($snap, sub {
6107 my ($ds, $drive) = @_;
6109 return if drive_is_cdrom
($drive);
6111 my $volid = $drive->{file
};
6112 my $device = "drive-$ds";
6114 if (!$drivehash || $drivehash->{$ds}) {
6115 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6117 die $err if !$force;
6122 # save changes (remove drive fron snapshot)
6123 lock_config
($vmid, $updatefn, $ds) if !$force;
6124 push @$unused, $volid;
6127 # now cleanup config
6129 lock_config
($vmid, $updatefn);
6133 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6136 foreach_drive
($conf, sub {
6137 my ($ds, $drive) = @_;
6139 return if drive_is_cdrom
($drive);
6140 my $volid = $drive->{file
};
6141 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6144 return $err ?
0 : 1;
6147 sub template_create
{
6148 my ($vmid, $conf, $disk) = @_;
6150 my $storecfg = PVE
::Storage
::config
();
6152 foreach_drive
($conf, sub {
6153 my ($ds, $drive) = @_;
6155 return if drive_is_cdrom
($drive);
6156 return if $disk && $ds ne $disk;
6158 my $volid = $drive->{file
};
6159 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6161 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6162 $drive->{file
} = $voliddst;
6163 $conf->{$ds} = print_drive
($vmid, $drive);
6164 update_config_nolock
($vmid, $conf, 1);
6171 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6174 sub qemu_img_convert
{
6175 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6177 my $storecfg = PVE
::Storage
::config
();
6178 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6179 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6181 if ($src_storeid && $dst_storeid) {
6183 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6185 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6186 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6188 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6189 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6191 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6192 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6195 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6196 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6197 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6201 if($line =~ m/\((\S+)\/100\
%\)/){
6203 my $transferred = int($size * $percent / 100);
6204 my $remaining = $size - $transferred;
6206 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6211 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6213 die "copy failed: $err" if $err;
6217 sub qemu_img_format
{
6218 my ($scfg, $volname) = @_;
6220 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6227 sub qemu_drive_mirror
{
6228 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6230 my $storecfg = PVE
::Storage
::config
();
6231 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6233 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6235 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6237 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6239 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6240 $opts->{format
} = $format if $format;
6242 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6245 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6247 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6248 my $stat = @$stats[0];
6249 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6250 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6252 my $busy = $stat->{busy
};
6253 my $ready = $stat->{ready
};
6255 if (my $total = $stat->{len
}) {
6256 my $transferred = $stat->{offset
} || 0;
6257 my $remaining = $total - $transferred;
6258 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6260 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6264 if ($stat->{ready
} eq 'true') {
6266 last if $vmiddst != $vmid;
6268 # try to switch the disk if source and destination are on the same guest
6269 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6271 die $@ if $@ !~ m/cannot be completed/;
6280 my $cancel_job = sub {
6281 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6283 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6284 my $stat = @$stats[0];
6291 eval { &$cancel_job(); };
6292 die "mirroring error: $err";
6295 if ($vmiddst != $vmid) {
6296 # if we clone a disk for a new target vm, we don't switch the disk
6297 &$cancel_job(); # so we call block-job-cancel
6302 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6303 $newvmid, $storage, $format, $full, $newvollist) = @_;
6308 print "create linked clone of drive $drivename ($drive->{file})\n";
6309 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6310 push @$newvollist, $newvolid;
6312 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6313 $storeid = $storage if $storage;
6315 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6317 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6318 $format = qemu_img_format
($scfg, $volname);
6321 # test if requested format is supported - else use default
6322 my $supported = grep { $_ eq $format } @$validFormats;
6323 $format = $defFormat if !$supported;
6325 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6327 print "create full clone of drive $drivename ($drive->{file})\n";
6328 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6329 push @$newvollist, $newvolid;
6331 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6333 if (!$running || $snapname) {
6334 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6336 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6340 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6343 $disk->{format
} = undef;
6344 $disk->{file
} = $newvolid;
6345 $disk->{size
} = $size;
6350 # this only works if VM is running
6351 sub get_current_qemu_machine
{
6354 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6355 my $res = vm_qmp_command
($vmid, $cmd);
6357 my ($current, $default);
6358 foreach my $e (@$res) {
6359 $default = $e->{name
} if $e->{'is-default'};
6360 $current = $e->{name
} if $e->{'is-current'};
6363 # fallback to the default machine if current is not supported by qemu
6364 return $current || $default || 'pc';
6367 sub qemu_machine_feature_enabled
{
6368 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6373 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6375 $current_major = $3;
6376 $current_minor = $4;
6378 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6380 $current_major = $1;
6381 $current_minor = $2;
6384 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6389 sub qemu_machine_pxe
{
6390 my ($vmid, $conf, $machine) = @_;
6392 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6394 foreach my $opt (keys %$conf) {
6395 next if $opt !~ m/^net(\d+)$/;
6396 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6398 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6399 return $machine.".pxe" if $romfile =~ m/pxe/;
6405 sub qemu_use_old_bios_files
{
6406 my ($machine_type) = @_;
6408 return if !$machine_type;
6410 my $use_old_bios_files = undef;
6412 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6414 $use_old_bios_files = 1;
6416 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6417 # load new efi bios files on migration. So this hack is required to allow
6418 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6419 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6420 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6423 return ($use_old_bios_files, $machine_type);
6430 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6431 my (undef, $id, $function) = @_;
6432 my $res = { id
=> $id, function
=> $function};
6433 push @{$devices->{$id}}, $res;
6439 sub vm_iothreads_list
{
6442 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6445 foreach my $iothread (@$res) {
6446 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6453 my ($conf, $drive) = @_;
6457 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6459 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6465 my $controller = int($drive->{index} / $maxdev);
6466 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6468 return ($maxdev, $controller, $controller_prefix);
6471 # bash completion helper
6473 sub complete_backup_archives
{
6474 my ($cmdname, $pname, $cvalue) = @_;
6476 my $cfg = PVE
::Storage
::config
();
6480 if ($cvalue =~ m/^([^:]+):/) {
6484 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6487 foreach my $id (keys %$data) {
6488 foreach my $item (@{$data->{$id}}) {
6489 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6490 push @$res, $item->{volid
} if defined($item->{volid
});
6497 my $complete_vmid_full = sub {
6500 my $idlist = vmstatus
();
6504 foreach my $id (keys %$idlist) {
6505 my $d = $idlist->{$id};
6506 if (defined($running)) {
6507 next if $d->{template
};
6508 next if $running && $d->{status
} ne 'running';
6509 next if !$running && $d->{status
} eq 'running';
6518 return &$complete_vmid_full();
6521 sub complete_vmid_stopped
{
6522 return &$complete_vmid_full(0);
6525 sub complete_vmid_running
{
6526 return &$complete_vmid_full(1);
6529 sub complete_storage
{
6531 my $cfg = PVE
::Storage
::config
();
6532 my $ids = $cfg->{ids
};
6535 foreach my $sid (keys %$ids) {
6536 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6537 next if !$ids->{$sid}->{content
}->{images
};