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] [,detect_zeroes=on|off] [,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] [,detect_zeroes=on|off] [,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] [,detect_zeroes=on|off] [,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] [,detect_zeroes=on|off] [,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][,detect_zeroes=on|off]
886 # [,iothread=on][,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|detect_zeroes|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->{detect_zeroes
} && $res->{detect_zeroes
} !~ m/^(on|off)$/;
946 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
947 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
949 return undef if $res->{mbps_rd
} && $res->{mbps
};
950 return undef if $res->{mbps_wr
} && $res->{mbps
};
952 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
953 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
955 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
956 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
957 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
959 return undef if $res->{iops_rd
} && $res->{iops
};
960 return undef if $res->{iops_wr
} && $res->{iops
};
963 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
964 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
965 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
966 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
967 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
968 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
971 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
974 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
975 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
976 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
977 return undef if $res->{interface
} eq 'virtio';
980 # rerror does not work with scsi drives
981 if ($res->{rerror
}) {
982 return undef if $res->{interface
} eq 'scsi';
988 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);
991 my ($vmid, $drive) = @_;
994 foreach my $o (@qemu_drive_options, qw(mbps mbps_rd mbps_wr mbps_max mbps_rd_max mbps_wr_max backup iothread queues detect_zeroes)) {
995 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
998 if ($drive->{size
}) {
999 $opts .= ",size=" . &$format_size($drive->{size
});
1002 if (my $model = $drive->{model
}) {
1003 $opts .= ",model=$model";
1006 return "$drive->{file}$opts";
1010 my($fh, $noerr) = @_;
1013 my $SG_GET_VERSION_NUM = 0x2282;
1015 my $versionbuf = "\x00" x
8;
1016 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1018 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1021 my $version = unpack("I", $versionbuf);
1022 if ($version < 30000) {
1023 die "scsi generic interface too old\n" if !$noerr;
1027 my $buf = "\x00" x
36;
1028 my $sensebuf = "\x00" x
8;
1029 my $cmd = pack("C x3 C x1", 0x12, 36);
1031 # see /usr/include/scsi/sg.h
1032 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";
1034 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1035 length($sensebuf), 0, length($buf), $buf,
1036 $cmd, $sensebuf, 6000);
1038 $ret = ioctl($fh, $SG_IO, $packet);
1040 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1044 my @res = unpack($sg_io_hdr_t, $packet);
1045 if ($res[17] || $res[18]) {
1046 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1051 (my $byte0, my $byte1, $res->{vendor
},
1052 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1054 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1055 $res->{type
} = $byte0 & 31;
1063 my $fh = IO
::File-
>new("+<$path") || return undef;
1064 my $res = scsi_inquiry
($fh, 1);
1070 sub machine_type_is_q35
{
1073 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1076 sub print_tabletdevice_full
{
1079 my $q35 = machine_type_is_q35
($conf);
1081 # we use uhci for old VMs because tablet driver was buggy in older qemu
1082 my $usbbus = $q35 ?
"ehci" : "uhci";
1084 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1087 sub print_drivedevice_full
{
1088 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1093 if ($drive->{interface
} eq 'virtio') {
1094 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1095 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1096 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1097 } elsif ($drive->{interface
} eq 'scsi') {
1099 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1100 my $unit = $drive->{index} % $maxdev;
1101 my $devicetype = 'hd';
1103 if (drive_is_cdrom
($drive)) {
1106 if ($drive->{file
} =~ m
|^/|) {
1107 $path = $drive->{file
};
1109 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1112 if($path =~ m/^iscsi\:\/\
//){
1113 $devicetype = 'generic';
1115 if (my $info = path_is_scsi
($path)) {
1116 if ($info->{type
} == 0) {
1117 $devicetype = 'block';
1118 } elsif ($info->{type
} == 1) { # tape
1119 $devicetype = 'generic';
1125 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1126 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1128 $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}";
1131 } elsif ($drive->{interface
} eq 'ide'){
1133 my $controller = int($drive->{index} / $maxdev);
1134 my $unit = $drive->{index} % $maxdev;
1135 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1137 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1138 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1139 $device .= ",model=$model";
1141 } elsif ($drive->{interface
} eq 'sata'){
1142 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1143 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1144 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1145 } elsif ($drive->{interface
} eq 'usb') {
1147 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1149 die "unsupported interface type";
1152 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1157 sub get_initiator_name
{
1160 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1161 while (defined(my $line = <$fh>)) {
1162 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1171 sub print_drive_full
{
1172 my ($storecfg, $vmid, $drive) = @_;
1175 my $volid = $drive->{file
};
1178 if (drive_is_cdrom
($drive)) {
1179 $path = get_iso_path
($storecfg, $vmid, $volid);
1181 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1183 $path = PVE
::Storage
::path
($storecfg, $volid);
1184 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1185 $format = qemu_img_format
($scfg, $volname);
1192 foreach my $o (@qemu_drive_options) {
1193 next if $o eq 'bootindex';
1194 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1197 $opts .= ",format=$format" if $format && !$drive->{format
};
1199 foreach my $o (qw(bps bps_rd bps_wr)) {
1200 my $v = $drive->{"m$o"};
1201 $opts .= ",$o=" . int($v*1024*1024) if $v;
1204 my $cache_direct = 0;
1206 if (my $cache = $drive->{cache
}) {
1207 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1208 } elsif (!drive_is_cdrom
($drive)) {
1209 $opts .= ",cache=none";
1213 # aio native works only with O_DIRECT
1214 if (!$drive->{aio
}) {
1216 $opts .= ",aio=native";
1218 $opts .= ",aio=threads";
1222 if (!drive_is_cdrom
($drive)) {
1224 if ($drive->{detect_zeroes
} && $drive->{detect_zeroes
} eq 'off') {
1225 $detectzeroes = 'off';
1226 } elsif ($drive->{discard
}) {
1227 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1229 # This used to be our default with discard not being specified:
1230 $detectzeroes = 'on';
1232 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1235 my $pathinfo = $path ?
"file=$path," : '';
1237 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1240 sub print_netdevice_full
{
1241 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1243 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1245 my $device = $net->{model
};
1246 if ($net->{model
} eq 'virtio') {
1247 $device = 'virtio-net-pci';
1250 my $pciaddr = print_pci_addr
("$netid", $bridges);
1251 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1252 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1253 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1254 my $vectors = $net->{queues
} * 2 + 2;
1255 $tmpstr .= ",vectors=$vectors,mq=on";
1257 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1259 if ($use_old_bios_files) {
1261 if ($device eq 'virtio-net-pci') {
1262 $romfile = 'pxe-virtio.rom';
1263 } elsif ($device eq 'e1000') {
1264 $romfile = 'pxe-e1000.rom';
1265 } elsif ($device eq 'ne2k') {
1266 $romfile = 'pxe-ne2k_pci.rom';
1267 } elsif ($device eq 'pcnet') {
1268 $romfile = 'pxe-pcnet.rom';
1269 } elsif ($device eq 'rtl8139') {
1270 $romfile = 'pxe-rtl8139.rom';
1272 $tmpstr .= ",romfile=$romfile" if $romfile;
1278 sub print_netdev_full
{
1279 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1282 if ($netid =~ m/^net(\d+)$/) {
1286 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1288 my $ifname = "tap${vmid}i$i";
1290 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1291 die "interface name '$ifname' is too long (max 15 character)\n"
1292 if length($ifname) >= 16;
1294 my $vhostparam = '';
1295 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1297 my $vmname = $conf->{name
} || "vm$vmid";
1300 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1302 if ($net->{bridge
}) {
1303 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1305 $netdev = "type=user,id=$netid,hostname=$vmname";
1308 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1313 sub drive_is_cdrom
{
1316 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1325 foreach my $kvp (split(/,/, $data)) {
1327 if ($kvp =~ m/^memory=(\S+)$/) {
1328 $res->{memory
} = $1;
1329 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1330 $res->{policy
} = $1;
1331 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1332 $res->{cpus
}->{start
} = $1;
1333 $res->{cpus
}->{end
} = $3;
1334 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1335 $res->{hostnodes
}->{start
} = $1;
1336 $res->{hostnodes
}->{end
} = $3;
1348 return undef if !$value;
1351 my @list = split(/,/, $value);
1355 foreach my $kv (@list) {
1357 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1360 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1363 my $pcidevices = lspci
($2);
1364 $res->{pciid
} = $pcidevices->{$2};
1366 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1367 $res->{rombar
} = $1;
1368 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1369 $res->{'x-vga'} = $1;
1370 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1371 $res->{pcie
} = 1 if $1 == 1;
1373 warn "unknown hostpci setting '$kv'\n";
1377 return undef if !$found;
1382 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1388 foreach my $kvp (split(/,/, $data)) {
1390 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) {
1392 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1393 $res->{model
} = $model;
1394 $res->{macaddr
} = $mac;
1395 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1396 $res->{bridge
} = $1;
1397 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1398 $res->{queues
} = $1;
1399 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1401 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1403 } elsif ($kvp =~ m/^firewall=([01])$/) {
1404 $res->{firewall
} = $1;
1405 } elsif ($kvp =~ m/^link_down=([01])$/) {
1406 $res->{link_down
} = $1;
1413 return undef if !$res->{model
};
1421 my $res = "$net->{model}";
1422 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1423 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1424 $res .= ",rate=$net->{rate}" if $net->{rate
};
1425 $res .= ",tag=$net->{tag}" if $net->{tag
};
1426 $res .= ",firewall=1" if $net->{firewall
};
1427 $res .= ",link_down=1" if $net->{link_down
};
1428 $res .= ",queues=$net->{queues}" if $net->{queues
};
1433 sub add_random_macs
{
1434 my ($settings) = @_;
1436 foreach my $opt (keys %$settings) {
1437 next if $opt !~ m/^net(\d+)$/;
1438 my $net = parse_net
($settings->{$opt});
1440 $settings->{$opt} = print_net
($net);
1444 sub add_unused_volume
{
1445 my ($config, $volid) = @_;
1448 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1449 my $test = "unused$ind";
1450 if (my $vid = $config->{$test}) {
1451 return if $vid eq $volid; # do not add duplicates
1457 die "To many unused volume - please delete them first.\n" if !$key;
1459 $config->{$key} = $volid;
1464 sub vm_is_volid_owner
{
1465 my ($storecfg, $vmid, $volid) = @_;
1467 if ($volid !~ m
|^/|) {
1469 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1470 if ($owner && ($owner == $vmid)) {
1478 sub split_flagged_list
{
1479 my $text = shift || '';
1480 $text =~ s/[,;]/ /g;
1482 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1485 sub join_flagged_list
{
1486 my ($how, $lst) = @_;
1487 join $how, map { $lst->{$_} . $_ } keys %$lst;
1490 sub vmconfig_delete_pending_option
{
1491 my ($conf, $key, $force) = @_;
1493 delete $conf->{pending
}->{$key};
1494 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1495 $pending_delete_hash->{$key} = $force ?
'!' : '';
1496 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1499 sub vmconfig_undelete_pending_option
{
1500 my ($conf, $key) = @_;
1502 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1503 delete $pending_delete_hash->{$key};
1505 if (%$pending_delete_hash) {
1506 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1508 delete $conf->{pending
}->{delete};
1512 sub vmconfig_register_unused_drive
{
1513 my ($storecfg, $vmid, $conf, $drive) = @_;
1515 if (!drive_is_cdrom
($drive)) {
1516 my $volid = $drive->{file
};
1517 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1518 add_unused_volume
($conf, $volid, $vmid);
1523 sub vmconfig_cleanup_pending
{
1526 # remove pending changes when nothing changed
1528 foreach my $opt (keys %{$conf->{pending
}}) {
1529 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1531 delete $conf->{pending
}->{$opt};
1535 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1536 my $pending_delete_hash = {};
1537 while (my ($opt, $force) = each %$current_delete_hash) {
1538 if (defined($conf->{$opt})) {
1539 $pending_delete_hash->{$opt} = $force;
1545 if (%$pending_delete_hash) {
1546 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1548 delete $conf->{pending
}->{delete};
1554 my $valid_smbios1_options = {
1555 manufacturer
=> '\S+',
1559 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1564 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1570 foreach my $kvp (split(/,/, $data)) {
1571 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1572 my ($k, $v) = split(/=/, $kvp);
1573 return undef if !defined($k) || !defined($v);
1574 return undef if !$valid_smbios1_options->{$k};
1575 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1586 foreach my $k (keys %$smbios1) {
1587 next if !defined($smbios1->{$k});
1588 next if !$valid_smbios1_options->{$k};
1589 $data .= ',' if $data;
1590 $data .= "$k=$smbios1->{$k}";
1595 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1596 sub verify_smbios1
{
1597 my ($value, $noerr) = @_;
1599 return $value if parse_smbios1
($value);
1601 return undef if $noerr;
1603 die "unable to parse smbios (type 1) options\n";
1606 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1607 sub verify_bootdisk
{
1608 my ($value, $noerr) = @_;
1610 return $value if valid_drivename
($value);
1612 return undef if $noerr;
1614 die "invalid boot disk '$value'\n";
1617 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1619 my ($value, $noerr) = @_;
1621 return $value if parse_numa
($value);
1623 return undef if $noerr;
1625 die "unable to parse numa options\n";
1628 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1630 my ($value, $noerr) = @_;
1632 return $value if parse_net
($value);
1634 return undef if $noerr;
1636 die "unable to parse network options\n";
1639 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1641 my ($value, $noerr) = @_;
1643 return $value if parse_drive
(undef, $value);
1645 return undef if $noerr;
1647 die "unable to parse drive options\n";
1650 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1651 sub verify_hostpci
{
1652 my ($value, $noerr) = @_;
1654 return $value if parse_hostpci
($value);
1656 return undef if $noerr;
1658 die "unable to parse pci id\n";
1661 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1662 sub verify_watchdog
{
1663 my ($value, $noerr) = @_;
1665 return $value if parse_watchdog
($value);
1667 return undef if $noerr;
1669 die "unable to parse watchdog options\n";
1672 sub parse_watchdog
{
1675 return undef if !$value;
1679 foreach my $p (split(/,/, $value)) {
1680 next if $p =~ m/^\s*$/;
1682 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1684 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1685 $res->{action
} = $2;
1694 sub parse_usb_device
{
1697 return undef if !$value;
1699 my @dl = split(/,/, $value);
1703 foreach my $v (@dl) {
1704 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1706 $res->{vendorid
} = $2;
1707 $res->{productid
} = $4;
1708 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1710 $res->{hostbus
} = $1;
1711 $res->{hostport
} = $2;
1712 } elsif ($v =~ m/^spice$/) {
1719 return undef if !$found;
1724 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1725 sub verify_usb_device
{
1726 my ($value, $noerr) = @_;
1728 return $value if parse_usb_device
($value);
1730 return undef if $noerr;
1732 die "unable to parse usb device\n";
1735 # add JSON properties for create and set function
1736 sub json_config_properties
{
1739 foreach my $opt (keys %$confdesc) {
1740 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1741 $prop->{$opt} = $confdesc->{$opt};
1748 my ($key, $value) = @_;
1750 die "unknown setting '$key'\n" if !$confdesc->{$key};
1752 my $type = $confdesc->{$key}->{type
};
1754 if (!defined($value)) {
1755 die "got undefined value\n";
1758 if ($value =~ m/[\n\r]/) {
1759 die "property contains a line feed\n";
1762 if ($type eq 'boolean') {
1763 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1764 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1765 die "type check ('boolean') failed - got '$value'\n";
1766 } elsif ($type eq 'integer') {
1767 return int($1) if $value =~ m/^(\d+)$/;
1768 die "type check ('integer') failed - got '$value'\n";
1769 } elsif ($type eq 'number') {
1770 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1771 die "type check ('number') failed - got '$value'\n";
1772 } elsif ($type eq 'string') {
1773 if (my $fmt = $confdesc->{$key}->{format
}) {
1774 if ($fmt eq 'pve-qm-drive') {
1775 # special case - we need to pass $key to parse_drive()
1776 my $drive = parse_drive
($key, $value);
1777 return $value if $drive;
1778 die "unable to parse drive options\n";
1780 PVE
::JSONSchema
::check_format
($fmt, $value);
1783 $value =~ s/^\"(.*)\"$/$1/;
1786 die "internal error"
1790 sub lock_config_full
{
1791 my ($vmid, $timeout, $code, @param) = @_;
1793 my $filename = config_file_lock
($vmid);
1795 my $res = lock_file
($filename, $timeout, $code, @param);
1802 sub lock_config_mode
{
1803 my ($vmid, $timeout, $shared, $code, @param) = @_;
1805 my $filename = config_file_lock
($vmid);
1807 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1815 my ($vmid, $code, @param) = @_;
1817 return lock_config_full
($vmid, 10, $code, @param);
1820 sub cfs_config_path
{
1821 my ($vmid, $node) = @_;
1823 $node = $nodename if !$node;
1824 return "nodes/$node/qemu-server/$vmid.conf";
1827 sub check_iommu_support
{
1828 #fixme : need to check IOMMU support
1829 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1837 my ($vmid, $node) = @_;
1839 my $cfspath = cfs_config_path
($vmid, $node);
1840 return "/etc/pve/$cfspath";
1843 sub config_file_lock
{
1846 return "$lock_dir/lock-$vmid.conf";
1852 my $conf = config_file
($vmid);
1853 utime undef, undef, $conf;
1857 my ($storecfg, $vmid, $keep_empty_config) = @_;
1859 my $conffile = config_file
($vmid);
1861 my $conf = load_config
($vmid);
1865 # only remove disks owned by this VM
1866 foreach_drive
($conf, sub {
1867 my ($ds, $drive) = @_;
1869 return if drive_is_cdrom
($drive);
1871 my $volid = $drive->{file
};
1873 return if !$volid || $volid =~ m
|^/|;
1875 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1876 return if !$path || !$owner || ($owner != $vmid);
1878 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1881 if ($keep_empty_config) {
1882 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1887 # also remove unused disk
1889 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1892 PVE
::Storage
::foreach_volid
($dl, sub {
1893 my ($volid, $sid, $volname, $d) = @_;
1894 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1904 my ($vmid, $node) = @_;
1906 my $cfspath = cfs_config_path
($vmid, $node);
1908 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1910 die "no such VM ('$vmid')\n" if !defined($conf);
1915 sub parse_vm_config
{
1916 my ($filename, $raw) = @_;
1918 return undef if !defined($raw);
1921 digest
=> Digest
::SHA
::sha1_hex
($raw),
1926 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1927 || die "got strange filename '$filename'";
1935 my @lines = split(/\n/, $raw);
1936 foreach my $line (@lines) {
1937 next if $line =~ m/^\s*$/;
1939 if ($line =~ m/^\[PENDING\]\s*$/i) {
1940 $section = 'pending';
1941 if (defined($descr)) {
1943 $conf->{description
} = $descr;
1946 $conf = $res->{$section} = {};
1949 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1951 if (defined($descr)) {
1953 $conf->{description
} = $descr;
1956 $conf = $res->{snapshots
}->{$section} = {};
1960 if ($line =~ m/^\#(.*)\s*$/) {
1961 $descr = '' if !defined($descr);
1962 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1966 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1967 $descr = '' if !defined($descr);
1968 $descr .= PVE
::Tools
::decode_text
($2);
1969 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1970 $conf->{snapstate
} = $1;
1971 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1974 $conf->{$key} = $value;
1975 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1977 if ($section eq 'pending') {
1978 $conf->{delete} = $value; # we parse this later
1980 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1982 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1985 eval { $value = check_type
($key, $value); };
1987 warn "vm $vmid - unable to parse value of '$key' - $@";
1989 my $fmt = $confdesc->{$key}->{format
};
1990 if ($fmt && $fmt eq 'pve-qm-drive') {
1991 my $v = parse_drive
($key, $value);
1992 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1993 $v->{file
} = $volid;
1994 $value = print_drive
($vmid, $v);
1996 warn "vm $vmid - unable to parse value of '$key'\n";
2001 if ($key eq 'cdrom') {
2002 $conf->{ide2
} = $value;
2004 $conf->{$key} = $value;
2010 if (defined($descr)) {
2012 $conf->{description
} = $descr;
2014 delete $res->{snapstate
}; # just to be sure
2019 sub write_vm_config
{
2020 my ($filename, $conf) = @_;
2022 delete $conf->{snapstate
}; # just to be sure
2024 if ($conf->{cdrom
}) {
2025 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2026 $conf->{ide2
} = $conf->{cdrom
};
2027 delete $conf->{cdrom
};
2030 # we do not use 'smp' any longer
2031 if ($conf->{sockets
}) {
2032 delete $conf->{smp
};
2033 } elsif ($conf->{smp
}) {
2034 $conf->{sockets
} = $conf->{smp
};
2035 delete $conf->{cores
};
2036 delete $conf->{smp
};
2039 my $used_volids = {};
2041 my $cleanup_config = sub {
2042 my ($cref, $pending, $snapname) = @_;
2044 foreach my $key (keys %$cref) {
2045 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2046 $key eq 'snapstate' || $key eq 'pending';
2047 my $value = $cref->{$key};
2048 if ($key eq 'delete') {
2049 die "propertry 'delete' is only allowed in [PENDING]\n"
2051 # fixme: check syntax?
2054 eval { $value = check_type
($key, $value); };
2055 die "unable to parse value of '$key' - $@" if $@;
2057 $cref->{$key} = $value;
2059 if (!$snapname && valid_drivename
($key)) {
2060 my $drive = parse_drive
($key, $value);
2061 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2066 &$cleanup_config($conf);
2068 &$cleanup_config($conf->{pending
}, 1);
2070 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2071 die "internal error" if $snapname eq 'pending';
2072 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2075 # remove 'unusedX' settings if we re-add a volume
2076 foreach my $key (keys %$conf) {
2077 my $value = $conf->{$key};
2078 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2079 delete $conf->{$key};
2083 my $generate_raw_config = sub {
2084 my ($conf, $pending) = @_;
2088 # add description as comment to top of file
2089 if (defined(my $descr = $conf->{description
})) {
2091 foreach my $cl (split(/\n/, $descr)) {
2092 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2095 $raw .= "#\n" if $pending;
2099 foreach my $key (sort keys %$conf) {
2100 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2101 $raw .= "$key: $conf->{$key}\n";
2106 my $raw = &$generate_raw_config($conf);
2108 if (scalar(keys %{$conf->{pending
}})){
2109 $raw .= "\n[PENDING]\n";
2110 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2113 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2114 $raw .= "\n[$snapname]\n";
2115 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2121 sub update_config_nolock
{
2122 my ($vmid, $conf, $skiplock) = @_;
2124 check_lock
($conf) if !$skiplock;
2126 my $cfspath = cfs_config_path
($vmid);
2128 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2132 my ($vmid, $conf, $skiplock) = @_;
2134 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2141 # we use static defaults from our JSON schema configuration
2142 foreach my $key (keys %$confdesc) {
2143 if (defined(my $default = $confdesc->{$key}->{default})) {
2144 $res->{$key} = $default;
2148 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2149 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2155 my $vmlist = PVE
::Cluster
::get_vmlist
();
2157 return $res if !$vmlist || !$vmlist->{ids
};
2158 my $ids = $vmlist->{ids
};
2160 foreach my $vmid (keys %$ids) {
2161 my $d = $ids->{$vmid};
2162 next if !$d->{node
} || $d->{node
} ne $nodename;
2163 next if !$d->{type
} || $d->{type
} ne 'qemu';
2164 $res->{$vmid}->{exists} = 1;
2169 # test if VM uses local resources (to prevent migration)
2170 sub check_local_resources
{
2171 my ($conf, $noerr) = @_;
2175 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2176 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2178 foreach my $k (keys %$conf) {
2179 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2180 # sockets are safe: they will recreated be on the target side post-migrate
2181 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2182 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2185 die "VM uses local resources\n" if $loc_res && !$noerr;
2190 # check if used storages are available on all nodes (use by migrate)
2191 sub check_storage_availability
{
2192 my ($storecfg, $conf, $node) = @_;
2194 foreach_drive
($conf, sub {
2195 my ($ds, $drive) = @_;
2197 my $volid = $drive->{file
};
2200 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2203 # check if storage is available on both nodes
2204 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2205 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2209 # list nodes where all VM images are available (used by has_feature API)
2211 my ($conf, $storecfg) = @_;
2213 my $nodelist = PVE
::Cluster
::get_nodelist
();
2214 my $nodehash = { map { $_ => 1 } @$nodelist };
2215 my $nodename = PVE
::INotify
::nodename
();
2217 foreach_drive
($conf, sub {
2218 my ($ds, $drive) = @_;
2220 my $volid = $drive->{file
};
2223 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2225 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2226 if ($scfg->{disable
}) {
2228 } elsif (my $avail = $scfg->{nodes
}) {
2229 foreach my $node (keys %$nodehash) {
2230 delete $nodehash->{$node} if !$avail->{$node};
2232 } elsif (!$scfg->{shared
}) {
2233 foreach my $node (keys %$nodehash) {
2234 delete $nodehash->{$node} if $node ne $nodename
2246 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2250 my ($pidfile, $pid) = @_;
2252 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2256 return undef if !$line;
2257 my @param = split(/\0/, $line);
2259 my $cmd = $param[0];
2260 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2262 for (my $i = 0; $i < scalar (@param); $i++) {
2265 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2266 my $p = $param[$i+1];
2267 return 1 if $p && ($p eq $pidfile);
2276 my ($vmid, $nocheck, $node) = @_;
2278 my $filename = config_file
($vmid, $node);
2280 die "unable to find configuration file for VM $vmid - no such machine\n"
2281 if !$nocheck && ! -f
$filename;
2283 my $pidfile = pidfile_name
($vmid);
2285 if (my $fd = IO
::File-
>new("<$pidfile")) {
2290 my $mtime = $st->mtime;
2291 if ($mtime > time()) {
2292 warn "file '$filename' modified in future\n";
2295 if ($line =~ m/^(\d+)$/) {
2297 if (check_cmdline
($pidfile, $pid)) {
2298 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2310 my $vzlist = config_list
();
2312 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2314 while (defined(my $de = $fd->read)) {
2315 next if $de !~ m/^(\d+)\.pid$/;
2317 next if !defined($vzlist->{$vmid});
2318 if (my $pid = check_running
($vmid)) {
2319 $vzlist->{$vmid}->{pid
} = $pid;
2327 my ($storecfg, $conf) = @_;
2329 my $bootdisk = $conf->{bootdisk
};
2330 return undef if !$bootdisk;
2331 return undef if !valid_drivename
($bootdisk);
2333 return undef if !$conf->{$bootdisk};
2335 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2336 return undef if !defined($drive);
2338 return undef if drive_is_cdrom
($drive);
2340 my $volid = $drive->{file
};
2341 return undef if !$volid;
2343 return $drive->{size
};
2346 my $last_proc_pid_stat;
2348 # get VM status information
2349 # This must be fast and should not block ($full == false)
2350 # We only query KVM using QMP if $full == true (this can be slow)
2352 my ($opt_vmid, $full) = @_;
2356 my $storecfg = PVE
::Storage
::config
();
2358 my $list = vzlist
();
2359 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2361 my $cpucount = $cpuinfo->{cpus
} || 1;
2363 foreach my $vmid (keys %$list) {
2364 next if $opt_vmid && ($vmid ne $opt_vmid);
2366 my $cfspath = cfs_config_path
($vmid);
2367 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2370 $d->{pid
} = $list->{$vmid}->{pid
};
2372 # fixme: better status?
2373 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2375 my $size = disksize
($storecfg, $conf);
2376 if (defined($size)) {
2377 $d->{disk
} = 0; # no info available
2378 $d->{maxdisk
} = $size;
2384 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2385 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2386 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2388 $d->{name
} = $conf->{name
} || "VM $vmid";
2389 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2391 if ($conf->{balloon
}) {
2392 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2393 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2404 $d->{diskwrite
} = 0;
2406 $d->{template
} = is_template
($conf);
2411 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2412 foreach my $dev (keys %$netdev) {
2413 next if $dev !~ m/^tap([1-9]\d*)i/;
2415 my $d = $res->{$vmid};
2418 $d->{netout
} += $netdev->{$dev}->{receive
};
2419 $d->{netin
} += $netdev->{$dev}->{transmit
};
2422 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2423 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2428 my $ctime = gettimeofday
;
2430 foreach my $vmid (keys %$list) {
2432 my $d = $res->{$vmid};
2433 my $pid = $d->{pid
};
2436 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2437 next if !$pstat; # not running
2439 my $used = $pstat->{utime} + $pstat->{stime
};
2441 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2443 if ($pstat->{vsize
}) {
2444 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2447 my $old = $last_proc_pid_stat->{$pid};
2449 $last_proc_pid_stat->{$pid} = {
2457 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2459 if ($dtime > 1000) {
2460 my $dutime = $used - $old->{used
};
2462 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2463 $last_proc_pid_stat->{$pid} = {
2469 $d->{cpu
} = $old->{cpu
};
2473 return $res if !$full;
2475 my $qmpclient = PVE
::QMPClient-
>new();
2477 my $ballooncb = sub {
2478 my ($vmid, $resp) = @_;
2480 my $info = $resp->{'return'};
2481 return if !$info->{max_mem
};
2483 my $d = $res->{$vmid};
2485 # use memory assigned to VM
2486 $d->{maxmem
} = $info->{max_mem
};
2487 $d->{balloon
} = $info->{actual
};
2489 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2490 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2491 $d->{freemem
} = $info->{free_mem
};
2494 $d->{ballooninfo
} = $info;
2497 my $blockstatscb = sub {
2498 my ($vmid, $resp) = @_;
2499 my $data = $resp->{'return'} || [];
2500 my $totalrdbytes = 0;
2501 my $totalwrbytes = 0;
2503 for my $blockstat (@$data) {
2504 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2505 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2507 $blockstat->{device
} =~ s/drive-//;
2508 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2510 $res->{$vmid}->{diskread
} = $totalrdbytes;
2511 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2514 my $statuscb = sub {
2515 my ($vmid, $resp) = @_;
2517 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2518 # this fails if ballon driver is not loaded, so this must be
2519 # the last commnand (following command are aborted if this fails).
2520 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2522 my $status = 'unknown';
2523 if (!defined($status = $resp->{'return'}->{status
})) {
2524 warn "unable to get VM status\n";
2528 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2531 foreach my $vmid (keys %$list) {
2532 next if $opt_vmid && ($vmid ne $opt_vmid);
2533 next if !$res->{$vmid}->{pid
}; # not running
2534 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2537 $qmpclient->queue_execute(undef, 1);
2539 foreach my $vmid (keys %$list) {
2540 next if $opt_vmid && ($vmid ne $opt_vmid);
2541 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2548 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2551 my $current_size = 1024;
2552 my $dimm_size = 512;
2553 return if $current_size == $memory;
2555 for (my $j = 0; $j < 8; $j++) {
2556 for (my $i = 0; $i < 32; $i++) {
2557 my $name = "dimm${dimm_id}";
2559 my $numanode = $i % $sockets;
2560 $current_size += $dimm_size;
2561 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2562 return $current_size if $current_size >= $memory;
2568 sub foreach_reverse_dimm
{
2569 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2572 my $current_size = 4177920;
2573 my $dimm_size = 65536;
2574 return if $current_size == $memory;
2576 for (my $j = 0; $j < 8; $j++) {
2577 for (my $i = 0; $i < 32; $i++) {
2578 my $name = "dimm${dimm_id}";
2580 my $numanode = $i % $sockets;
2581 $current_size -= $dimm_size;
2582 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2583 return $current_size if $current_size <= $memory;
2590 my ($conf, $func) = @_;
2592 foreach my $ds (keys %$conf) {
2593 next if !valid_drivename
($ds);
2595 my $drive = parse_drive
($ds, $conf->{$ds});
2598 &$func($ds, $drive);
2603 my ($conf, $func) = @_;
2607 my $test_volid = sub {
2608 my ($volid, $is_cdrom) = @_;
2612 $volhash->{$volid} = $is_cdrom || 0;
2615 foreach_drive
($conf, sub {
2616 my ($ds, $drive) = @_;
2617 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2620 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2621 my $snap = $conf->{snapshots
}->{$snapname};
2622 &$test_volid($snap->{vmstate
}, 0);
2623 foreach_drive
($snap, sub {
2624 my ($ds, $drive) = @_;
2625 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2629 foreach my $volid (keys %$volhash) {
2630 &$func($volid, $volhash->{$volid});
2634 sub vga_conf_has_spice
{
2637 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2642 sub config_to_command
{
2643 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2646 my $globalFlags = [];
2647 my $machineFlags = [];
2653 my $kvmver = kvm_user_version
();
2654 my $vernum = 0; # unknown
2655 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2656 $vernum = $1*1000000+$2*1000;
2657 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2658 $vernum = $1*1000000+$2*1000+$3;
2661 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2663 my $have_ovz = -f
'/proc/vz/vestat';
2665 my $q35 = machine_type_is_q35
($conf);
2666 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2667 my $machine_type = $forcemachine || $conf->{machine
};
2668 my $use_old_bios_files = undef;
2669 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2671 my $cpuunits = defined($conf->{cpuunits
}) ?
2672 $conf->{cpuunits
} : $defaults->{cpuunits
};
2674 push @$cmd, '/usr/bin/systemd-run';
2675 push @$cmd, '--scope';
2676 push @$cmd, '--slice', "qemu";
2677 push @$cmd, '--unit', $vmid;
2678 # set KillMode=none, so that systemd don't kill those scopes
2679 # at shutdown (pve-manager service should stop the VMs instead)
2680 push @$cmd, '-p', "KillMode=none";
2681 push @$cmd, '-p', "CPUShares=$cpuunits";
2682 if ($conf->{cpulimit
}) {
2683 my $cpulimit = int($conf->{cpulimit
} * 100);
2684 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2687 push @$cmd, '/usr/bin/kvm';
2689 push @$cmd, '-id', $vmid;
2693 my $qmpsocket = qmp_socket
($vmid);
2694 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2695 push @$cmd, '-mon', "chardev=qmp,mode=control";
2697 my $socket = vnc_socket
($vmid);
2698 push @$cmd, '-vnc', "unix:$socket,x509,password";
2700 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2702 push @$cmd, '-daemonize';
2704 if ($conf->{smbios1
}) {
2705 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2708 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2709 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2710 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2711 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2712 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2713 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2714 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2718 # the q35 chipset support native usb2, so we enable usb controller
2719 # by default for this machine type
2720 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2722 $pciaddr = print_pci_addr
("piix3", $bridges);
2723 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2726 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2727 next if !$conf->{"usb$i"};
2730 # include usb device config
2731 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2734 my $vga = $conf->{vga
};
2736 my $qxlnum = vga_conf_has_spice
($vga);
2737 $vga = 'qxl' if $qxlnum;
2740 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2741 $conf->{ostype
} eq 'win7' ||
2742 $conf->{ostype
} eq 'w2k8')) {
2749 # enable absolute mouse coordinates (needed by vnc)
2751 if (defined($conf->{tablet
})) {
2752 $tablet = $conf->{tablet
};
2754 $tablet = $defaults->{tablet
};
2755 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2756 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2759 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2762 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2763 my $d = parse_hostpci
($conf->{"hostpci$i"});
2766 my $pcie = $d->{pcie
};
2768 die "q35 machine model is not enabled" if !$q35;
2769 $pciaddr = print_pcie_addr
("hostpci$i");
2771 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2774 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2775 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2776 if ($xvga && $xvga ne '') {
2777 push @$cpuFlags, 'kvm=off';
2780 my $pcidevices = $d->{pciid
};
2781 my $multifunction = 1 if @$pcidevices > 1;
2784 foreach my $pcidevice (@$pcidevices) {
2786 my $id = "hostpci$i";
2787 $id .= ".$j" if $multifunction;
2788 my $addr = $pciaddr;
2789 $addr .= ".$j" if $multifunction;
2790 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2793 $devicestr .= "$rombar$xvga";
2794 $devicestr .= ",multifunction=on" if $multifunction;
2797 push @$devices, '-device', $devicestr;
2803 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2804 my $d = parse_usb_device
($conf->{"usb$i"});
2806 if ($d->{vendorid
} && $d->{productid
}) {
2807 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2808 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2809 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2810 } elsif ($d->{spice
}) {
2811 # usb redir support for spice
2812 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2813 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2818 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2819 if (my $path = $conf->{"serial$i"}) {
2820 if ($path eq 'socket') {
2821 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2822 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2823 push @$devices, '-device', "isa-serial,chardev=serial$i";
2825 die "no such serial device\n" if ! -c
$path;
2826 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2827 push @$devices, '-device', "isa-serial,chardev=serial$i";
2833 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2834 if (my $path = $conf->{"parallel$i"}) {
2835 die "no such parallel device\n" if ! -c
$path;
2836 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2837 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2838 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2842 my $vmname = $conf->{name
} || "vm$vmid";
2844 push @$cmd, '-name', $vmname;
2847 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2848 $sockets = $conf->{sockets
} if $conf->{sockets
};
2850 my $cores = $conf->{cores
} || 1;
2852 my $maxcpus = $sockets * $cores;
2854 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2856 my $allowed_vcpus = $cpuinfo->{cpus
};
2858 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2859 if ($allowed_vcpus < $maxcpus);
2861 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2863 push @$cmd, '-nodefaults';
2865 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2867 my $bootindex_hash = {};
2869 foreach my $o (split(//, $bootorder)) {
2870 $bootindex_hash->{$o} = $i*100;
2874 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2876 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2878 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2880 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2883 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2885 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2886 my $useLocaltime = $conf->{localtime};
2888 if (my $ost = $conf->{ostype
}) {
2889 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2891 if ($ost =~ m/^w/) { # windows
2892 $useLocaltime = 1 if !defined($conf->{localtime});
2894 # use time drift fix when acpi is enabled
2895 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2896 $tdf = 1 if !defined($conf->{tdf
});
2900 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2902 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2903 push @$cmd, '-no-hpet';
2904 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2905 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2906 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2907 push @$cpuFlags , 'hv_time' if !$nokvm;
2910 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2914 if ($ost eq 'win7' || $ost eq 'win8') {
2915 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2919 push @$rtcFlags, 'driftfix=slew' if $tdf;
2922 push @$machineFlags, 'accel=tcg';
2924 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2927 if ($machine_type) {
2928 push @$machineFlags, "type=${machine_type}";
2931 if ($conf->{startdate
}) {
2932 push @$rtcFlags, "base=$conf->{startdate}";
2933 } elsif ($useLocaltime) {
2934 push @$rtcFlags, 'base=localtime';
2937 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2938 $cpu = $conf->{cpu
} if $conf->{cpu
};
2940 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2942 push @$cpuFlags , '-x2apic'
2943 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2945 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2947 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2949 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2951 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2952 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2955 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2957 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2959 push @$cmd, '-cpu', $cpu;
2961 my $memory = $conf->{memory
} || $defaults->{memory
};
2962 my $static_memory = 0;
2963 my $dimm_memory = 0;
2965 if ($hotplug_features->{memory
}) {
2966 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2967 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2968 $static_memory = $STATICMEM;
2969 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2970 $dimm_memory = $memory - $static_memory;
2971 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2975 $static_memory = $memory;
2976 push @$cmd, '-m', $static_memory;
2979 if ($conf->{numa
}) {
2981 my $numa_totalmemory = undef;
2982 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2983 next if !$conf->{"numa$i"};
2984 my $numa = parse_numa
($conf->{"numa$i"});
2987 die "missing numa node$i memory value\n" if !$numa->{memory
};
2988 my $numa_memory = $numa->{memory
};
2989 $numa_totalmemory += $numa_memory;
2990 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2993 my $cpus_start = $numa->{cpus
}->{start
};
2994 die "missing numa node$i cpus\n" if !defined($cpus_start);
2995 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2996 my $cpus = $cpus_start;
2997 if (defined($cpus_end)) {
2998 $cpus .= "-$cpus_end";
2999 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3003 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3004 if (defined($hostnodes_start)) {
3005 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3006 my $hostnodes = $hostnodes_start;
3007 if (defined($hostnodes_end)) {
3008 $hostnodes .= "-$hostnodes_end";
3009 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3012 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3013 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3014 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3018 my $policy = $numa->{policy
};
3019 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3020 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3023 push @$cmd, '-object', $numa_object;
3024 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3027 die "total memory for NUMA nodes must be equal to vm static memory\n"
3028 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3030 #if no custom tology, we split memory and cores across numa nodes
3031 if(!$numa_totalmemory) {
3033 my $numa_memory = ($static_memory / $sockets) . "M";
3035 for (my $i = 0; $i < $sockets; $i++) {
3037 my $cpustart = ($cores * $i);
3038 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3039 my $cpus = $cpustart;
3040 $cpus .= "-$cpuend" if $cpuend;
3042 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3043 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3048 if ($hotplug_features->{memory
}) {
3049 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3050 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3051 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3052 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3054 #if dimm_memory is not aligned to dimm map
3055 if($current_size > $memory) {
3056 $conf->{memory
} = $current_size;
3057 update_config_nolock
($vmid, $conf, 1);
3062 push @$cmd, '-S' if $conf->{freeze
};
3064 # set keyboard layout
3065 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3066 push @$cmd, '-k', $kb if $kb;
3069 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3070 #push @$cmd, '-soundhw', 'es1370';
3071 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3073 if($conf->{agent
}) {
3074 my $qgasocket = qmp_socket
($vmid, 1);
3075 my $pciaddr = print_pci_addr
("qga0", $bridges);
3076 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3077 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3078 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3085 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3086 for(my $i = 1; $i < $qxlnum; $i++){
3087 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3088 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3091 # assume other OS works like Linux
3092 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3093 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3097 my $pciaddr = print_pci_addr
("spice", $bridges);
3099 my $nodename = PVE
::INotify
::nodename
();
3100 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3101 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3103 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3105 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3106 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3107 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3110 # enable balloon by default, unless explicitly disabled
3111 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3112 $pciaddr = print_pci_addr
("balloon0", $bridges);
3113 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3116 if ($conf->{watchdog
}) {
3117 my $wdopts = parse_watchdog
($conf->{watchdog
});
3118 $pciaddr = print_pci_addr
("watchdog", $bridges);
3119 my $watchdog = $wdopts->{model
} || 'i6300esb';
3120 push @$devices, '-device', "$watchdog$pciaddr";
3121 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3125 my $scsicontroller = {};
3126 my $ahcicontroller = {};
3127 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3129 # Add iscsi initiator name if available
3130 if (my $initiator = get_initiator_name
()) {
3131 push @$devices, '-iscsi', "initiator-name=$initiator";
3134 foreach_drive
($conf, sub {
3135 my ($ds, $drive) = @_;
3137 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3138 push @$vollist, $drive->{file
};
3141 $use_virtio = 1 if $ds =~ m/^virtio/;
3143 if (drive_is_cdrom
($drive)) {
3144 if ($bootindex_hash->{d
}) {
3145 $drive->{bootindex
} = $bootindex_hash->{d
};
3146 $bootindex_hash->{d
} += 1;
3149 if ($bootindex_hash->{c
}) {
3150 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3151 $bootindex_hash->{c
} += 1;
3155 if($drive->{interface
} eq 'virtio'){
3156 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3159 if ($drive->{interface
} eq 'scsi') {
3161 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3163 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3164 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3167 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3168 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3169 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3173 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3174 $queues = ",num_queues=$drive->{queues}";
3177 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3178 $scsicontroller->{$controller}=1;
3181 if ($drive->{interface
} eq 'sata') {
3182 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3183 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3184 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3185 $ahcicontroller->{$controller}=1;
3188 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3189 push @$devices, '-drive',$drive_cmd;
3190 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3193 for (my $i = 0; $i < $MAX_NETS; $i++) {
3194 next if !$conf->{"net$i"};
3195 my $d = parse_net
($conf->{"net$i"});
3198 $use_virtio = 1 if $d->{model
} eq 'virtio';
3200 if ($bootindex_hash->{n
}) {
3201 $d->{bootindex
} = $bootindex_hash->{n
};
3202 $bootindex_hash->{n
} += 1;
3205 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3206 push @$devices, '-netdev', $netdevfull;
3208 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3209 push @$devices, '-device', $netdevicefull;
3214 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3219 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3221 while (my ($k, $v) = each %$bridges) {
3222 $pciaddr = print_pci_addr
("pci.$k");
3223 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3228 if ($conf->{args
}) {
3229 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3233 push @$cmd, @$devices;
3234 push @$cmd, '-rtc', join(',', @$rtcFlags)
3235 if scalar(@$rtcFlags);
3236 push @$cmd, '-machine', join(',', @$machineFlags)
3237 if scalar(@$machineFlags);
3238 push @$cmd, '-global', join(',', @$globalFlags)
3239 if scalar(@$globalFlags);
3241 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3246 return "${var_run_tmpdir}/$vmid.vnc";
3252 my $res = vm_mon_cmd
($vmid, 'query-spice');
3254 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3258 my ($vmid, $qga) = @_;
3259 my $sockettype = $qga ?
'qga' : 'qmp';
3260 return "${var_run_tmpdir}/$vmid.$sockettype";
3265 return "${var_run_tmpdir}/$vmid.pid";
3268 sub vm_devices_list
{
3271 my $res = vm_mon_cmd
($vmid, 'query-pci');
3273 foreach my $pcibus (@$res) {
3274 foreach my $device (@{$pcibus->{devices
}}) {
3275 next if !$device->{'qdev_id'};
3276 if ($device->{'pci_bridge'}) {
3277 $devices->{$device->{'qdev_id'}} = 1;
3278 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3279 next if !$bridge_device->{'qdev_id'};
3280 $devices->{$bridge_device->{'qdev_id'}} = 1;
3281 $devices->{$device->{'qdev_id'}}++;
3284 $devices->{$device->{'qdev_id'}} = 1;
3289 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3290 foreach my $block (@$resblock) {
3291 if($block->{device
} =~ m/^drive-(\S+)/){
3296 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3297 foreach my $mice (@$resmice) {
3298 if ($mice->{name
} eq 'QEMU HID Tablet') {
3299 $devices->{tablet
} = 1;
3308 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3310 my $q35 = machine_type_is_q35
($conf);
3312 my $devices_list = vm_devices_list
($vmid);
3313 return 1 if defined($devices_list->{$deviceid});
3315 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3317 if ($deviceid eq 'tablet') {
3319 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3321 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3323 qemu_iothread_add
($vmid, $deviceid, $device);
3325 qemu_driveadd
($storecfg, $vmid, $device);
3326 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3328 qemu_deviceadd
($vmid, $devicefull);
3329 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3331 eval { qemu_drivedel
($vmid, $deviceid); };
3336 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3339 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3340 my $pciaddr = print_pci_addr
($deviceid);
3341 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3343 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3345 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3346 qemu_iothread_add
($vmid, $deviceid, $device);
3347 $devicefull .= ",iothread=iothread-$deviceid";
3350 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3351 $devicefull .= ",num_queues=$device->{queues}";
3354 qemu_deviceadd
($vmid, $devicefull);
3355 qemu_deviceaddverify
($vmid, $deviceid);
3357 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3359 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3360 qemu_driveadd
($storecfg, $vmid, $device);
3362 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3363 eval { qemu_deviceadd
($vmid, $devicefull); };
3365 eval { qemu_drivedel
($vmid, $deviceid); };
3370 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3372 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3374 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3375 my $use_old_bios_files = undef;
3376 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3378 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3379 qemu_deviceadd
($vmid, $netdevicefull);
3380 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3382 eval { qemu_netdevdel
($vmid, $deviceid); };
3387 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3390 my $pciaddr = print_pci_addr
($deviceid);
3391 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3393 qemu_deviceadd
($vmid, $devicefull);
3394 qemu_deviceaddverify
($vmid, $deviceid);
3397 die "can't hotplug device '$deviceid'\n";
3403 # fixme: this should raise exceptions on error!
3404 sub vm_deviceunplug
{
3405 my ($vmid, $conf, $deviceid) = @_;
3407 my $devices_list = vm_devices_list
($vmid);
3408 return 1 if !defined($devices_list->{$deviceid});
3410 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3412 if ($deviceid eq 'tablet') {
3414 qemu_devicedel
($vmid, $deviceid);
3416 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3418 qemu_devicedel
($vmid, $deviceid);
3419 qemu_devicedelverify
($vmid, $deviceid);
3420 qemu_drivedel
($vmid, $deviceid);
3421 qemu_iothread_del
($conf, $vmid, $deviceid);
3423 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3425 qemu_devicedel
($vmid, $deviceid);
3426 qemu_devicedelverify
($vmid, $deviceid);
3427 qemu_iothread_del
($conf, $vmid, $deviceid);
3429 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3431 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3432 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3433 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3435 qemu_devicedel
($vmid, $deviceid);
3436 qemu_drivedel
($vmid, $deviceid);
3437 qemu_deletescsihw
($conf, $vmid, $deviceid);
3439 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3441 qemu_devicedel
($vmid, $deviceid);
3442 qemu_devicedelverify
($vmid, $deviceid);
3443 qemu_netdevdel
($vmid, $deviceid);
3446 die "can't unplug device '$deviceid'\n";
3452 sub qemu_deviceadd
{
3453 my ($vmid, $devicefull) = @_;
3455 $devicefull = "driver=".$devicefull;
3456 my %options = split(/[=,]/, $devicefull);
3458 vm_mon_cmd
($vmid, "device_add" , %options);
3461 sub qemu_devicedel
{
3462 my ($vmid, $deviceid) = @_;
3464 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3467 sub qemu_iothread_add
{
3468 my($vmid, $deviceid, $device) = @_;
3470 if ($device->{iothread
}) {
3471 my $iothreads = vm_iothreads_list
($vmid);
3472 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3476 sub qemu_iothread_del
{
3477 my($conf, $vmid, $deviceid) = @_;
3479 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3480 if ($device->{iothread
}) {
3481 my $iothreads = vm_iothreads_list
($vmid);
3482 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3486 sub qemu_objectadd
{
3487 my($vmid, $objectid, $qomtype) = @_;
3489 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3494 sub qemu_objectdel
{
3495 my($vmid, $objectid) = @_;
3497 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3503 my ($storecfg, $vmid, $device) = @_;
3505 my $drive = print_drive_full
($storecfg, $vmid, $device);
3506 $drive =~ s/\\/\\\\/g;
3507 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3509 # If the command succeeds qemu prints: "OK
"
3510 return 1 if $ret =~ m/OK/s;
3512 die "adding drive failed
: $ret\n";
3516 my($vmid, $deviceid) = @_;
3518 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3521 return 1 if $ret eq "";
3523 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3524 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3526 die "deleting drive
$deviceid failed
: $ret\n";
3529 sub qemu_deviceaddverify {
3530 my ($vmid, $deviceid) = @_;
3532 for (my $i = 0; $i <= 5; $i++) {
3533 my $devices_list = vm_devices_list($vmid);
3534 return 1 if defined($devices_list->{$deviceid});
3538 die "error on hotplug device
'$deviceid'\n";
3542 sub qemu_devicedelverify {
3543 my ($vmid, $deviceid) = @_;
3545 # need to verify that the device is correctly removed as device_del
3546 # is async and empty return is not reliable
3548 for (my $i = 0; $i <= 5; $i++) {
3549 my $devices_list = vm_devices_list($vmid);
3550 return 1 if !defined($devices_list->{$deviceid});
3554 die "error on hot-unplugging device
'$deviceid'\n";
3557 sub qemu_findorcreatescsihw {
3558 my ($storecfg, $conf, $vmid, $device) = @_;
3560 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3562 my $scsihwid="$controller_prefix$controller";
3563 my $devices_list = vm_devices_list($vmid);
3565 if(!defined($devices_list->{$scsihwid})) {
3566 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3572 sub qemu_deletescsihw {
3573 my ($conf, $vmid, $opt) = @_;
3575 my $device = parse_drive($opt, $conf->{$opt});
3577 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3578 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3582 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3584 my $devices_list = vm_devices_list($vmid);
3585 foreach my $opt (keys %{$devices_list}) {
3586 if (PVE::QemuServer::valid_drivename($opt)) {
3587 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3588 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3594 my $scsihwid="scsihw
$controller";
3596 vm_deviceunplug($vmid, $conf, $scsihwid);
3601 sub qemu_add_pci_bridge {
3602 my ($storecfg, $conf, $vmid, $device) = @_;
3608 print_pci_addr($device, $bridges);
3610 while (my ($k, $v) = each %$bridges) {
3613 return 1 if !defined($bridgeid) || $bridgeid < 1;
3615 my $bridge = "pci
.$bridgeid";
3616 my $devices_list = vm_devices_list($vmid);
3618 if (!defined($devices_list->{$bridge})) {
3619 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3625 sub qemu_set_link_status {
3626 my ($vmid, $device, $up) = @_;
3628 vm_mon_cmd($vmid, "set_link
", name => $device,
3629 up => $up ? JSON::true : JSON::false);
3632 sub qemu_netdevadd {
3633 my ($vmid, $conf, $device, $deviceid) = @_;
3635 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3636 my %options = split(/[=,]/, $netdev);
3638 vm_mon_cmd($vmid, "netdev_add
", %options);
3642 sub qemu_netdevdel {
3643 my ($vmid, $deviceid) = @_;
3645 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3648 sub qemu_cpu_hotplug {
3649 my ($vmid, $conf, $vcpus) = @_;
3652 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3653 $sockets = $conf->{sockets} if $conf->{sockets};
3654 my $cores = $conf->{cores} || 1;
3655 my $maxcpus = $sockets * $cores;
3657 $vcpus = $maxcpus if !$vcpus;
3659 die "you can
't add more vcpus than maxcpus\n"
3660 if $vcpus > $maxcpus;
3662 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3663 die "online cpu unplug is not yet possible\n"
3664 if $vcpus < $currentvcpus;
3666 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3667 die "vcpus in running vm is different than configuration\n"
3668 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3670 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3671 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3675 sub qemu_memory_hotplug {
3676 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3678 return $value if !check_running($vmid);
3680 my $memory = $conf->{memory} || $defaults->{memory};
3681 $value = $defaults->{memory} if !$value;
3682 return $value if $value == $memory;
3684 my $static_memory = $STATICMEM;
3685 my $dimm_memory = $memory - $static_memory;
3687 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3688 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3692 $sockets = $conf->{sockets} if $conf->{sockets};
3694 if($value > $memory) {
3696 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3697 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3699 return if $current_size <= $conf->{memory};
3701 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3703 eval { qemu_objectdel($vmid, "mem-
$name"); };
3707 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3709 eval { qemu_objectdel($vmid, "mem-
$name"); };
3712 #update conf after each succesful module hotplug
3713 $conf->{memory} = $current_size;
3714 update_config_nolock($vmid, $conf, 1);
3719 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3720 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3722 return if $current_size >= $conf->{memory};
3723 print "try to unplug memory dimm
$name\n";
3727 eval { qemu_devicedel($vmid, $name) };
3729 my $dimm_list = qemu_dimm_list($vmid);
3730 last if !$dimm_list->{$name};
3731 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3735 #update conf after each succesful module unplug
3736 $conf->{memory} = $current_size;
3738 eval { qemu_objectdel($vmid, "mem-
$name"); };
3739 update_config_nolock($vmid, $conf, 1);
3744 sub qemu_dimm_list {
3747 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3750 foreach my $dimm (@$dimmarray) {
3752 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3753 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3754 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3755 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3756 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3761 sub qemu_block_set_io_throttle {
3762 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3764 return if !check_running($vmid) ;
3766 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));
3770 # old code, only used to shutdown old VM after update
3772 my ($fh, $timeout) = @_;
3774 my $sel = new IO::Select;
3781 while (scalar (@ready = $sel->can_read($timeout))) {
3783 if ($count = $fh->sysread($buf, 8192)) {
3784 if ($buf =~ /^(.*)\(qemu\) $/s) {
3791 if (!defined($count)) {
3798 die "monitor
read timeout
\n" if !scalar(@ready);
3803 # old code, only used to shutdown old VM after update
3804 sub vm_monitor_command {
3805 my ($vmid, $cmdstr, $nocheck) = @_;
3810 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3812 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3814 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3815 die "unable to
connect to VM
$vmid socket - $!\n";
3819 # hack: migrate sometime blocks the monitor (when migrate_downtime
3821 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3822 $timeout = 60*60; # 1 hour
3826 my $data = __read_avail($sock, $timeout);
3828 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3829 die "got unexpected qemu monitor banner
\n";
3832 my $sel = new IO::Select;
3835 if (!scalar(my @ready = $sel->can_write($timeout))) {
3836 die "monitor
write error
- timeout
";
3839 my $fullcmd = "$cmdstr\r";
3841 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3844 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3845 die "monitor
write error
- $!";
3848 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3852 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3853 $timeout = 60*60; # 1 hour
3854 } elsif ($cmdstr =~ m/^(eject|change)/) {
3855 $timeout = 60; # note: cdrom mount command is slow
3857 if ($res = __read_avail($sock, $timeout)) {
3859 my @lines = split("\r?
\n", $res);
3861 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3863 $res = join("\n", @lines);
3871 syslog("err
", "VM
$vmid monitor command failed
- $err");
3878 sub qemu_block_resize {
3879 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3881 my $running = check_running($vmid);
3883 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3885 return if !$running;
3887 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3891 sub qemu_volume_snapshot {
3892 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3894 my $running = check_running($vmid);
3896 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3897 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3899 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3903 sub qemu_volume_snapshot_delete {
3904 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3906 my $running = check_running($vmid);
3908 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3910 return if !$running;
3912 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3915 sub set_migration_caps {
3921 "auto-converge
" => 1,
3923 "x-rdma-pin-all
" => 0,
3928 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3930 for my $supported_capability (@$supported_capabilities) {
3932 capability => $supported_capability->{capability},
3933 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3937 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3940 my $fast_plug_option = {
3949 # hotplug changes in [PENDING]
3950 # $selection hash can be used to only apply specified options, for
3951 # example: { cores => 1 } (only apply changed 'cores')
3952 # $errors ref is used to return error messages
3953 sub vmconfig_hotplug_pending {
3954 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3956 my $defaults = load_defaults();
3958 # commit values which do not have any impact on running VM first
3959 # Note: those option cannot raise errors, we we do not care about
3960 # $selection and always apply them.
3962 my $add_error = sub {
3963 my ($opt, $msg) = @_;
3964 $errors->{$opt} = "hotplug problem
- $msg";
3968 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3969 if ($fast_plug_option->{$opt}) {
3970 $conf->{$opt} = $conf->{pending}->{$opt};
3971 delete $conf->{pending}->{$opt};
3977 update_config_nolock($vmid, $conf, 1);
3978 $conf = load_config($vmid); # update/reload
3981 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3983 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3984 while (my ($opt, $force) = each %$pending_delete_hash) {
3985 next if $selection && !$selection->{$opt};
3987 if ($opt eq 'hotplug') {
3988 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3989 } elsif ($opt eq 'tablet') {
3990 die "skip
\n" if !$hotplug_features->{usb};
3991 if ($defaults->{tablet}) {
3992 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3994 vm_deviceunplug($vmid, $conf, $opt);
3996 } elsif ($opt eq 'vcpus') {
3997 die "skip
\n" if !$hotplug_features->{cpu};
3998 qemu_cpu_hotplug($vmid, $conf, undef);
3999 } elsif ($opt eq 'balloon') {
4000 # enable balloon device is not hotpluggable
4001 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4002 } elsif ($fast_plug_option->{$opt}) {
4004 } elsif ($opt =~ m/^net(\d+)$/) {
4005 die "skip
\n" if !$hotplug_features->{network};
4006 vm_deviceunplug($vmid, $conf, $opt);
4007 } elsif (valid_drivename($opt)) {
4008 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4009 vm_deviceunplug($vmid, $conf, $opt);
4010 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4011 } elsif ($opt =~ m/^memory$/) {
4012 die "skip
\n" if !$hotplug_features->{memory};
4013 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4014 } elsif ($opt eq 'cpuunits') {
4015 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4016 } elsif ($opt eq 'cpulimit') {
4017 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4023 &$add_error($opt, $err) if $err ne "skip
\n";
4025 # save new config if hotplug was successful
4026 delete $conf->{$opt};
4027 vmconfig_undelete_pending_option($conf, $opt);
4028 update_config_nolock($vmid, $conf, 1);
4029 $conf = load_config($vmid); # update/reload
4033 foreach my $opt (keys %{$conf->{pending}}) {
4034 next if $selection && !$selection->{$opt};
4035 my $value = $conf->{pending}->{$opt};
4037 if ($opt eq 'hotplug') {
4038 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4039 } elsif ($opt eq 'tablet') {
4040 die "skip
\n" if !$hotplug_features->{usb};
4042 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4043 } elsif ($value == 0) {
4044 vm_deviceunplug($vmid, $conf, $opt);
4046 } elsif ($opt eq 'vcpus') {
4047 die "skip
\n" if !$hotplug_features->{cpu};
4048 qemu_cpu_hotplug($vmid, $conf, $value);
4049 } elsif ($opt eq 'balloon') {
4050 # enable/disable balloning device is not hotpluggable
4051 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4052 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4053 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4055 # allow manual ballooning if shares is set to zero
4056 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4057 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4058 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4060 } elsif ($opt =~ m/^net(\d+)$/) {
4061 # some changes can be done without hotplug
4062 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4063 $vmid, $opt, $value);
4064 } elsif (valid_drivename($opt)) {
4065 # some changes can be done without hotplug
4066 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4067 $vmid, $opt, $value, 1);
4068 } elsif ($opt =~ m/^memory$/) { #dimms
4069 die "skip
\n" if !$hotplug_features->{memory};
4070 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4071 } elsif ($opt eq 'cpuunits') {
4072 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4073 } elsif ($opt eq 'cpulimit') {
4074 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4075 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4077 die "skip
\n"; # skip non-hot-pluggable options
4081 &$add_error($opt, $err) if $err ne "skip
\n";
4083 # save new config if hotplug was successful
4084 $conf->{$opt} = $value;
4085 delete $conf->{pending}->{$opt};
4086 update_config_nolock($vmid, $conf, 1);
4087 $conf = load_config($vmid); # update/reload
4092 sub try_deallocate_drive {
4093 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4095 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4096 my $volid = $drive->{file};
4097 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4098 my $sid = PVE::Storage::parse_volume_id($volid);
4099 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4101 # check if the disk is really unused
4102 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4103 if is_volume_in_use($storecfg, $conf, $key, $volid);
4104 PVE::Storage::vdisk_free($storecfg, $volid);
4107 # If vm is not owner of this disk remove from config
4115 sub vmconfig_delete_or_detach_drive {
4116 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4118 my $drive = parse_drive($opt, $conf->{$opt});
4120 my $rpcenv = PVE::RPCEnvironment::get();
4121 my $authuser = $rpcenv->get_user();
4124 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4125 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4127 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4131 sub vmconfig_apply_pending {
4132 my ($vmid, $conf, $storecfg) = @_;
4136 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4137 while (my ($opt, $force) = each %$pending_delete_hash) {
4138 die "internal error
" if $opt =~ m/^unused/;
4139 $conf = load_config($vmid); # update/reload
4140 if (!defined($conf->{$opt})) {
4141 vmconfig_undelete_pending_option($conf, $opt);
4142 update_config_nolock($vmid, $conf, 1);
4143 } elsif (valid_drivename($opt)) {
4144 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4145 vmconfig_undelete_pending_option($conf, $opt);
4146 delete $conf->{$opt};
4147 update_config_nolock($vmid, $conf, 1);
4149 vmconfig_undelete_pending_option($conf, $opt);
4150 delete $conf->{$opt};
4151 update_config_nolock($vmid, $conf, 1);
4155 $conf = load_config($vmid); # update/reload
4157 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4158 $conf = load_config($vmid); # update/reload
4160 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4161 # skip if nothing changed
4162 } elsif (valid_drivename($opt)) {
4163 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4164 if defined($conf->{$opt});
4165 $conf->{$opt} = $conf->{pending}->{$opt};
4167 $conf->{$opt} = $conf->{pending}->{$opt};
4170 delete $conf->{pending}->{$opt};
4171 update_config_nolock($vmid, $conf, 1);
4175 my $safe_num_ne = sub {
4178 return 0 if !defined($a) && !defined($b);
4179 return 1 if !defined($a);
4180 return 1 if !defined($b);
4185 my $safe_string_ne = sub {
4188 return 0 if !defined($a) && !defined($b);
4189 return 1 if !defined($a);
4190 return 1 if !defined($b);
4195 sub vmconfig_update_net {
4196 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4198 my $newnet = parse_net($value);
4200 if ($conf->{$opt}) {
4201 my $oldnet = parse_net($conf->{$opt});
4203 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4204 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4205 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4206 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4208 # for non online change, we try to hot-unplug
4209 die "skip
\n" if !$hotplug;
4210 vm_deviceunplug($vmid, $conf, $opt);
4213 die "internal error
" if $opt !~ m/net(\d+)/;
4214 my $iface = "tap
${vmid
}i
$1";
4216 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4217 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4220 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4221 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4222 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4223 PVE::Network::tap_unplug($iface);
4224 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4227 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4228 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4236 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4242 sub vmconfig_update_disk {
4243 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4245 # fixme: do we need force?
4247 my $drive = parse_drive($opt, $value);
4249 if ($conf->{$opt}) {
4251 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4253 my $media = $drive->{media} || 'disk';
4254 my $oldmedia = $old_drive->{media} || 'disk';
4255 die "unable to change media type
\n" if $media ne $oldmedia;
4257 if (!drive_is_cdrom($old_drive)) {
4259 if ($drive->{file} ne $old_drive->{file}) {
4261 die "skip
\n" if !$hotplug;
4263 # unplug and register as unused
4264 vm_deviceunplug($vmid, $conf, $opt);
4265 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4268 # update existing disk
4270 # skip non hotpluggable value
4271 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4272 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4273 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4274 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4279 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4280 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4281 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4282 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4283 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4284 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4285 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4286 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4287 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4288 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4289 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4290 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4292 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4293 ($drive->{mbps} || 0)*1024*1024,
4294 ($drive->{mbps_rd} || 0)*1024*1024,
4295 ($drive->{mbps_wr} || 0)*1024*1024,
4296 $drive->{iops} || 0,
4297 $drive->{iops_rd} || 0,
4298 $drive->{iops_wr} || 0,
4299 ($drive->{mbps_max} || 0)*1024*1024,
4300 ($drive->{mbps_rd_max} || 0)*1024*1024,
4301 ($drive->{mbps_wr_max} || 0)*1024*1024,
4302 $drive->{iops_max} || 0,
4303 $drive->{iops_rd_max} || 0,
4304 $drive->{iops_wr_max} || 0);
4313 if ($drive->{file} eq 'none') {
4314 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4316 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4317 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4318 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4326 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4328 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
4329 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4333 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4334 $forcemachine, $spice_ticket) = @_;
4336 lock_config($vmid, sub {
4337 my $conf = load_config($vmid, $migratedfrom);
4339 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4341 check_lock($conf) if !$skiplock;
4343 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4345 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4346 vmconfig_apply_pending($vmid, $conf, $storecfg);
4347 $conf = load_config($vmid); # update/reload
4350 my $defaults = load_defaults();
4352 # set environment variable useful inside network script
4353 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4355 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4357 my $migrate_port = 0;
4360 if ($statefile eq 'tcp') {
4361 my $localip = "localhost
";
4362 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4363 my $nodename = PVE::INotify::nodename();
4364 if ($datacenterconf->{migration_unsecure}) {
4365 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4366 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4368 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4369 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4370 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4371 push @$cmd, '-incoming', $migrate_uri;
4374 push @$cmd, '-loadstate', $statefile;
4381 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4382 my $d = parse_hostpci($conf->{"hostpci
$i"});
4384 my $pcidevices = $d->{pciid};
4385 foreach my $pcidevice (@$pcidevices) {
4386 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4388 my $info = pci_device_info("0000:$pciid");
4389 die "IOMMU
not present
\n" if !check_iommu_support();
4390 die "no pci device info
for device
'$pciid'\n" if !$info;
4391 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4392 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4396 PVE::Storage::activate_volumes($storecfg, $vollist);
4398 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4401 die "start failed
: $err" if $err;
4403 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4405 if ($statefile && $statefile ne 'tcp') {
4406 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4410 if ($migratedfrom) {
4413 set_migration_caps($vmid);
4418 print "spice listens on port
$spice_port\n";
4419 if ($spice_ticket) {
4420 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4421 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4427 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4428 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4429 if $conf->{balloon};
4432 foreach my $opt (keys %$conf) {
4433 next if $opt !~ m/^net\d+$/;
4434 my $nicconf = parse_net($conf->{$opt});
4435 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4439 vm_mon_cmd_nocheck($vmid, 'qom-set',
4440 path => "machine
/peripheral/balloon0
",
4441 property => "guest-stats-polling-interval
",
4442 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4448 my ($vmid, $execute, %params) = @_;
4450 my $cmd = { execute => $execute, arguments => \%params };
4451 vm_qmp_command($vmid, $cmd);
4454 sub vm_mon_cmd_nocheck {
4455 my ($vmid, $execute, %params) = @_;
4457 my $cmd = { execute => $execute, arguments => \%params };
4458 vm_qmp_command($vmid, $cmd, 1);
4461 sub vm_qmp_command {
4462 my ($vmid, $cmd, $nocheck) = @_;
4467 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4468 $timeout = $cmd->{arguments}->{timeout};
4469 delete $cmd->{arguments}->{timeout};
4473 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4474 my $sname = qmp_socket($vmid);
4475 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4476 my $qmpclient = PVE::QMPClient->new();
4478 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4479 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4480 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4481 if scalar(%{$cmd->{arguments}});
4482 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4484 die "unable to open monitor socket\n";
4488 syslog("err", "VM $vmid qmp command failed - $err");
4495 sub vm_human_monitor_command {
4496 my ($vmid, $cmdline) = @_;
4501 execute => 'human-monitor-command
',
4502 arguments => { 'command-line
' => $cmdline},
4505 return vm_qmp_command($vmid, $cmd);
4508 sub vm_commandline {
4509 my ($storecfg, $vmid) = @_;
4511 my $conf = load_config($vmid);
4513 my $defaults = load_defaults();
4515 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4517 return join(' ', @$cmd);
4521 my ($vmid, $skiplock) = @_;
4523 lock_config($vmid, sub {
4525 my $conf = load_config($vmid);
4527 check_lock($conf) if !$skiplock;
4529 vm_mon_cmd($vmid, "system_reset");
4533 sub get_vm_volumes {
4537 foreach_volid($conf, sub {
4538 my ($volid, $is_cdrom) = @_;
4540 return if $volid =~ m|^/|;
4542 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4545 push @$vollist, $volid;
4551 sub vm_stop_cleanup {
4552 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4557 my $vollist = get_vm_volumes($conf);
4558 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4561 foreach my $ext (qw(mon qmp pid vnc qga)) {
4562 unlink "/var/run/qemu-server/${vmid}.$ext";
4565 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4567 warn $@ if $@; # avoid errors - just warn
4570 # Note: use $nockeck to skip tests if VM configuration file exists.
4571 # We need that when migration VMs to other nodes (files already moved)
4572 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4574 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4576 $force = 1 if !defined($force) && !$shutdown;
4579 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4580 kill 15, $pid if $pid;
4581 my $conf = load_config
($vmid, $migratedfrom);
4582 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4586 lock_config
($vmid, sub {
4588 my $pid = check_running
($vmid, $nocheck);
4593 $conf = load_config
($vmid);
4594 check_lock
($conf) if !$skiplock;
4595 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4596 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4597 $timeout = $opts->{down
} if $opts->{down
};
4601 $timeout = 60 if !defined($timeout);
4605 if (defined($conf) && $conf->{agent
}) {
4606 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4608 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4611 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4618 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4623 if ($count >= $timeout) {
4625 warn "VM still running - terminating now with SIGTERM\n";
4628 die "VM quit/powerdown failed - got timeout\n";
4631 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4636 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4639 die "VM quit/powerdown failed\n";
4647 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4652 if ($count >= $timeout) {
4653 warn "VM still running - terminating now with SIGKILL\n";
4658 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4663 my ($vmid, $skiplock) = @_;
4665 lock_config
($vmid, sub {
4667 my $conf = load_config
($vmid);
4669 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4671 vm_mon_cmd
($vmid, "stop");
4676 my ($vmid, $skiplock, $nocheck) = @_;
4678 lock_config
($vmid, sub {
4682 my $conf = load_config
($vmid);
4684 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4686 vm_mon_cmd
($vmid, "cont");
4689 vm_mon_cmd_nocheck
($vmid, "cont");
4695 my ($vmid, $skiplock, $key) = @_;
4697 lock_config
($vmid, sub {
4699 my $conf = load_config
($vmid);
4701 # there is no qmp command, so we use the human monitor command
4702 vm_human_monitor_command
($vmid, "sendkey $key");
4707 my ($storecfg, $vmid, $skiplock) = @_;
4709 lock_config
($vmid, sub {
4711 my $conf = load_config
($vmid);
4713 check_lock
($conf) if !$skiplock;
4715 if (!check_running
($vmid)) {
4716 destroy_vm
($storecfg, $vmid);
4718 die "VM $vmid is running - destroy failed\n";
4726 my ($filename, $buf) = @_;
4728 my $fh = IO
::File-
>new($filename, "w");
4729 return undef if !$fh;
4731 my $res = print $fh $buf;
4738 sub pci_device_info
{
4743 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4744 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4746 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4747 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4749 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4750 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4752 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4753 return undef if !defined($product) || $product !~ s/^0x//;
4758 product
=> $product,
4764 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4773 my $name = $dev->{name
};
4775 my $fn = "$pcisysfs/devices/$name/reset";
4777 return file_write
($fn, "1");
4780 sub pci_dev_bind_to_vfio
{
4783 my $name = $dev->{name
};
4785 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4787 if (!-d
$vfio_basedir) {
4788 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4790 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4792 my $testdir = "$vfio_basedir/$name";
4793 return 1 if -d
$testdir;
4795 my $data = "$dev->{vendor} $dev->{product}";
4796 return undef if !file_write
("$vfio_basedir/new_id", $data);
4798 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4799 if (!file_write
($fn, $name)) {
4800 return undef if -f
$fn;
4803 $fn = "$vfio_basedir/bind";
4804 if (! -d
$testdir) {
4805 return undef if !file_write
($fn, $name);
4811 sub pci_dev_group_bind_to_vfio
{
4814 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4816 if (!-d
$vfio_basedir) {
4817 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4819 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4821 # get IOMMU group devices
4822 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4823 my @devs = grep /^0000:/, readdir($D);
4826 foreach my $pciid (@devs) {
4827 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4829 # pci bridges, switches or root ports are not supported
4830 # they have a pci_bus subdirectory so skip them
4831 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4833 my $info = pci_device_info
($1);
4834 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4840 sub print_pci_addr
{
4841 my ($id, $bridges) = @_;
4845 piix3
=> { bus
=> 0, addr
=> 1 },
4846 #addr2 : first videocard
4847 balloon0
=> { bus
=> 0, addr
=> 3 },
4848 watchdog
=> { bus
=> 0, addr
=> 4 },
4849 scsihw0
=> { bus
=> 0, addr
=> 5 },
4850 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4851 scsihw1
=> { bus
=> 0, addr
=> 6 },
4852 ahci0
=> { bus
=> 0, addr
=> 7 },
4853 qga0
=> { bus
=> 0, addr
=> 8 },
4854 spice
=> { bus
=> 0, addr
=> 9 },
4855 virtio0
=> { bus
=> 0, addr
=> 10 },
4856 virtio1
=> { bus
=> 0, addr
=> 11 },
4857 virtio2
=> { bus
=> 0, addr
=> 12 },
4858 virtio3
=> { bus
=> 0, addr
=> 13 },
4859 virtio4
=> { bus
=> 0, addr
=> 14 },
4860 virtio5
=> { bus
=> 0, addr
=> 15 },
4861 hostpci0
=> { bus
=> 0, addr
=> 16 },
4862 hostpci1
=> { bus
=> 0, addr
=> 17 },
4863 net0
=> { bus
=> 0, addr
=> 18 },
4864 net1
=> { bus
=> 0, addr
=> 19 },
4865 net2
=> { bus
=> 0, addr
=> 20 },
4866 net3
=> { bus
=> 0, addr
=> 21 },
4867 net4
=> { bus
=> 0, addr
=> 22 },
4868 net5
=> { bus
=> 0, addr
=> 23 },
4869 vga1
=> { bus
=> 0, addr
=> 24 },
4870 vga2
=> { bus
=> 0, addr
=> 25 },
4871 vga3
=> { bus
=> 0, addr
=> 26 },
4872 hostpci2
=> { bus
=> 0, addr
=> 27 },
4873 hostpci3
=> { bus
=> 0, addr
=> 28 },
4874 #addr29 : usb-host (pve-usb.cfg)
4875 'pci.1' => { bus
=> 0, addr
=> 30 },
4876 'pci.2' => { bus
=> 0, addr
=> 31 },
4877 'net6' => { bus
=> 1, addr
=> 1 },
4878 'net7' => { bus
=> 1, addr
=> 2 },
4879 'net8' => { bus
=> 1, addr
=> 3 },
4880 'net9' => { bus
=> 1, addr
=> 4 },
4881 'net10' => { bus
=> 1, addr
=> 5 },
4882 'net11' => { bus
=> 1, addr
=> 6 },
4883 'net12' => { bus
=> 1, addr
=> 7 },
4884 'net13' => { bus
=> 1, addr
=> 8 },
4885 'net14' => { bus
=> 1, addr
=> 9 },
4886 'net15' => { bus
=> 1, addr
=> 10 },
4887 'net16' => { bus
=> 1, addr
=> 11 },
4888 'net17' => { bus
=> 1, addr
=> 12 },
4889 'net18' => { bus
=> 1, addr
=> 13 },
4890 'net19' => { bus
=> 1, addr
=> 14 },
4891 'net20' => { bus
=> 1, addr
=> 15 },
4892 'net21' => { bus
=> 1, addr
=> 16 },
4893 'net22' => { bus
=> 1, addr
=> 17 },
4894 'net23' => { bus
=> 1, addr
=> 18 },
4895 'net24' => { bus
=> 1, addr
=> 19 },
4896 'net25' => { bus
=> 1, addr
=> 20 },
4897 'net26' => { bus
=> 1, addr
=> 21 },
4898 'net27' => { bus
=> 1, addr
=> 22 },
4899 'net28' => { bus
=> 1, addr
=> 23 },
4900 'net29' => { bus
=> 1, addr
=> 24 },
4901 'net30' => { bus
=> 1, addr
=> 25 },
4902 'net31' => { bus
=> 1, addr
=> 26 },
4903 'virtio6' => { bus
=> 2, addr
=> 1 },
4904 'virtio7' => { bus
=> 2, addr
=> 2 },
4905 'virtio8' => { bus
=> 2, addr
=> 3 },
4906 'virtio9' => { bus
=> 2, addr
=> 4 },
4907 'virtio10' => { bus
=> 2, addr
=> 5 },
4908 'virtio11' => { bus
=> 2, addr
=> 6 },
4909 'virtio12' => { bus
=> 2, addr
=> 7 },
4910 'virtio13' => { bus
=> 2, addr
=> 8 },
4911 'virtio14' => { bus
=> 2, addr
=> 9 },
4912 'virtio15' => { bus
=> 2, addr
=> 10 },
4913 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4914 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4915 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4916 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4917 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4918 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4919 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4920 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4921 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4922 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4923 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4924 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4925 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4926 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4927 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4928 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4929 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4930 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4931 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4932 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4933 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4934 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4935 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4936 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4937 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4938 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4939 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4940 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4941 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4942 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4943 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4947 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4948 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4949 my $bus = $devices->{$id}->{bus
};
4950 $res = ",bus=pci.$bus,addr=$addr";
4951 $bridges->{$bus} = 1 if $bridges;
4957 sub print_pcie_addr
{
4962 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4963 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4964 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4965 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4968 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4969 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4970 my $bus = $devices->{$id}->{bus
};
4971 $res = ",bus=$bus,addr=$addr";
4977 # vzdump restore implementaion
4979 sub tar_archive_read_firstfile
{
4980 my $archive = shift;
4982 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4984 # try to detect archive type first
4985 my $pid = open (TMP
, "tar tf '$archive'|") ||
4986 die "unable to open file '$archive'\n";
4987 my $firstfile = <TMP
>;
4991 die "ERROR: archive contaions no data\n" if !$firstfile;
4997 sub tar_restore_cleanup
{
4998 my ($storecfg, $statfile) = @_;
5000 print STDERR
"starting cleanup\n";
5002 if (my $fd = IO
::File-
>new($statfile, "r")) {
5003 while (defined(my $line = <$fd>)) {
5004 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5007 if ($volid =~ m
|^/|) {
5008 unlink $volid || die 'unlink failed\n';
5010 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5012 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5014 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5016 print STDERR
"unable to parse line in statfile - $line";
5023 sub restore_archive
{
5024 my ($archive, $vmid, $user, $opts) = @_;
5026 my $format = $opts->{format
};
5029 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5030 $format = 'tar' if !$format;
5032 } elsif ($archive =~ m/\.tar$/) {
5033 $format = 'tar' if !$format;
5034 } elsif ($archive =~ m/.tar.lzo$/) {
5035 $format = 'tar' if !$format;
5037 } elsif ($archive =~ m/\.vma$/) {
5038 $format = 'vma' if !$format;
5039 } elsif ($archive =~ m/\.vma\.gz$/) {
5040 $format = 'vma' if !$format;
5042 } elsif ($archive =~ m/\.vma\.lzo$/) {
5043 $format = 'vma' if !$format;
5046 $format = 'vma' if !$format; # default
5049 # try to detect archive format
5050 if ($format eq 'tar') {
5051 return restore_tar_archive
($archive, $vmid, $user, $opts);
5053 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5057 sub restore_update_config_line
{
5058 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5060 return if $line =~ m/^\#qmdump\#/;
5061 return if $line =~ m/^\#vzdump\#/;
5062 return if $line =~ m/^lock:/;
5063 return if $line =~ m/^unused\d+:/;
5064 return if $line =~ m/^parent:/;
5065 return if $line =~ m/^template:/; # restored VM is never a template
5067 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5068 # try to convert old 1.X settings
5069 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5070 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5071 my ($model, $macaddr) = split(/\=/, $devconfig);
5072 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5075 bridge
=> "vmbr$ind",
5076 macaddr
=> $macaddr,
5078 my $netstr = print_net
($net);
5080 print $outfd "net$cookie->{netcount}: $netstr\n";
5081 $cookie->{netcount
}++;
5083 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5084 my ($id, $netstr) = ($1, $2);
5085 my $net = parse_net
($netstr);
5086 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5087 $netstr = print_net
($net);
5088 print $outfd "$id: $netstr\n";
5089 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5092 if ($line =~ m/backup=no/) {
5093 print $outfd "#$line";
5094 } elsif ($virtdev && $map->{$virtdev}) {
5095 my $di = parse_drive
($virtdev, $value);
5096 delete $di->{format
}; # format can change on restore
5097 $di->{file
} = $map->{$virtdev};
5098 $value = print_drive
($vmid, $di);
5099 print $outfd "$virtdev: $value\n";
5109 my ($cfg, $vmid) = @_;
5111 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5113 my $volid_hash = {};
5114 foreach my $storeid (keys %$info) {
5115 foreach my $item (@{$info->{$storeid}}) {
5116 next if !($item->{volid
} && $item->{size
});
5117 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5118 $volid_hash->{$item->{volid
}} = $item;
5125 sub is_volume_in_use
{
5126 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5128 my $path = PVE
::Storage
::path
($storecfg, $volid);
5130 my $scan_config = sub {
5131 my ($cref, $snapname) = @_;
5133 foreach my $key (keys %$cref) {
5134 my $value = $cref->{$key};
5135 if (valid_drivename
($key)) {
5136 next if $skip_drive && $key eq $skip_drive;
5137 my $drive = parse_drive
($key, $value);
5138 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5139 return 1 if $volid eq $drive->{file
};
5140 if ($drive->{file
} =~ m!^/!) {
5141 return 1 if $drive->{file
} eq $path;
5143 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5145 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5147 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5155 return 1 if &$scan_config($conf);
5159 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5160 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5166 sub update_disksize
{
5167 my ($vmid, $conf, $volid_hash) = @_;
5173 # Note: it is allowed to define multiple storages with same path (alias), so
5174 # we need to check both 'volid' and real 'path' (two different volid can point
5175 # to the same path).
5180 foreach my $opt (keys %$conf) {
5181 if (valid_drivename
($opt)) {
5182 my $drive = parse_drive
($opt, $conf->{$opt});
5183 my $volid = $drive->{file
};
5186 $used->{$volid} = 1;
5187 if ($volid_hash->{$volid} &&
5188 (my $path = $volid_hash->{$volid}->{path
})) {
5189 $usedpath->{$path} = 1;
5192 next if drive_is_cdrom
($drive);
5193 next if !$volid_hash->{$volid};
5195 $drive->{size
} = $volid_hash->{$volid}->{size
};
5196 my $new = print_drive
($vmid, $drive);
5197 if ($new ne $conf->{$opt}) {
5199 $conf->{$opt} = $new;
5204 # remove 'unusedX' entry if volume is used
5205 foreach my $opt (keys %$conf) {
5206 next if $opt !~ m/^unused\d+$/;
5207 my $volid = $conf->{$opt};
5208 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5209 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5211 delete $conf->{$opt};
5215 foreach my $volid (sort keys %$volid_hash) {
5216 next if $volid =~ m/vm-$vmid-state-/;
5217 next if $used->{$volid};
5218 my $path = $volid_hash->{$volid}->{path
};
5219 next if !$path; # just to be sure
5220 next if $usedpath->{$path};
5222 add_unused_volume
($conf, $volid);
5223 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5230 my ($vmid, $nolock) = @_;
5232 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5234 my $volid_hash = scan_volids
($cfg, $vmid);
5236 my $updatefn = sub {
5239 my $conf = load_config
($vmid);
5244 foreach my $volid (keys %$volid_hash) {
5245 my $info = $volid_hash->{$volid};
5246 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5249 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5251 update_config_nolock
($vmid, $conf, 1) if $changes;
5254 if (defined($vmid)) {
5258 lock_config
($vmid, $updatefn, $vmid);
5261 my $vmlist = config_list
();
5262 foreach my $vmid (keys %$vmlist) {
5266 lock_config
($vmid, $updatefn, $vmid);
5272 sub restore_vma_archive
{
5273 my ($archive, $vmid, $user, $opts, $comp) = @_;
5275 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5276 my $readfrom = $archive;
5281 my $qarchive = PVE
::Tools
::shellquote
($archive);
5282 if ($comp eq 'gzip') {
5283 $uncomp = "zcat $qarchive|";
5284 } elsif ($comp eq 'lzop') {
5285 $uncomp = "lzop -d -c $qarchive|";
5287 die "unknown compression method '$comp'\n";
5292 my $tmpdir = "/var/tmp/vzdumptmp$$";
5295 # disable interrupts (always do cleanups)
5296 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5297 warn "got interrupt - ignored\n";
5300 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5301 POSIX
::mkfifo
($mapfifo, 0600);
5304 my $openfifo = sub {
5305 open($fifofh, '>', $mapfifo) || die $!;
5308 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5315 my $rpcenv = PVE
::RPCEnvironment
::get
();
5317 my $conffile = config_file
($vmid);
5318 my $tmpfn = "$conffile.$$.tmp";
5320 # Note: $oldconf is undef if VM does not exists
5321 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5323 my $print_devmap = sub {
5324 my $virtdev_hash = {};
5326 my $cfgfn = "$tmpdir/qemu-server.conf";
5328 # we can read the config - that is already extracted
5329 my $fh = IO
::File-
>new($cfgfn, "r") ||
5330 "unable to read qemu-server.conf - $!\n";
5332 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5333 PVE
::Tools
::file_copy
($fwcfgfn, "/etc/pve/firewall/$vmid.fw")
5336 while (defined(my $line = <$fh>)) {
5337 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5338 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5339 die "archive does not contain data for drive '$virtdev'\n"
5340 if !$devinfo->{$devname};
5341 if (defined($opts->{storage
})) {
5342 $storeid = $opts->{storage
} || 'local';
5343 } elsif (!$storeid) {
5346 $format = 'raw' if !$format;
5347 $devinfo->{$devname}->{devname
} = $devname;
5348 $devinfo->{$devname}->{virtdev
} = $virtdev;
5349 $devinfo->{$devname}->{format
} = $format;
5350 $devinfo->{$devname}->{storeid
} = $storeid;
5352 # check permission on storage
5353 my $pool = $opts->{pool
}; # todo: do we need that?
5354 if ($user ne 'root@pam') {
5355 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5358 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5362 foreach my $devname (keys %$devinfo) {
5363 die "found no device mapping information for device '$devname'\n"
5364 if !$devinfo->{$devname}->{virtdev
};
5367 my $cfg = cfs_read_file
('storage.cfg');
5369 # create empty/temp config
5371 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5372 foreach_drive
($oldconf, sub {
5373 my ($ds, $drive) = @_;
5375 return if drive_is_cdrom
($drive);
5377 my $volid = $drive->{file
};
5379 return if !$volid || $volid =~ m
|^/|;
5381 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5382 return if !$path || !$owner || ($owner != $vmid);
5384 # Note: only delete disk we want to restore
5385 # other volumes will become unused
5386 if ($virtdev_hash->{$ds}) {
5387 PVE
::Storage
::vdisk_free
($cfg, $volid);
5393 foreach my $virtdev (sort keys %$virtdev_hash) {
5394 my $d = $virtdev_hash->{$virtdev};
5395 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5396 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5398 # test if requested format is supported
5399 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5400 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5401 $d->{format
} = $defFormat if !$supported;
5403 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5404 $d->{format
}, undef, $alloc_size);
5405 print STDERR
"new volume ID is '$volid'\n";
5406 $d->{volid
} = $volid;
5407 my $path = PVE
::Storage
::path
($cfg, $volid);
5409 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5411 my $write_zeros = 1;
5412 # fixme: what other storages types initialize volumes with zero?
5413 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5414 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5418 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5420 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5421 $map->{$virtdev} = $volid;
5424 $fh->seek(0, 0) || die "seek failed - $!\n";
5426 my $outfd = new IO
::File
($tmpfn, "w") ||
5427 die "unable to write config for VM $vmid\n";
5429 my $cookie = { netcount
=> 0 };
5430 while (defined(my $line = <$fh>)) {
5431 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5440 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5441 die "interrupted by signal\n";
5443 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5445 $oldtimeout = alarm($timeout);
5452 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5453 my ($dev_id, $size, $devname) = ($1, $2, $3);
5454 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5455 } elsif ($line =~ m/^CTIME: /) {
5456 # we correctly received the vma config, so we can disable
5457 # the timeout now for disk allocation (set to 10 minutes, so
5458 # that we always timeout if something goes wrong)
5461 print $fifofh "done\n";
5462 my $tmp = $oldtimeout || 0;
5463 $oldtimeout = undef;
5469 print "restore vma archive: $cmd\n";
5470 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5474 alarm($oldtimeout) if $oldtimeout;
5477 foreach my $devname (keys %$devinfo) {
5478 my $volid = $devinfo->{$devname}->{volid
};
5479 push @$vollist, $volid if $volid;
5482 my $cfg = cfs_read_file
('storage.cfg');
5483 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5491 foreach my $devname (keys %$devinfo) {
5492 my $volid = $devinfo->{$devname}->{volid
};
5495 if ($volid =~ m
|^/|) {
5496 unlink $volid || die 'unlink failed\n';
5498 PVE
::Storage
::vdisk_free
($cfg, $volid);
5500 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5502 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5509 rename($tmpfn, $conffile) ||
5510 die "unable to commit configuration file '$conffile'\n";
5512 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5514 eval { rescan
($vmid, 1); };
5518 sub restore_tar_archive
{
5519 my ($archive, $vmid, $user, $opts) = @_;
5521 if ($archive ne '-') {
5522 my $firstfile = tar_archive_read_firstfile
($archive);
5523 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5524 if $firstfile ne 'qemu-server.conf';
5527 my $storecfg = cfs_read_file
('storage.cfg');
5529 # destroy existing data - keep empty config
5530 my $vmcfgfn = config_file
($vmid);
5531 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5533 my $tocmd = "/usr/lib/qemu-server/qmextract";
5535 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5536 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5537 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5538 $tocmd .= ' --info' if $opts->{info
};
5540 # tar option "xf" does not autodetect compression when read from STDIN,
5541 # so we pipe to zcat
5542 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5543 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5545 my $tmpdir = "/var/tmp/vzdumptmp$$";
5548 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5549 local $ENV{VZDUMP_VMID
} = $vmid;
5550 local $ENV{VZDUMP_USER
} = $user;
5552 my $conffile = config_file
($vmid);
5553 my $tmpfn = "$conffile.$$.tmp";
5555 # disable interrupts (always do cleanups)
5556 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5557 print STDERR
"got interrupt - ignored\n";
5562 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5563 die "interrupted by signal\n";
5566 if ($archive eq '-') {
5567 print "extracting archive from STDIN\n";
5568 run_command
($cmd, input
=> "<&STDIN");
5570 print "extracting archive '$archive'\n";
5574 return if $opts->{info
};
5578 my $statfile = "$tmpdir/qmrestore.stat";
5579 if (my $fd = IO
::File-
>new($statfile, "r")) {
5580 while (defined (my $line = <$fd>)) {
5581 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5582 $map->{$1} = $2 if $1;
5584 print STDERR
"unable to parse line in statfile - $line\n";
5590 my $confsrc = "$tmpdir/qemu-server.conf";
5592 my $srcfd = new IO
::File
($confsrc, "r") ||
5593 die "unable to open file '$confsrc'\n";
5595 my $outfd = new IO
::File
($tmpfn, "w") ||
5596 die "unable to write config for VM $vmid\n";
5598 my $cookie = { netcount
=> 0 };
5599 while (defined (my $line = <$srcfd>)) {
5600 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5612 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5619 rename $tmpfn, $conffile ||
5620 die "unable to commit configuration file '$conffile'\n";
5622 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5624 eval { rescan
($vmid, 1); };
5629 # Internal snapshots
5631 # NOTE: Snapshot create/delete involves several non-atomic
5632 # action, and can take a long time.
5633 # So we try to avoid locking the file and use 'lock' variable
5634 # inside the config file instead.
5636 my $snapshot_copy_config = sub {
5637 my ($source, $dest) = @_;
5639 foreach my $k (keys %$source) {
5640 next if $k eq 'snapshots';
5641 next if $k eq 'snapstate';
5642 next if $k eq 'snaptime';
5643 next if $k eq 'vmstate';
5644 next if $k eq 'lock';
5645 next if $k eq 'digest';
5646 next if $k eq 'description';
5647 next if $k =~ m/^unused\d+$/;
5649 $dest->{$k} = $source->{$k};
5653 my $snapshot_apply_config = sub {
5654 my ($conf, $snap) = @_;
5656 # copy snapshot list
5658 snapshots
=> $conf->{snapshots
},
5661 # keep description and list of unused disks
5662 foreach my $k (keys %$conf) {
5663 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5664 $newconf->{$k} = $conf->{$k};
5667 &$snapshot_copy_config($snap, $newconf);
5672 sub foreach_writable_storage
{
5673 my ($conf, $func) = @_;
5677 foreach my $ds (keys %$conf) {
5678 next if !valid_drivename
($ds);
5680 my $drive = parse_drive
($ds, $conf->{$ds});
5682 next if drive_is_cdrom
($drive);
5684 my $volid = $drive->{file
};
5686 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5687 $sidhash->{$sid} = $sid if $sid;
5690 foreach my $sid (sort keys %$sidhash) {
5695 my $alloc_vmstate_volid = sub {
5696 my ($storecfg, $vmid, $conf, $snapname) = @_;
5698 # Note: we try to be smart when selecting a $target storage
5702 # search shared storage first
5703 foreach_writable_storage
($conf, sub {
5705 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5706 return if !$scfg->{shared
};
5708 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5712 # now search local storage
5713 foreach_writable_storage
($conf, sub {
5715 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5716 return if $scfg->{shared
};
5718 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5722 $target = 'local' if !$target;
5724 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5725 # we abort live save after $conf->{memory}, so we need at max twice that space
5726 my $size = $conf->{memory
}*2 + $driver_state_size;
5728 my $name = "vm-$vmid-state-$snapname";
5729 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5730 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5731 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5736 my $snapshot_prepare = sub {
5737 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5741 my $updatefn = sub {
5743 my $conf = load_config
($vmid);
5745 die "you can't take a snapshot if it's a template\n"
5746 if is_template
($conf);
5750 $conf->{lock} = 'snapshot';
5752 die "snapshot name '$snapname' already used\n"
5753 if defined($conf->{snapshots
}->{$snapname});
5755 my $storecfg = PVE
::Storage
::config
();
5756 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5758 $snap = $conf->{snapshots
}->{$snapname} = {};
5760 if ($save_vmstate && check_running
($vmid)) {
5761 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5764 &$snapshot_copy_config($conf, $snap);
5766 $snap->{snapstate
} = "prepare";
5767 $snap->{snaptime
} = time();
5768 $snap->{description
} = $comment if $comment;
5770 # always overwrite machine if we save vmstate. This makes sure we
5771 # can restore it later using correct machine type
5772 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5774 update_config_nolock
($vmid, $conf, 1);
5777 lock_config
($vmid, $updatefn);
5782 my $snapshot_commit = sub {
5783 my ($vmid, $snapname) = @_;
5785 my $updatefn = sub {
5787 my $conf = load_config
($vmid);
5789 die "missing snapshot lock\n"
5790 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5792 my $has_machine_config = defined($conf->{machine
});
5794 my $snap = $conf->{snapshots
}->{$snapname};
5796 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5798 die "wrong snapshot state\n"
5799 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5801 delete $snap->{snapstate
};
5802 delete $conf->{lock};
5804 my $newconf = &$snapshot_apply_config($conf, $snap);
5806 delete $newconf->{machine
} if !$has_machine_config;
5808 $newconf->{parent
} = $snapname;
5810 update_config_nolock
($vmid, $newconf, 1);
5813 lock_config
($vmid, $updatefn);
5816 sub snapshot_rollback
{
5817 my ($vmid, $snapname) = @_;
5821 my $storecfg = PVE
::Storage
::config
();
5823 my $conf = load_config
($vmid);
5825 my $get_snapshot_config = sub {
5827 die "you can't rollback if vm is a template\n" if is_template
($conf);
5829 my $res = $conf->{snapshots
}->{$snapname};
5831 die "snapshot '$snapname' does not exist\n" if !defined($res);
5836 my $snap = &$get_snapshot_config();
5838 foreach_drive
($snap, sub {
5839 my ($ds, $drive) = @_;
5841 return if drive_is_cdrom
($drive);
5843 my $volid = $drive->{file
};
5845 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5848 my $updatefn = sub {
5850 $conf = load_config
($vmid);
5852 $snap = &$get_snapshot_config();
5854 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5855 if $snap->{snapstate
};
5859 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5862 die "unable to rollback vm $vmid: vm is running\n"
5863 if check_running
($vmid);
5866 $conf->{lock} = 'rollback';
5868 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5869 delete $conf->{lock};
5875 my $has_machine_config = defined($conf->{machine
});
5877 # copy snapshot config to current config
5878 $conf = &$snapshot_apply_config($conf, $snap);
5879 $conf->{parent
} = $snapname;
5881 # Note: old code did not store 'machine', so we try to be smart
5882 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5883 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5884 # we remove the 'machine' configuration if not explicitly specified
5885 # in the original config.
5886 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5889 update_config_nolock
($vmid, $conf, 1);
5891 if (!$prepare && $snap->{vmstate
}) {
5892 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5893 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5897 lock_config
($vmid, $updatefn);
5899 foreach_drive
($snap, sub {
5900 my ($ds, $drive) = @_;
5902 return if drive_is_cdrom
($drive);
5904 my $volid = $drive->{file
};
5905 my $device = "drive-$ds";
5907 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5911 lock_config
($vmid, $updatefn);
5914 my $savevm_wait = sub {
5918 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5919 if (!$stat->{status
}) {
5920 die "savevm not active\n";
5921 } elsif ($stat->{status
} eq 'active') {
5924 } elsif ($stat->{status
} eq 'completed') {
5927 die "query-savevm returned status '$stat->{status}'\n";
5932 sub do_snapshots_with_qemu
{
5933 my ($storecfg, $volid) = @_;
5935 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5937 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5938 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5942 if ($volid =~ m/\.(qcow2|qed)$/){
5949 sub snapshot_create
{
5950 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5952 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5954 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5956 my $config = load_config
($vmid);
5958 my $running = check_running
($vmid);
5960 my $freezefs = $running && $config->{agent
};
5961 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5966 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5967 warn "guest-fsfreeze-freeze problems - $@" if $@;
5971 # create internal snapshots of all drives
5973 my $storecfg = PVE
::Storage
::config
();
5976 if ($snap->{vmstate
}) {
5977 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5978 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5979 &$savevm_wait($vmid);
5981 vm_mon_cmd
($vmid, "savevm-start");
5985 foreach_drive
($snap, sub {
5986 my ($ds, $drive) = @_;
5988 return if drive_is_cdrom
($drive);
5990 my $volid = $drive->{file
};
5991 my $device = "drive-$ds";
5993 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5994 $drivehash->{$ds} = 1;
6000 eval { vm_mon_cmd
($vmid, "savevm-end") };
6004 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6005 warn "guest-fsfreeze-thaw problems - $@" if $@;
6008 # savevm-end is async, we need to wait
6010 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6011 if (!$stat->{bytes
}) {
6014 print "savevm not yet finished\n";
6022 warn "snapshot create failed: starting cleanup\n";
6023 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6028 &$snapshot_commit($vmid, $snapname);
6031 # Note: $drivehash is only set when called from snapshot_create.
6032 sub snapshot_delete
{
6033 my ($vmid, $snapname, $force, $drivehash) = @_;
6040 my $unlink_parent = sub {
6041 my ($confref, $new_parent) = @_;
6043 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6045 $confref->{parent
} = $new_parent;
6047 delete $confref->{parent
};
6052 my $updatefn = sub {
6053 my ($remove_drive) = @_;
6055 my $conf = load_config
($vmid);
6059 die "you can't delete a snapshot if vm is a template\n"
6060 if is_template
($conf);
6063 $snap = $conf->{snapshots
}->{$snapname};
6065 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6067 # remove parent refs
6069 &$unlink_parent($conf, $snap->{parent
});
6070 foreach my $sn (keys %{$conf->{snapshots
}}) {
6071 next if $sn eq $snapname;
6072 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6076 if ($remove_drive) {
6077 if ($remove_drive eq 'vmstate') {
6078 delete $snap->{$remove_drive};
6080 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6081 my $volid = $drive->{file
};
6082 delete $snap->{$remove_drive};
6083 add_unused_volume
($conf, $volid);
6088 $snap->{snapstate
} = 'delete';
6090 delete $conf->{snapshots
}->{$snapname};
6091 delete $conf->{lock} if $drivehash;
6092 foreach my $volid (@$unused) {
6093 add_unused_volume
($conf, $volid);
6097 update_config_nolock
($vmid, $conf, 1);
6100 lock_config
($vmid, $updatefn);
6102 # now remove vmstate file
6104 my $storecfg = PVE
::Storage
::config
();
6106 if ($snap->{vmstate
}) {
6107 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6109 die $err if !$force;
6112 # save changes (remove vmstate from snapshot)
6113 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6116 # now remove all internal snapshots
6117 foreach_drive
($snap, sub {
6118 my ($ds, $drive) = @_;
6120 return if drive_is_cdrom
($drive);
6122 my $volid = $drive->{file
};
6123 my $device = "drive-$ds";
6125 if (!$drivehash || $drivehash->{$ds}) {
6126 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6128 die $err if !$force;
6133 # save changes (remove drive fron snapshot)
6134 lock_config
($vmid, $updatefn, $ds) if !$force;
6135 push @$unused, $volid;
6138 # now cleanup config
6140 lock_config
($vmid, $updatefn);
6144 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6147 foreach_drive
($conf, sub {
6148 my ($ds, $drive) = @_;
6150 return if drive_is_cdrom
($drive);
6151 my $volid = $drive->{file
};
6152 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6155 return $err ?
0 : 1;
6158 sub template_create
{
6159 my ($vmid, $conf, $disk) = @_;
6161 my $storecfg = PVE
::Storage
::config
();
6163 foreach_drive
($conf, sub {
6164 my ($ds, $drive) = @_;
6166 return if drive_is_cdrom
($drive);
6167 return if $disk && $ds ne $disk;
6169 my $volid = $drive->{file
};
6170 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6172 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6173 $drive->{file
} = $voliddst;
6174 $conf->{$ds} = print_drive
($vmid, $drive);
6175 update_config_nolock
($vmid, $conf, 1);
6182 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6185 sub qemu_img_convert
{
6186 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6188 my $storecfg = PVE
::Storage
::config
();
6189 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6190 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6192 if ($src_storeid && $dst_storeid) {
6194 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6196 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6197 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6199 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6200 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6202 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6203 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6206 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6207 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6208 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6212 if($line =~ m/\((\S+)\/100\
%\)/){
6214 my $transferred = int($size * $percent / 100);
6215 my $remaining = $size - $transferred;
6217 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6222 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6224 die "copy failed: $err" if $err;
6228 sub qemu_img_format
{
6229 my ($scfg, $volname) = @_;
6231 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6238 sub qemu_drive_mirror
{
6239 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6241 my $storecfg = PVE
::Storage
::config
();
6242 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6244 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6246 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6248 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6250 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6251 $opts->{format
} = $format if $format;
6253 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6256 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6258 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6259 my $stat = @$stats[0];
6260 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6261 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6263 my $busy = $stat->{busy
};
6264 my $ready = $stat->{ready
};
6266 if (my $total = $stat->{len
}) {
6267 my $transferred = $stat->{offset
} || 0;
6268 my $remaining = $total - $transferred;
6269 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6271 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6275 if ($stat->{ready
} eq 'true') {
6277 last if $vmiddst != $vmid;
6279 # try to switch the disk if source and destination are on the same guest
6280 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6282 die $@ if $@ !~ m/cannot be completed/;
6291 my $cancel_job = sub {
6292 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6294 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6295 my $stat = @$stats[0];
6302 eval { &$cancel_job(); };
6303 die "mirroring error: $err";
6306 if ($vmiddst != $vmid) {
6307 # if we clone a disk for a new target vm, we don't switch the disk
6308 &$cancel_job(); # so we call block-job-cancel
6313 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6314 $newvmid, $storage, $format, $full, $newvollist) = @_;
6319 print "create linked clone of drive $drivename ($drive->{file})\n";
6320 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6321 push @$newvollist, $newvolid;
6323 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6324 $storeid = $storage if $storage;
6326 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6328 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6329 $format = qemu_img_format
($scfg, $volname);
6332 # test if requested format is supported - else use default
6333 my $supported = grep { $_ eq $format } @$validFormats;
6334 $format = $defFormat if !$supported;
6336 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6338 print "create full clone of drive $drivename ($drive->{file})\n";
6339 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6340 push @$newvollist, $newvolid;
6342 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6344 if (!$running || $snapname) {
6345 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6347 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6351 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6354 $disk->{format
} = undef;
6355 $disk->{file
} = $newvolid;
6356 $disk->{size
} = $size;
6361 # this only works if VM is running
6362 sub get_current_qemu_machine
{
6365 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6366 my $res = vm_qmp_command
($vmid, $cmd);
6368 my ($current, $default);
6369 foreach my $e (@$res) {
6370 $default = $e->{name
} if $e->{'is-default'};
6371 $current = $e->{name
} if $e->{'is-current'};
6374 # fallback to the default machine if current is not supported by qemu
6375 return $current || $default || 'pc';
6378 sub qemu_machine_feature_enabled
{
6379 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6384 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6386 $current_major = $3;
6387 $current_minor = $4;
6389 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6391 $current_major = $1;
6392 $current_minor = $2;
6395 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6400 sub qemu_machine_pxe
{
6401 my ($vmid, $conf, $machine) = @_;
6403 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6405 foreach my $opt (keys %$conf) {
6406 next if $opt !~ m/^net(\d+)$/;
6407 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6409 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6410 return $machine.".pxe" if $romfile =~ m/pxe/;
6416 sub qemu_use_old_bios_files
{
6417 my ($machine_type) = @_;
6419 return if !$machine_type;
6421 my $use_old_bios_files = undef;
6423 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6425 $use_old_bios_files = 1;
6427 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6428 # load new efi bios files on migration. So this hack is required to allow
6429 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6430 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6431 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6434 return ($use_old_bios_files, $machine_type);
6441 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6442 my (undef, $id, $function) = @_;
6443 my $res = { id
=> $id, function
=> $function};
6444 push @{$devices->{$id}}, $res;
6450 sub vm_iothreads_list
{
6453 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6456 foreach my $iothread (@$res) {
6457 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6464 my ($conf, $drive) = @_;
6468 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6470 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6476 my $controller = int($drive->{index} / $maxdev);
6477 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6479 return ($maxdev, $controller, $controller_prefix);
6482 # bash completion helper
6484 sub complete_backup_archives
{
6485 my ($cmdname, $pname, $cvalue) = @_;
6487 my $cfg = PVE
::Storage
::config
();
6491 if ($cvalue =~ m/^([^:]+):/) {
6495 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6498 foreach my $id (keys %$data) {
6499 foreach my $item (@{$data->{$id}}) {
6500 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6501 push @$res, $item->{volid
} if defined($item->{volid
});
6508 my $complete_vmid_full = sub {
6511 my $idlist = vmstatus
();
6515 foreach my $id (keys %$idlist) {
6516 my $d = $idlist->{$id};
6517 if (defined($running)) {
6518 next if $d->{template
};
6519 next if $running && $d->{status
} ne 'running';
6520 next if !$running && $d->{status
} eq 'running';
6529 return &$complete_vmid_full();
6532 sub complete_vmid_stopped
{
6533 return &$complete_vmid_full(0);
6536 sub complete_vmid_running
{
6537 return &$complete_vmid_full(1);
6540 sub complete_storage
{
6542 my $cfg = PVE
::Storage
::config
();
6543 my $ids = $cfg->{ids
};
6546 foreach my $sid (keys %$ids) {
6547 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6548 next if !$ids->{$sid}->{content
}->{images
};