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);
32 use PVE
::RPCEnvironment
;
33 use Time
::HiRes
qw(gettimeofday);
34 use File
::Copy
qw(copy);
37 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
39 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
41 # Note about locking: we use flock on the config file protect
42 # against concurent actions.
43 # Aditionaly, we have a 'lock' setting in the config file. This
44 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
45 # allowed when such lock is set. But you can ignore this kind of
46 # lock with the --skiplock flag.
48 cfs_register_file
('/qemu-server/',
52 PVE
::JSONSchema
::register_standard_option
('skiplock', {
53 description
=> "Ignore locks - only root is allowed to use this option.",
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 #no warnings 'redefine';
74 my ($controller, $vmid, $option, $value) = @_;
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
81 my $nodename = PVE
::INotify
::nodename
();
83 mkdir "/etc/pve/nodes/$nodename";
84 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
87 my $var_run_tmpdir = "/var/run/qemu-server";
88 mkdir $var_run_tmpdir;
90 my $lock_dir = "/var/lock/qemu-server";
93 my $pcisysfs = "/sys/bus/pci";
95 my $cpu_vendor_list = {
97 486 => 'GenuineIntel',
98 pentium
=> 'GenuineIntel',
99 pentium2
=> 'GenuineIntel',
100 pentium3
=> 'GenuineIntel',
101 coreduo
=> 'GenuineIntel',
102 core2duo
=> 'GenuineIntel',
103 Conroe
=> 'GenuineIntel',
104 Penryn
=> 'GenuineIntel',
105 Nehalem
=> 'GenuineIntel',
106 Westmere
=> 'GenuineIntel',
107 SandyBridge
=> 'GenuineIntel',
108 IvyBridge
=> 'GenuineIntel',
109 Haswell
=> 'GenuineIntel',
110 'Haswell-noTSX' => 'GenuineIntel',
111 Broadwell
=> 'GenuineIntel',
112 'Broadwell-noTSX' => 'GenuineIntel',
115 athlon
=> 'AuthenticAMD',
116 phenom
=> 'AuthenticAMD',
117 Opteron_G1
=> 'AuthenticAMD',
118 Opteron_G2
=> 'AuthenticAMD',
119 Opteron_G3
=> 'AuthenticAMD',
120 Opteron_G4
=> 'AuthenticAMD',
121 Opteron_G5
=> 'AuthenticAMD',
123 # generic types, use vendor from host node
133 description
=> "Emulated CPU type.",
135 enum
=> [ sort keys %$cpu_vendor_list ],
136 format_description
=> 'cputype',
141 description
=> "Do not identify as a KVM virtual machine.",
152 enum
=> [qw(i6300esb ib700)],
153 description
=> "Watchdog type to emulate.",
154 default => 'i6300esb',
159 enum
=> [qw(reset shutdown poweroff pause debug none)],
160 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
164 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
170 description
=> "Specifies whether a VM will be started during system bootup.",
176 description
=> "Automatic restart after crash (currently ignored).",
181 type
=> 'string', format
=> 'pve-hotplug-features',
182 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'.",
183 default => 'network,disk,usb',
188 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
194 description
=> "Lock/unlock the VM.",
195 enum
=> [qw(migrate backup snapshot rollback)],
200 description
=> "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
208 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.",
216 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
223 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
229 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",
237 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
238 enum
=> PVE
::Tools
::kvmkeymaplist
(),
243 type
=> 'string', format
=> 'dns-name',
244 description
=> "Set a name for the VM. Only used on the configuration web interface.",
249 description
=> "scsi controller model",
250 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
256 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
261 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
262 description
=> <<EODESC,
263 Used to enable special optimization/features for specific
266 other => unspecified OS
267 wxp => Microsoft Windows XP
268 w2k => Microsoft Windows 2000
269 w2k3 => Microsoft Windows 2003
270 w2k8 => Microsoft Windows 2008
271 wvista => Microsoft Windows Vista
272 win7 => Microsoft Windows 7
273 win8 => Microsoft Windows 8/2012
274 l24 => Linux 2.4 Kernel
275 l26 => Linux 2.6/3.X Kernel
276 solaris => solaris/opensolaris/openindiania kernel
278 other|l24|l26|solaris ... no special behaviour
279 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
285 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
286 pattern
=> '[acdn]{1,4}',
291 type
=> 'string', format
=> 'pve-qm-bootdisk',
292 description
=> "Enable booting from specified disk.",
293 pattern
=> '(ide|sata|scsi|virtio)\d+',
298 description
=> "The number of CPUs. Please use option -sockets instead.",
305 description
=> "The number of CPU sockets.",
312 description
=> "The number of cores per socket.",
319 description
=> "Enable/disable NUMA.",
325 description
=> "Number of hotplugged vcpus.",
332 description
=> "Enable/disable ACPI.",
338 description
=> "Enable/disable Qemu GuestAgent.",
344 description
=> "Enable/disable KVM hardware virtualization.",
350 description
=> "Enable/disable time drift fix.",
356 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
361 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
366 description
=> "Select the VGA type. If you want to use high resolution" .
367 " modes (>= 1280x1024x16) then you should use the options " .
368 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
369 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
370 "display sever. For win* OS you can select how many independent " .
371 "displays you want, Linux guests can add displays them self. " .
372 "You can also run without any graphic card, using a serial device" .
374 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
378 type
=> 'string', format
=> 'pve-qm-watchdog',
379 description
=> "Create a virtual hardware watchdog device. Once enabled" .
380 " (by a guest action), the watchdog must be periodically polled " .
381 "by an agent inside the guest or else the watchdog will reset " .
382 "the guest (or execute the respective action specified)",
387 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
388 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'.",
389 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
392 startup
=> get_standard_option
('pve-startup-order'),
396 description
=> "Enable/disable Template.",
402 description
=> <<EODESCR,
403 Arbitrary arguments passed to kvm, for example:
405 args: -no-reboot -no-hpet
407 NOTE: this option is for experts only.
414 description
=> "Enable/disable the USB tablet device. This device is " .
415 "usually needed to allow absolute mouse positioning with VNC. " .
416 "Else the mouse runs out of sync with normal VNC clients. " .
417 "If you're running lots of console-only guests on one host, " .
418 "you may consider disabling this to save some context switches. " .
419 "This is turned off by default if you use spice (-vga=qxl).",
424 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
428 migrate_downtime
=> {
431 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
437 type
=> 'string', format
=> 'pve-qm-drive',
438 typetext
=> 'volume',
439 description
=> "This is an alias for option -ide2",
443 description
=> "Emulated CPU type.",
447 parent
=> get_standard_option
('pve-snapshot-name', {
449 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
453 description
=> "Timestamp for snapshots.",
459 type
=> 'string', format
=> 'pve-volume-id',
460 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
463 description
=> "Specific the Qemu machine type.",
465 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
470 description
=> "Specify SMBIOS type 1 fields.",
471 type
=> 'string', format
=> 'pve-qm-smbios1',
478 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
484 enum
=> [ qw(seabios ovmf) ],
485 description
=> "Select BIOS implementation.",
486 default => 'seabios',
490 # what about other qemu settings ?
492 #machine => 'string',
505 ##soundhw => 'string',
507 while (my ($k, $v) = each %$confdesc) {
508 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
511 my $MAX_IDE_DISKS = 4;
512 my $MAX_SCSI_DISKS = 14;
513 my $MAX_VIRTIO_DISKS = 16;
514 my $MAX_SATA_DISKS = 6;
515 my $MAX_USB_DEVICES = 5;
517 my $MAX_UNUSED_DISKS = 8;
518 my $MAX_HOSTPCI_DEVICES = 4;
519 my $MAX_SERIAL_PORTS = 4;
520 my $MAX_PARALLEL_PORTS = 3;
522 my $MAX_MEM = 4194304;
523 my $STATICMEM = 1024;
528 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
529 description
=> "CPUs accessing this numa node.",
530 format_description
=> "id[-id];...",
534 description
=> "Amount of memory this numa node provides.",
535 format_description
=> "mb",
540 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
541 description
=> "host numa nodes to use",
542 format_description
=> "id[-id];...",
547 enum
=> [qw(preferred bind interleave)],
548 format_description
=> 'preferred|bind|interleave',
549 description
=> "numa allocation policy.",
553 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
556 type
=> 'string', format
=> $numa_fmt,
557 description
=> "numa topology",
559 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
561 for (my $i = 0; $i < $MAX_NUMA; $i++) {
562 $confdesc->{"numa$i"} = $numadesc;
565 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
566 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
567 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
568 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
573 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
574 description
=> "MAC address",
575 format_description
=> "XX:XX:XX:XX:XX:XX",
578 model
=> { alias
=> 'macaddr', default_key
=> 1 },
579 (map { $_ => { group
=> 'model' } } @$nic_model_list),
582 description
=> 'Bridge to attach the network device to.',
583 format_description
=> 'bridge',
588 minimum
=> 0, maximum
=> 16,
589 description
=> 'Number of packet queues to be used on the device.',
590 format_description
=> 'number',
596 description
=> 'Rate limit in mbps as floating point number.',
597 format_description
=> 'mbps',
602 minimum
=> 2, maximum
=> 4094,
603 description
=> 'VLAN tag to apply to packets on this interface.',
604 format_description
=> 'vlanid',
609 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
610 description
=> 'VLAN trunks to pass through this interface.',
611 format_description
=> 'id;id...',
616 description
=> 'Whether this interface should be protected by the firewall.',
617 format_description
=> '0|1',
622 description
=> 'Whether this interface should be DISconnected (like pulling the plug).',
623 format_description
=> '0|1',
629 type
=> 'string', format
=> 'pve-qm-net',
630 description
=> <<EODESCR,
631 Specify network devices.
633 MODEL is one of: $nic_model_list_txt
635 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
636 automatically generated if not specified.
638 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
640 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'.
642 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
648 The DHCP server assign addresses to the guest starting from 10.0.2.15.
652 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
654 for (my $i = 0; $i < $MAX_NETS; $i++) {
655 $confdesc->{"net$i"} = $netdesc;
658 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
659 sub verify_volume_id_or_qm_path
{
660 my ($volid, $noerr) = @_;
662 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
666 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
667 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
669 return undef if $noerr;
677 my %drivedesc_base = (
678 volume
=> { alias
=> 'file' },
681 format
=> 'pve-volume-id-or-qm-path',
683 format_description
=> 'volume',
684 description
=> "The drive's backing volume.",
688 format_description
=> 'cdrom|disk',
689 enum
=> [qw(cdrom disk)],
690 description
=> "The drive's media type.",
696 format_description
=> 'count',
697 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
702 format_description
=> 'count',
703 description
=> "Force the drive's physical geometry to have a specific head count.",
708 format_description
=> 'count',
709 description
=> "Force the drive's physical geometry to have a specific sector count.",
714 format_description
=> 'none|lba|auto',
715 enum
=> [qw(none lba auto)],
716 description
=> "Force disk geometry bios translation mode.",
721 format_description
=> 'on|off',
722 description
=> "Whether the drive should be included when making snapshots.",
727 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
728 enum
=> [qw(none writethrough writeback unsafe directsync)],
729 description
=> "The drive's cache mode",
734 format_description
=> 'drive format',
735 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
736 description
=> "The drive's backing file's data format.",
741 format
=> 'disk-size',
742 description
=> "Disk size. This is purely informational and has no effect.",
747 format_description
=> 'on|off',
748 description
=> "Whether the drive should be included when making backups.",
753 format_description
=> 'enospc|ignore|report|stop',
754 enum
=> [qw(enospc ignore report stop)],
755 description
=> 'Write error action.',
760 format_description
=> 'native|threads',
761 enum
=> [qw(native threads)],
762 description
=> 'AIO type to use.',
767 format_description
=> 'ignore|on',
768 enum
=> [qw(ignore on)],
769 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
774 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
779 format
=> 'urlencoded',
780 format_description
=> 'serial',
781 maxLength
=> 20*3, # *3 since it's %xx url enoded
782 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
790 format_description
=> 'ignore|report|stop',
791 enum
=> [qw(ignore report stop)],
792 description
=> 'Read error action.',
797 my %iothread_fmt = ( iothread
=> {
799 format_description
=> 'off|on',
800 description
=> "Whether to use iothreads for this drive",
807 format
=> 'urlencoded',
808 format_description
=> 'model',
809 maxLength
=> 40*3, # *3 since it's %xx url enoded
810 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
818 format_description
=> 'nbqueues',
819 description
=> "Number of queues.",
825 my $add_throttle_desc = sub {
826 my ($key, $type, $what, $size, $longsize) = @_;
827 $drivedesc_base{$key} = {
829 format_description
=> $size,
830 description
=> "Maximum $what speed in $longsize per second.",
834 # throughput: (leaky bucket)
835 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
836 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
837 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
838 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
839 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
840 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
841 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
842 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
843 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
845 # pools: (pool of IO before throttling starts taking effect)
846 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
847 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
848 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
849 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
850 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
851 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
861 type
=> 'string', format
=> $ide_fmt,
862 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
864 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
873 type
=> 'string', format
=> $scsi_fmt,
874 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
876 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
884 type
=> 'string', format
=> $sata_fmt,
885 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
887 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
896 type
=> 'string', format
=> $virtio_fmt,
897 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
899 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
912 type
=> 'string', format
=> 'pve-qm-usb-device',
913 format_description
=> 'HOSTUSBDEVICE|spice',
914 description
=> 'The Host USB device or port or the value spice',
919 format_description
=> 'yes|no',
920 description
=> 'Specifies whether if given host option is a USB3 device or port',
926 type
=> 'string', format
=> $usb_fmt,
927 description
=> <<EODESCR,
928 Configure an USB device (n is 0 to 4). This can be used to
929 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
931 'bus-port(.port)*' (decimal numbers) or
932 'vendor_id:product_id' (hexadeciaml numbers) or
935 You can use the 'lsusb -t' command to list existing usb devices.
937 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
939 The value 'spice' can be used to add a usb redirection devices for spice.
941 The 'usb3' option determines whether the device is a USB3 device or not (this does currently not work reliably with spice redirection and is then ignored).
945 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
947 # NOTE: the match-groups of this regex are used in parse_hostpci
948 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
953 pattern
=> qr/$PCIRE(;$PCIRE)*/,
954 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
955 description
=> "The PCI ID of a host's PCI device or a list of PCI virtual functions of the host.",
973 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
977 type
=> 'string', format
=> 'pve-qm-hostpci',
978 description
=> <<EODESCR,
979 Map host pci devices. HOSTPCIDEVICE syntax is:
981 'bus:dev.func' (hexadecimal numbers)
983 You can us the 'lspci' command to list existing pci devices.
985 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
987 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
989 Experimental: user reported problems with this option.
992 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
997 pattern
=> '(/dev/.+|socket)',
998 description
=> <<EODESCR,
999 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).
1001 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1003 Experimental: user reported problems with this option.
1010 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1011 description
=> <<EODESCR,
1012 Map host parallel devices (n is 0 to 2).
1014 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1016 Experimental: user reported problems with this option.
1020 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1021 $confdesc->{"parallel$i"} = $paralleldesc;
1024 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1025 $confdesc->{"serial$i"} = $serialdesc;
1028 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1029 $confdesc->{"hostpci$i"} = $hostpcidesc;
1032 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1033 $drivename_hash->{"ide$i"} = 1;
1034 $confdesc->{"ide$i"} = $idedesc;
1037 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1038 $drivename_hash->{"sata$i"} = 1;
1039 $confdesc->{"sata$i"} = $satadesc;
1042 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1043 $drivename_hash->{"scsi$i"} = 1;
1044 $confdesc->{"scsi$i"} = $scsidesc ;
1047 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1048 $drivename_hash->{"virtio$i"} = 1;
1049 $confdesc->{"virtio$i"} = $virtiodesc;
1052 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1053 $confdesc->{"usb$i"} = $usbdesc;
1058 type
=> 'string', format
=> 'pve-volume-id',
1059 description
=> "Reference to unused volumes.",
1062 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1063 $confdesc->{"unused$i"} = $unuseddesc;
1066 my $kvm_api_version = 0;
1070 return $kvm_api_version if $kvm_api_version;
1072 my $fh = IO
::File-
>new("</dev/kvm") ||
1075 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1076 $kvm_api_version = $v;
1081 return $kvm_api_version;
1084 my $kvm_user_version;
1086 sub kvm_user_version
{
1088 return $kvm_user_version if $kvm_user_version;
1090 $kvm_user_version = 'unknown';
1094 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1095 $kvm_user_version = $2;
1099 eval { run_command
("kvm -version", outfunc
=> $code); };
1102 return $kvm_user_version;
1106 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1108 sub valid_drive_names
{
1109 # order is important - used to autoselect boot disk
1110 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1111 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1112 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1113 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1116 sub is_valid_drivename
{
1119 return defined($drivename_hash->{$dev});
1124 return defined($confdesc->{$key});
1128 return $nic_model_list;
1131 sub os_list_description
{
1135 wxp
=> 'Windows XP',
1136 w2k
=> 'Windows 2000',
1137 w2k3
=>, 'Windows 2003',
1138 w2k8
=> 'Windows 2008',
1139 wvista
=> 'Windows Vista',
1140 win7
=> 'Windows 7',
1141 win8
=> 'Windows 8/2012',
1149 sub get_cdrom_path
{
1151 return $cdrom_path if $cdrom_path;
1153 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1154 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1155 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1159 my ($storecfg, $vmid, $cdrom) = @_;
1161 if ($cdrom eq 'cdrom') {
1162 return get_cdrom_path
();
1163 } elsif ($cdrom eq 'none') {
1165 } elsif ($cdrom =~ m
|^/|) {
1168 return PVE
::Storage
::path
($storecfg, $cdrom);
1172 # try to convert old style file names to volume IDs
1173 sub filename_to_volume_id
{
1174 my ($vmid, $file, $media) = @_;
1176 if (!($file eq 'none' || $file eq 'cdrom' ||
1177 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1179 return undef if $file =~ m
|/|;
1181 if ($media && $media eq 'cdrom') {
1182 $file = "local:iso/$file";
1184 $file = "local:$vmid/$file";
1191 sub verify_media_type
{
1192 my ($opt, $vtype, $media) = @_;
1197 if ($media eq 'disk') {
1199 } elsif ($media eq 'cdrom') {
1202 die "internal error";
1205 return if ($vtype eq $etype);
1207 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1210 sub cleanup_drive_path
{
1211 my ($opt, $storecfg, $drive) = @_;
1213 # try to convert filesystem paths to volume IDs
1215 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1216 ($drive->{file
} !~ m
|^/dev/.+|) &&
1217 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1218 ($drive->{file
} !~ m/^\d+$/)) {
1219 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1220 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1221 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1222 verify_media_type
($opt, $vtype, $drive->{media
});
1223 $drive->{file
} = $volid;
1226 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1229 sub parse_hotplug_features
{
1234 return $res if $data eq '0';
1236 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1238 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1239 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1242 warn "ignoring unknown hotplug feature '$feature'\n";
1248 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1249 sub pve_verify_hotplug_features
{
1250 my ($value, $noerr) = @_;
1252 return $value if parse_hotplug_features
($value);
1254 return undef if $noerr;
1256 die "unable to parse hotplug option\n";
1259 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1260 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1261 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1262 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1263 # [,iothread=on][,serial=serial][,model=model]
1266 my ($key, $data) = @_;
1268 my ($interface, $index);
1270 if ($key =~ m/^([^\d]+)(\d+)$/) {
1277 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1278 : $confdesc->{$key}->{format
};
1280 warn "invalid drive key: $key\n";
1283 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1284 return undef if !$res;
1285 $res->{interface
} = $interface;
1286 $res->{index} = $index;
1289 foreach my $opt (qw(bps bps_rd bps_wr)) {
1290 if (my $bps = defined(delete $res->{$opt})) {
1291 if (defined($res->{"m$opt"})) {
1292 warn "both $opt and m$opt specified\n";
1296 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1299 return undef if $error;
1301 return undef if $res->{mbps_rd
} && $res->{mbps
};
1302 return undef if $res->{mbps_wr
} && $res->{mbps
};
1303 return undef if $res->{iops_rd
} && $res->{iops
};
1304 return undef if $res->{iops_wr
} && $res->{iops
};
1306 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1307 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1308 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1309 return undef if $res->{interface
} eq 'virtio';
1312 if (my $size = $res->{size
}) {
1313 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1320 my ($vmid, $drive) = @_;
1321 my $data = { %$drive };
1322 delete $data->{$_} for qw(index interface);
1323 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1327 my($fh, $noerr) = @_;
1330 my $SG_GET_VERSION_NUM = 0x2282;
1332 my $versionbuf = "\x00" x
8;
1333 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1335 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1338 my $version = unpack("I", $versionbuf);
1339 if ($version < 30000) {
1340 die "scsi generic interface too old\n" if !$noerr;
1344 my $buf = "\x00" x
36;
1345 my $sensebuf = "\x00" x
8;
1346 my $cmd = pack("C x3 C x1", 0x12, 36);
1348 # see /usr/include/scsi/sg.h
1349 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";
1351 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1352 length($sensebuf), 0, length($buf), $buf,
1353 $cmd, $sensebuf, 6000);
1355 $ret = ioctl($fh, $SG_IO, $packet);
1357 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1361 my @res = unpack($sg_io_hdr_t, $packet);
1362 if ($res[17] || $res[18]) {
1363 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1368 (my $byte0, my $byte1, $res->{vendor
},
1369 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1371 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1372 $res->{type
} = $byte0 & 31;
1380 my $fh = IO
::File-
>new("+<$path") || return undef;
1381 my $res = scsi_inquiry
($fh, 1);
1387 sub machine_type_is_q35
{
1390 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1393 sub print_tabletdevice_full
{
1396 my $q35 = machine_type_is_q35
($conf);
1398 # we use uhci for old VMs because tablet driver was buggy in older qemu
1399 my $usbbus = $q35 ?
"ehci" : "uhci";
1401 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1404 sub print_drivedevice_full
{
1405 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1410 if ($drive->{interface
} eq 'virtio') {
1411 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1412 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1413 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1414 } elsif ($drive->{interface
} eq 'scsi') {
1416 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1417 my $unit = $drive->{index} % $maxdev;
1418 my $devicetype = 'hd';
1420 if (drive_is_cdrom
($drive)) {
1423 if ($drive->{file
} =~ m
|^/|) {
1424 $path = $drive->{file
};
1425 if (my $info = path_is_scsi
($path)) {
1426 if ($info->{type
} == 0) {
1427 $devicetype = 'block';
1428 } elsif ($info->{type
} == 1) { # tape
1429 $devicetype = 'generic';
1433 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1436 if($path =~ m/^iscsi\:\/\
//){
1437 $devicetype = 'generic';
1441 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1442 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1444 $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}";
1447 } elsif ($drive->{interface
} eq 'ide'){
1449 my $controller = int($drive->{index} / $maxdev);
1450 my $unit = $drive->{index} % $maxdev;
1451 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1453 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1454 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1455 $model = URI
::Escape
::uri_unescape
($model);
1456 $device .= ",model=$model";
1458 } elsif ($drive->{interface
} eq 'sata'){
1459 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1460 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1461 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1462 } elsif ($drive->{interface
} eq 'usb') {
1464 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1466 die "unsupported interface type";
1469 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1474 sub get_initiator_name
{
1477 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1478 while (defined(my $line = <$fh>)) {
1479 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1488 sub print_drive_full
{
1489 my ($storecfg, $vmid, $drive) = @_;
1492 my $volid = $drive->{file
};
1495 if (drive_is_cdrom
($drive)) {
1496 $path = get_iso_path
($storecfg, $vmid, $volid);
1498 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1500 $path = PVE
::Storage
::path
($storecfg, $volid);
1501 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1502 $format = qemu_img_format
($scfg, $volname);
1510 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);
1511 foreach my $o (@qemu_drive_options) {
1512 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1514 if (my $serial = $drive->{serial
}) {
1515 $serial = URI
::Escape
::uri_unescape
($serial);
1516 $opts .= ",serial=$serial";
1519 $opts .= ",format=$format" if $format && !$drive->{format
};
1521 foreach my $o (qw(bps bps_rd bps_wr)) {
1522 my $v = $drive->{"m$o"};
1523 $opts .= ",$o=" . int($v*1024*1024) if $v;
1526 my $cache_direct = 0;
1528 if (my $cache = $drive->{cache
}) {
1529 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1530 } elsif (!drive_is_cdrom
($drive)) {
1531 $opts .= ",cache=none";
1535 # aio native works only with O_DIRECT
1536 if (!$drive->{aio
}) {
1538 $opts .= ",aio=native";
1540 $opts .= ",aio=threads";
1544 if (!drive_is_cdrom
($drive)) {
1546 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1547 $detectzeroes = 'off';
1548 } elsif ($drive->{discard
}) {
1549 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1551 # This used to be our default with discard not being specified:
1552 $detectzeroes = 'on';
1554 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1557 my $pathinfo = $path ?
"file=$path," : '';
1559 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1562 sub print_netdevice_full
{
1563 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1565 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1567 my $device = $net->{model
};
1568 if ($net->{model
} eq 'virtio') {
1569 $device = 'virtio-net-pci';
1572 my $pciaddr = print_pci_addr
("$netid", $bridges);
1573 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1574 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1575 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1576 my $vectors = $net->{queues
} * 2 + 2;
1577 $tmpstr .= ",vectors=$vectors,mq=on";
1579 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1581 if ($use_old_bios_files) {
1583 if ($device eq 'virtio-net-pci') {
1584 $romfile = 'pxe-virtio.rom';
1585 } elsif ($device eq 'e1000') {
1586 $romfile = 'pxe-e1000.rom';
1587 } elsif ($device eq 'ne2k') {
1588 $romfile = 'pxe-ne2k_pci.rom';
1589 } elsif ($device eq 'pcnet') {
1590 $romfile = 'pxe-pcnet.rom';
1591 } elsif ($device eq 'rtl8139') {
1592 $romfile = 'pxe-rtl8139.rom';
1594 $tmpstr .= ",romfile=$romfile" if $romfile;
1600 sub print_netdev_full
{
1601 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1604 if ($netid =~ m/^net(\d+)$/) {
1608 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1610 my $ifname = "tap${vmid}i$i";
1612 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1613 die "interface name '$ifname' is too long (max 15 character)\n"
1614 if length($ifname) >= 16;
1616 my $vhostparam = '';
1617 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1619 my $vmname = $conf->{name
} || "vm$vmid";
1622 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1624 if ($net->{bridge
}) {
1625 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1627 $netdev = "type=user,id=$netid,hostname=$vmname";
1630 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1635 sub drive_is_cdrom
{
1638 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1642 sub parse_number_sets
{
1645 foreach my $part (split(/;/, $set)) {
1646 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1647 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1648 push @$res, [ $1, $2 ];
1650 die "invalid range: $part\n";
1659 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1660 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1661 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1668 return undef if !$value;
1670 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1672 my @idlist = split(/;/, $res->{host
});
1673 delete $res->{host
};
1674 foreach my $id (@idlist) {
1675 if ($id =~ /^$PCIRE$/) {
1676 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1678 # should have been caught by parse_property_string already
1679 die "failed to parse PCI id: $id\n";
1685 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1689 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1694 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1701 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1704 sub add_random_macs
{
1705 my ($settings) = @_;
1707 foreach my $opt (keys %$settings) {
1708 next if $opt !~ m/^net(\d+)$/;
1709 my $net = parse_net
($settings->{$opt});
1711 $settings->{$opt} = print_net
($net);
1715 sub vm_is_volid_owner
{
1716 my ($storecfg, $vmid, $volid) = @_;
1718 if ($volid !~ m
|^/|) {
1720 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1721 if ($owner && ($owner == $vmid)) {
1729 sub split_flagged_list
{
1730 my $text = shift || '';
1731 $text =~ s/[,;]/ /g;
1733 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1736 sub join_flagged_list
{
1737 my ($how, $lst) = @_;
1738 join $how, map { $lst->{$_} . $_ } keys %$lst;
1741 sub vmconfig_delete_pending_option
{
1742 my ($conf, $key, $force) = @_;
1744 delete $conf->{pending
}->{$key};
1745 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1746 $pending_delete_hash->{$key} = $force ?
'!' : '';
1747 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1750 sub vmconfig_undelete_pending_option
{
1751 my ($conf, $key) = @_;
1753 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1754 delete $pending_delete_hash->{$key};
1756 if (%$pending_delete_hash) {
1757 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1759 delete $conf->{pending
}->{delete};
1763 sub vmconfig_register_unused_drive
{
1764 my ($storecfg, $vmid, $conf, $drive) = @_;
1766 if (!drive_is_cdrom
($drive)) {
1767 my $volid = $drive->{file
};
1768 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1769 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1774 sub vmconfig_cleanup_pending
{
1777 # remove pending changes when nothing changed
1779 foreach my $opt (keys %{$conf->{pending
}}) {
1780 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1782 delete $conf->{pending
}->{$opt};
1786 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1787 my $pending_delete_hash = {};
1788 while (my ($opt, $force) = each %$current_delete_hash) {
1789 if (defined($conf->{$opt})) {
1790 $pending_delete_hash->{$opt} = $force;
1796 if (%$pending_delete_hash) {
1797 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1799 delete $conf->{pending
}->{delete};
1805 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1809 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1810 format_description
=> 'UUID',
1816 format_description
=> 'str',
1822 format_description
=> 'str',
1828 format_description
=> 'name',
1834 format_description
=> 'name',
1840 format_description
=> 'str',
1846 format_description
=> 'str',
1854 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1861 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1864 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1866 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1867 sub verify_bootdisk
{
1868 my ($value, $noerr) = @_;
1870 return $value if is_valid_drivename
($value);
1872 return undef if $noerr;
1874 die "invalid boot disk '$value'\n";
1877 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1879 my ($value, $noerr) = @_;
1881 return $value if parse_net
($value);
1883 return undef if $noerr;
1885 die "unable to parse network options\n";
1888 sub parse_watchdog
{
1891 return undef if !$value;
1893 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1898 sub parse_usb_device
{
1901 return undef if !$value;
1904 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1905 $res->{vendorid
} = $2;
1906 $res->{productid
} = $4;
1907 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1908 $res->{hostbus
} = $1;
1909 $res->{hostport
} = $2;
1910 } elsif ($value =~ m/^spice$/i) {
1919 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1920 sub verify_usb_device
{
1921 my ($value, $noerr) = @_;
1923 return $value if parse_usb_device
($value);
1925 return undef if $noerr;
1927 die "unable to parse usb device\n";
1930 # add JSON properties for create and set function
1931 sub json_config_properties
{
1934 foreach my $opt (keys %$confdesc) {
1935 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1936 $prop->{$opt} = $confdesc->{$opt};
1943 my ($key, $value) = @_;
1945 die "unknown setting '$key'\n" if !$confdesc->{$key};
1947 my $type = $confdesc->{$key}->{type
};
1949 if (!defined($value)) {
1950 die "got undefined value\n";
1953 if ($value =~ m/[\n\r]/) {
1954 die "property contains a line feed\n";
1957 if ($type eq 'boolean') {
1958 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1959 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1960 die "type check ('boolean') failed - got '$value'\n";
1961 } elsif ($type eq 'integer') {
1962 return int($1) if $value =~ m/^(\d+)$/;
1963 die "type check ('integer') failed - got '$value'\n";
1964 } elsif ($type eq 'number') {
1965 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1966 die "type check ('number') failed - got '$value'\n";
1967 } elsif ($type eq 'string') {
1968 if (my $fmt = $confdesc->{$key}->{format
}) {
1969 if ($fmt eq 'pve-qm-drive') {
1970 # special case - we need to pass $key to parse_drive()
1971 my $drive = parse_drive
($key, $value);
1972 return $value if $drive;
1973 die "unable to parse drive options\n";
1975 PVE
::JSONSchema
::check_format
($fmt, $value);
1978 $value =~ s/^\"(.*)\"$/$1/;
1981 die "internal error"
1985 sub check_iommu_support
{
1986 #fixme : need to check IOMMU support
1987 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1997 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1998 utime undef, undef, $conf;
2002 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2004 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2006 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2008 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2010 # only remove disks owned by this VM
2011 foreach_drive
($conf, sub {
2012 my ($ds, $drive) = @_;
2014 return if drive_is_cdrom
($drive);
2016 my $volid = $drive->{file
};
2018 return if !$volid || $volid =~ m
|^/|;
2020 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2021 return if !$path || !$owner || ($owner != $vmid);
2023 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2026 if ($keep_empty_config) {
2027 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2032 # also remove unused disk
2034 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2037 PVE
::Storage
::foreach_volid
($dl, sub {
2038 my ($volid, $sid, $volname, $d) = @_;
2039 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2048 sub parse_vm_config
{
2049 my ($filename, $raw) = @_;
2051 return undef if !defined($raw);
2054 digest
=> Digest
::SHA
::sha1_hex
($raw),
2059 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2060 || die "got strange filename '$filename'";
2068 my @lines = split(/\n/, $raw);
2069 foreach my $line (@lines) {
2070 next if $line =~ m/^\s*$/;
2072 if ($line =~ m/^\[PENDING\]\s*$/i) {
2073 $section = 'pending';
2074 if (defined($descr)) {
2076 $conf->{description
} = $descr;
2079 $conf = $res->{$section} = {};
2082 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2084 if (defined($descr)) {
2086 $conf->{description
} = $descr;
2089 $conf = $res->{snapshots
}->{$section} = {};
2093 if ($line =~ m/^\#(.*)\s*$/) {
2094 $descr = '' if !defined($descr);
2095 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2099 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2100 $descr = '' if !defined($descr);
2101 $descr .= PVE
::Tools
::decode_text
($2);
2102 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2103 $conf->{snapstate
} = $1;
2104 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2107 $conf->{$key} = $value;
2108 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2110 if ($section eq 'pending') {
2111 $conf->{delete} = $value; # we parse this later
2113 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2115 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2118 eval { $value = check_type
($key, $value); };
2120 warn "vm $vmid - unable to parse value of '$key' - $@";
2122 my $fmt = $confdesc->{$key}->{format
};
2123 if ($fmt && $fmt eq 'pve-qm-drive') {
2124 my $v = parse_drive
($key, $value);
2125 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2126 $v->{file
} = $volid;
2127 $value = print_drive
($vmid, $v);
2129 warn "vm $vmid - unable to parse value of '$key'\n";
2134 if ($key eq 'cdrom') {
2135 $conf->{ide2
} = $value;
2137 $conf->{$key} = $value;
2143 if (defined($descr)) {
2145 $conf->{description
} = $descr;
2147 delete $res->{snapstate
}; # just to be sure
2152 sub write_vm_config
{
2153 my ($filename, $conf) = @_;
2155 delete $conf->{snapstate
}; # just to be sure
2157 if ($conf->{cdrom
}) {
2158 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2159 $conf->{ide2
} = $conf->{cdrom
};
2160 delete $conf->{cdrom
};
2163 # we do not use 'smp' any longer
2164 if ($conf->{sockets
}) {
2165 delete $conf->{smp
};
2166 } elsif ($conf->{smp
}) {
2167 $conf->{sockets
} = $conf->{smp
};
2168 delete $conf->{cores
};
2169 delete $conf->{smp
};
2172 my $used_volids = {};
2174 my $cleanup_config = sub {
2175 my ($cref, $pending, $snapname) = @_;
2177 foreach my $key (keys %$cref) {
2178 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2179 $key eq 'snapstate' || $key eq 'pending';
2180 my $value = $cref->{$key};
2181 if ($key eq 'delete') {
2182 die "propertry 'delete' is only allowed in [PENDING]\n"
2184 # fixme: check syntax?
2187 eval { $value = check_type
($key, $value); };
2188 die "unable to parse value of '$key' - $@" if $@;
2190 $cref->{$key} = $value;
2192 if (!$snapname && is_valid_drivename
($key)) {
2193 my $drive = parse_drive
($key, $value);
2194 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2199 &$cleanup_config($conf);
2201 &$cleanup_config($conf->{pending
}, 1);
2203 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2204 die "internal error" if $snapname eq 'pending';
2205 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2208 # remove 'unusedX' settings if we re-add a volume
2209 foreach my $key (keys %$conf) {
2210 my $value = $conf->{$key};
2211 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2212 delete $conf->{$key};
2216 my $generate_raw_config = sub {
2217 my ($conf, $pending) = @_;
2221 # add description as comment to top of file
2222 if (defined(my $descr = $conf->{description
})) {
2224 foreach my $cl (split(/\n/, $descr)) {
2225 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2228 $raw .= "#\n" if $pending;
2232 foreach my $key (sort keys %$conf) {
2233 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2234 $raw .= "$key: $conf->{$key}\n";
2239 my $raw = &$generate_raw_config($conf);
2241 if (scalar(keys %{$conf->{pending
}})){
2242 $raw .= "\n[PENDING]\n";
2243 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2246 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2247 $raw .= "\n[$snapname]\n";
2248 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2258 # we use static defaults from our JSON schema configuration
2259 foreach my $key (keys %$confdesc) {
2260 if (defined(my $default = $confdesc->{$key}->{default})) {
2261 $res->{$key} = $default;
2265 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2266 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2272 my $vmlist = PVE
::Cluster
::get_vmlist
();
2274 return $res if !$vmlist || !$vmlist->{ids
};
2275 my $ids = $vmlist->{ids
};
2277 foreach my $vmid (keys %$ids) {
2278 my $d = $ids->{$vmid};
2279 next if !$d->{node
} || $d->{node
} ne $nodename;
2280 next if !$d->{type
} || $d->{type
} ne 'qemu';
2281 $res->{$vmid}->{exists} = 1;
2286 # test if VM uses local resources (to prevent migration)
2287 sub check_local_resources
{
2288 my ($conf, $noerr) = @_;
2292 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2293 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2295 foreach my $k (keys %$conf) {
2296 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2297 # sockets are safe: they will recreated be on the target side post-migrate
2298 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2299 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2302 die "VM uses local resources\n" if $loc_res && !$noerr;
2307 # check if used storages are available on all nodes (use by migrate)
2308 sub check_storage_availability
{
2309 my ($storecfg, $conf, $node) = @_;
2311 foreach_drive
($conf, sub {
2312 my ($ds, $drive) = @_;
2314 my $volid = $drive->{file
};
2317 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2320 # check if storage is available on both nodes
2321 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2322 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2326 # list nodes where all VM images are available (used by has_feature API)
2328 my ($conf, $storecfg) = @_;
2330 my $nodelist = PVE
::Cluster
::get_nodelist
();
2331 my $nodehash = { map { $_ => 1 } @$nodelist };
2332 my $nodename = PVE
::INotify
::nodename
();
2334 foreach_drive
($conf, sub {
2335 my ($ds, $drive) = @_;
2337 my $volid = $drive->{file
};
2340 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2342 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2343 if ($scfg->{disable
}) {
2345 } elsif (my $avail = $scfg->{nodes
}) {
2346 foreach my $node (keys %$nodehash) {
2347 delete $nodehash->{$node} if !$avail->{$node};
2349 } elsif (!$scfg->{shared
}) {
2350 foreach my $node (keys %$nodehash) {
2351 delete $nodehash->{$node} if $node ne $nodename
2361 my ($pidfile, $pid) = @_;
2363 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2367 return undef if !$line;
2368 my @param = split(/\0/, $line);
2370 my $cmd = $param[0];
2371 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2373 for (my $i = 0; $i < scalar (@param); $i++) {
2376 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2377 my $p = $param[$i+1];
2378 return 1 if $p && ($p eq $pidfile);
2387 my ($vmid, $nocheck, $node) = @_;
2389 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2391 die "unable to find configuration file for VM $vmid - no such machine\n"
2392 if !$nocheck && ! -f
$filename;
2394 my $pidfile = pidfile_name
($vmid);
2396 if (my $fd = IO
::File-
>new("<$pidfile")) {
2401 my $mtime = $st->mtime;
2402 if ($mtime > time()) {
2403 warn "file '$filename' modified in future\n";
2406 if ($line =~ m/^(\d+)$/) {
2408 if (check_cmdline
($pidfile, $pid)) {
2409 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2421 my $vzlist = config_list
();
2423 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2425 while (defined(my $de = $fd->read)) {
2426 next if $de !~ m/^(\d+)\.pid$/;
2428 next if !defined($vzlist->{$vmid});
2429 if (my $pid = check_running
($vmid)) {
2430 $vzlist->{$vmid}->{pid
} = $pid;
2438 my ($storecfg, $conf) = @_;
2440 my $bootdisk = $conf->{bootdisk
};
2441 return undef if !$bootdisk;
2442 return undef if !is_valid_drivename
($bootdisk);
2444 return undef if !$conf->{$bootdisk};
2446 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2447 return undef if !defined($drive);
2449 return undef if drive_is_cdrom
($drive);
2451 my $volid = $drive->{file
};
2452 return undef if !$volid;
2454 return $drive->{size
};
2457 my $last_proc_pid_stat;
2459 # get VM status information
2460 # This must be fast and should not block ($full == false)
2461 # We only query KVM using QMP if $full == true (this can be slow)
2463 my ($opt_vmid, $full) = @_;
2467 my $storecfg = PVE
::Storage
::config
();
2469 my $list = vzlist
();
2470 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2472 my $cpucount = $cpuinfo->{cpus
} || 1;
2474 foreach my $vmid (keys %$list) {
2475 next if $opt_vmid && ($vmid ne $opt_vmid);
2477 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2478 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2481 $d->{pid
} = $list->{$vmid}->{pid
};
2483 # fixme: better status?
2484 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2486 my $size = disksize
($storecfg, $conf);
2487 if (defined($size)) {
2488 $d->{disk
} = 0; # no info available
2489 $d->{maxdisk
} = $size;
2495 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2496 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2497 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2499 $d->{name
} = $conf->{name
} || "VM $vmid";
2500 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2502 if ($conf->{balloon
}) {
2503 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2504 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2515 $d->{diskwrite
} = 0;
2517 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2522 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2523 foreach my $dev (keys %$netdev) {
2524 next if $dev !~ m/^tap([1-9]\d*)i/;
2526 my $d = $res->{$vmid};
2529 $d->{netout
} += $netdev->{$dev}->{receive
};
2530 $d->{netin
} += $netdev->{$dev}->{transmit
};
2533 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2534 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2539 my $ctime = gettimeofday
;
2541 foreach my $vmid (keys %$list) {
2543 my $d = $res->{$vmid};
2544 my $pid = $d->{pid
};
2547 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2548 next if !$pstat; # not running
2550 my $used = $pstat->{utime} + $pstat->{stime
};
2552 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2554 if ($pstat->{vsize
}) {
2555 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2558 my $old = $last_proc_pid_stat->{$pid};
2560 $last_proc_pid_stat->{$pid} = {
2568 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2570 if ($dtime > 1000) {
2571 my $dutime = $used - $old->{used
};
2573 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2574 $last_proc_pid_stat->{$pid} = {
2580 $d->{cpu
} = $old->{cpu
};
2584 return $res if !$full;
2586 my $qmpclient = PVE
::QMPClient-
>new();
2588 my $ballooncb = sub {
2589 my ($vmid, $resp) = @_;
2591 my $info = $resp->{'return'};
2592 return if !$info->{max_mem
};
2594 my $d = $res->{$vmid};
2596 # use memory assigned to VM
2597 $d->{maxmem
} = $info->{max_mem
};
2598 $d->{balloon
} = $info->{actual
};
2600 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2601 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2602 $d->{freemem
} = $info->{free_mem
};
2605 $d->{ballooninfo
} = $info;
2608 my $blockstatscb = sub {
2609 my ($vmid, $resp) = @_;
2610 my $data = $resp->{'return'} || [];
2611 my $totalrdbytes = 0;
2612 my $totalwrbytes = 0;
2614 for my $blockstat (@$data) {
2615 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2616 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2618 $blockstat->{device
} =~ s/drive-//;
2619 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2621 $res->{$vmid}->{diskread
} = $totalrdbytes;
2622 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2625 my $statuscb = sub {
2626 my ($vmid, $resp) = @_;
2628 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2629 # this fails if ballon driver is not loaded, so this must be
2630 # the last commnand (following command are aborted if this fails).
2631 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2633 my $status = 'unknown';
2634 if (!defined($status = $resp->{'return'}->{status
})) {
2635 warn "unable to get VM status\n";
2639 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2642 foreach my $vmid (keys %$list) {
2643 next if $opt_vmid && ($vmid ne $opt_vmid);
2644 next if !$res->{$vmid}->{pid
}; # not running
2645 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2648 $qmpclient->queue_execute(undef, 1);
2650 foreach my $vmid (keys %$list) {
2651 next if $opt_vmid && ($vmid ne $opt_vmid);
2652 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2659 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2662 my $current_size = 1024;
2663 my $dimm_size = 512;
2664 return if $current_size == $memory;
2666 for (my $j = 0; $j < 8; $j++) {
2667 for (my $i = 0; $i < 32; $i++) {
2668 my $name = "dimm${dimm_id}";
2670 my $numanode = $i % $sockets;
2671 $current_size += $dimm_size;
2672 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2673 return $current_size if $current_size >= $memory;
2679 sub foreach_reverse_dimm
{
2680 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2683 my $current_size = 4177920;
2684 my $dimm_size = 65536;
2685 return if $current_size == $memory;
2687 for (my $j = 0; $j < 8; $j++) {
2688 for (my $i = 0; $i < 32; $i++) {
2689 my $name = "dimm${dimm_id}";
2691 my $numanode = $i % $sockets;
2692 $current_size -= $dimm_size;
2693 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2694 return $current_size if $current_size <= $memory;
2701 my ($conf, $func) = @_;
2703 foreach my $ds (valid_drive_names
()) {
2704 next if !defined($conf->{$ds});
2706 my $drive = parse_drive
($ds, $conf->{$ds});
2709 &$func($ds, $drive);
2714 my ($conf, $func) = @_;
2718 my $test_volid = sub {
2719 my ($volid, $is_cdrom) = @_;
2723 $volhash->{$volid} = $is_cdrom || 0;
2726 foreach_drive
($conf, sub {
2727 my ($ds, $drive) = @_;
2728 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2731 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2732 my $snap = $conf->{snapshots
}->{$snapname};
2733 &$test_volid($snap->{vmstate
}, 0);
2734 foreach_drive
($snap, sub {
2735 my ($ds, $drive) = @_;
2736 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2740 foreach my $volid (keys %$volhash) {
2741 &$func($volid, $volhash->{$volid});
2745 sub vga_conf_has_spice
{
2748 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2753 sub config_to_command
{
2754 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2757 my $globalFlags = [];
2758 my $machineFlags = [];
2764 my $kvmver = kvm_user_version
();
2765 my $vernum = 0; # unknown
2766 my $ostype = $conf->{ostype
};
2767 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2768 $vernum = $1*1000000+$2*1000;
2769 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2770 $vernum = $1*1000000+$2*1000+$3;
2773 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2775 my $have_ovz = -f
'/proc/vz/vestat';
2777 my $q35 = machine_type_is_q35
($conf);
2778 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2779 my $machine_type = $forcemachine || $conf->{machine
};
2780 my $use_old_bios_files = undef;
2781 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2783 my $cpuunits = defined($conf->{cpuunits
}) ?
2784 $conf->{cpuunits
} : $defaults->{cpuunits
};
2786 push @$cmd, '/usr/bin/systemd-run';
2787 push @$cmd, '--scope';
2788 push @$cmd, '--slice', "qemu";
2789 push @$cmd, '--unit', $vmid;
2790 # set KillMode=none, so that systemd don't kill those scopes
2791 # at shutdown (pve-manager service should stop the VMs instead)
2792 push @$cmd, '-p', "KillMode=none";
2793 push @$cmd, '-p', "CPUShares=$cpuunits";
2794 if ($conf->{cpulimit
}) {
2795 my $cpulimit = int($conf->{cpulimit
} * 100);
2796 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2799 push @$cmd, '/usr/bin/kvm';
2801 push @$cmd, '-id', $vmid;
2805 my $qmpsocket = qmp_socket
($vmid);
2806 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2807 push @$cmd, '-mon', "chardev=qmp,mode=control";
2810 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2812 push @$cmd, '-daemonize';
2814 if ($conf->{smbios1
}) {
2815 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2818 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2819 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2820 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2821 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2822 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2823 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2824 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2828 # the q35 chipset support native usb2, so we enable usb controller
2829 # by default for this machine type
2830 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2832 $pciaddr = print_pci_addr
("piix3", $bridges);
2833 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2836 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2837 next if !$conf->{"usb$i"};
2838 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2839 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2842 # include usb device config
2843 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2846 # add usb3 controller if needed
2849 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2850 next if !$conf->{"usb$i"};
2851 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2852 next if !$d || !$d->{usb3
};
2856 $pciaddr = print_pci_addr
("xhci", $bridges);
2857 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2859 my $vga = $conf->{vga
};
2861 my $qxlnum = vga_conf_has_spice
($vga);
2862 $vga = 'qxl' if $qxlnum;
2865 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2866 $conf->{ostype
} eq 'win7' ||
2867 $conf->{ostype
} eq 'w2k8')) {
2874 # enable absolute mouse coordinates (needed by vnc)
2876 if (defined($conf->{tablet
})) {
2877 $tablet = $conf->{tablet
};
2879 $tablet = $defaults->{tablet
};
2880 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2881 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2884 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2888 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2889 my $d = parse_hostpci
($conf->{"hostpci$i"});
2892 my $pcie = $d->{pcie
};
2894 die "q35 machine model is not enabled" if !$q35;
2895 $pciaddr = print_pcie_addr
("hostpci$i");
2897 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2900 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2902 if ($d->{'x-vga'}) {
2903 $xvga = ',x-vga=on';
2906 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2907 push @$cpuFlags , 'hv_vendor_id=proxmox';
2909 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2913 my $pcidevices = $d->{pciid
};
2914 my $multifunction = 1 if @$pcidevices > 1;
2917 foreach my $pcidevice (@$pcidevices) {
2919 my $id = "hostpci$i";
2920 $id .= ".$j" if $multifunction;
2921 my $addr = $pciaddr;
2922 $addr .= ".$j" if $multifunction;
2923 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2926 $devicestr .= "$rombar$xvga";
2927 $devicestr .= ",multifunction=on" if $multifunction;
2930 push @$devices, '-device', $devicestr;
2936 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2937 next if !$conf->{"usb$i"};
2938 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2941 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2943 if (defined($d->{usb3
}) && $d->{usb3
}) {
2944 $usbbus = ',bus=xhci.0';
2947 if (defined($d->{host
})) {
2948 $d = parse_usb_device
($d->{host
});
2949 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2950 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2951 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2952 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2953 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2954 # usb redir support for spice, currently no usb3
2955 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2956 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2962 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2963 if (my $path = $conf->{"serial$i"}) {
2964 if ($path eq 'socket') {
2965 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2966 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2967 push @$devices, '-device', "isa-serial,chardev=serial$i";
2969 die "no such serial device\n" if ! -c
$path;
2970 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2971 push @$devices, '-device', "isa-serial,chardev=serial$i";
2977 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2978 if (my $path = $conf->{"parallel$i"}) {
2979 die "no such parallel device\n" if ! -c
$path;
2980 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2981 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2982 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2986 my $vmname = $conf->{name
} || "vm$vmid";
2988 push @$cmd, '-name', $vmname;
2991 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2992 $sockets = $conf->{sockets
} if $conf->{sockets
};
2994 my $cores = $conf->{cores
} || 1;
2996 my $maxcpus = $sockets * $cores;
2998 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3000 my $allowed_vcpus = $cpuinfo->{cpus
};
3002 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3003 if ($allowed_vcpus < $maxcpus);
3005 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3007 push @$cmd, '-nodefaults';
3009 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3011 my $bootindex_hash = {};
3013 foreach my $o (split(//, $bootorder)) {
3014 $bootindex_hash->{$o} = $i*100;
3018 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
3020 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3022 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3024 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3026 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3027 my $socket = vnc_socket
($vmid);
3028 push @$cmd, '-vnc', "unix:$socket,x509,password";
3030 push @$cmd, '-nographic';
3034 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3036 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3037 my $useLocaltime = $conf->{localtime};
3040 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3042 if ($ostype =~ m/^w/) { # windows
3043 $useLocaltime = 1 if !defined($conf->{localtime});
3045 # use time drift fix when acpi is enabled
3046 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3047 $tdf = 1 if !defined($conf->{tdf
});
3051 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3052 $ostype eq 'wvista') {
3053 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3054 push @$cmd, '-no-hpet';
3055 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3056 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3057 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3058 push @$cpuFlags , 'hv_time' if !$nokvm;
3061 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3065 if ($ostype eq 'win7' || $ostype eq 'win8') {
3066 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3070 push @$rtcFlags, 'driftfix=slew' if $tdf;
3073 push @$machineFlags, 'accel=tcg';
3075 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3078 if ($machine_type) {
3079 push @$machineFlags, "type=${machine_type}";
3082 if ($conf->{startdate
}) {
3083 push @$rtcFlags, "base=$conf->{startdate}";
3084 } elsif ($useLocaltime) {
3085 push @$rtcFlags, 'base=localtime';
3088 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3089 if (my $cputype = $conf->{cpu
}) {
3090 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3091 or die "Cannot parse cpu description: $cputype\n";
3092 $cpu = $cpuconf->{cputype
};
3093 $kvm_off = 1 if $cpuconf->{hidden
};
3096 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3098 push @$cpuFlags , '-x2apic'
3099 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3101 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3103 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3105 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3107 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3108 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3111 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3113 push @$cpuFlags, 'kvm=off' if $kvm_off;
3115 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3116 die "internal error"; # should not happen
3118 push @$cpuFlags, "vendor=${cpu_vendor}"
3119 if $cpu_vendor ne 'default';
3121 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3123 push @$cmd, '-cpu', $cpu;
3125 my $memory = $conf->{memory
} || $defaults->{memory
};
3126 my $static_memory = 0;
3127 my $dimm_memory = 0;
3129 if ($hotplug_features->{memory
}) {
3130 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3131 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3132 $static_memory = $STATICMEM;
3133 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3134 $dimm_memory = $memory - $static_memory;
3135 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3139 $static_memory = $memory;
3140 push @$cmd, '-m', $static_memory;
3143 if ($conf->{numa
}) {
3145 my $numa_totalmemory = undef;
3146 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3147 next if !$conf->{"numa$i"};
3148 my $numa = parse_numa
($conf->{"numa$i"});
3151 die "missing numa node$i memory value\n" if !$numa->{memory
};
3152 my $numa_memory = $numa->{memory
};
3153 $numa_totalmemory += $numa_memory;
3154 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3157 my $cpulists = $numa->{cpus
};
3158 die "missing numa node$i cpus\n" if !defined($cpulists);
3159 my $cpus = join(',', map {
3160 my ($start, $end) = @$_;
3161 defined($end) ?
"$start-$end" : $start
3165 my $hostnodelists = $numa->{hostnodes
};
3166 if (defined($hostnodelists)) {
3168 foreach my $hostnoderange (@$hostnodelists) {
3169 my ($start, $end) = @$hostnoderange;
3170 $hostnodes .= ',' if $hostnodes;
3171 $hostnodes .= $start;
3172 $hostnodes .= "-$end" if defined($end);
3174 for (my $i = $start; $i <= $end; ++$i ) {
3175 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3180 my $policy = $numa->{policy
};
3181 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3182 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3185 push @$cmd, '-object', $numa_object;
3186 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3189 die "total memory for NUMA nodes must be equal to vm static memory\n"
3190 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3192 #if no custom tology, we split memory and cores across numa nodes
3193 if(!$numa_totalmemory) {
3195 my $numa_memory = ($static_memory / $sockets) . "M";
3197 for (my $i = 0; $i < $sockets; $i++) {
3199 my $cpustart = ($cores * $i);
3200 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3201 my $cpus = $cpustart;
3202 $cpus .= "-$cpuend" if $cpuend;
3204 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3205 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3210 if ($hotplug_features->{memory
}) {
3211 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3212 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3213 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3214 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3216 #if dimm_memory is not aligned to dimm map
3217 if($current_size > $memory) {
3218 $conf->{memory
} = $current_size;
3219 PVE
::QemuConfig-
>write_config($vmid, $conf);
3224 push @$cmd, '-S' if $conf->{freeze
};
3226 # set keyboard layout
3227 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3228 push @$cmd, '-k', $kb if $kb;
3231 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3232 #push @$cmd, '-soundhw', 'es1370';
3233 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3235 if($conf->{agent
}) {
3236 my $qgasocket = qmp_socket
($vmid, 1);
3237 my $pciaddr = print_pci_addr
("qga0", $bridges);
3238 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3239 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3240 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3247 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3248 for(my $i = 1; $i < $qxlnum; $i++){
3249 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3250 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3253 # assume other OS works like Linux
3254 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3255 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3259 my $pciaddr = print_pci_addr
("spice", $bridges);
3261 my $nodename = PVE
::INotify
::nodename
();
3262 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3263 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3265 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3267 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3268 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3269 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3272 # enable balloon by default, unless explicitly disabled
3273 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3274 $pciaddr = print_pci_addr
("balloon0", $bridges);
3275 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3278 if ($conf->{watchdog
}) {
3279 my $wdopts = parse_watchdog
($conf->{watchdog
});
3280 $pciaddr = print_pci_addr
("watchdog", $bridges);
3281 my $watchdog = $wdopts->{model
} || 'i6300esb';
3282 push @$devices, '-device', "$watchdog$pciaddr";
3283 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3287 my $scsicontroller = {};
3288 my $ahcicontroller = {};
3289 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3291 # Add iscsi initiator name if available
3292 if (my $initiator = get_initiator_name
()) {
3293 push @$devices, '-iscsi', "initiator-name=$initiator";
3296 foreach_drive
($conf, sub {
3297 my ($ds, $drive) = @_;
3299 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3300 push @$vollist, $drive->{file
};
3303 $use_virtio = 1 if $ds =~ m/^virtio/;
3305 if (drive_is_cdrom
($drive)) {
3306 if ($bootindex_hash->{d
}) {
3307 $drive->{bootindex
} = $bootindex_hash->{d
};
3308 $bootindex_hash->{d
} += 1;
3311 if ($bootindex_hash->{c
}) {
3312 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3313 $bootindex_hash->{c
} += 1;
3317 if($drive->{interface
} eq 'virtio'){
3318 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3321 if ($drive->{interface
} eq 'scsi') {
3323 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3325 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3326 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3329 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3330 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3331 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3335 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3336 $queues = ",num_queues=$drive->{queues}";
3339 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3340 $scsicontroller->{$controller}=1;
3343 if ($drive->{interface
} eq 'sata') {
3344 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3345 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3346 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3347 $ahcicontroller->{$controller}=1;
3350 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3351 push @$devices, '-drive',$drive_cmd;
3352 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3355 for (my $i = 0; $i < $MAX_NETS; $i++) {
3356 next if !$conf->{"net$i"};
3357 my $d = parse_net
($conf->{"net$i"});
3360 $use_virtio = 1 if $d->{model
} eq 'virtio';
3362 if ($bootindex_hash->{n
}) {
3363 $d->{bootindex
} = $bootindex_hash->{n
};
3364 $bootindex_hash->{n
} += 1;
3367 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3368 push @$devices, '-netdev', $netdevfull;
3370 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3371 push @$devices, '-device', $netdevicefull;
3376 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3381 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3383 while (my ($k, $v) = each %$bridges) {
3384 $pciaddr = print_pci_addr
("pci.$k");
3385 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3390 if ($conf->{args
}) {
3391 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3395 push @$cmd, @$devices;
3396 push @$cmd, '-rtc', join(',', @$rtcFlags)
3397 if scalar(@$rtcFlags);
3398 push @$cmd, '-machine', join(',', @$machineFlags)
3399 if scalar(@$machineFlags);
3400 push @$cmd, '-global', join(',', @$globalFlags)
3401 if scalar(@$globalFlags);
3403 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3408 return "${var_run_tmpdir}/$vmid.vnc";
3414 my $res = vm_mon_cmd
($vmid, 'query-spice');
3416 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3420 my ($vmid, $qga) = @_;
3421 my $sockettype = $qga ?
'qga' : 'qmp';
3422 return "${var_run_tmpdir}/$vmid.$sockettype";
3427 return "${var_run_tmpdir}/$vmid.pid";
3430 sub vm_devices_list
{
3433 my $res = vm_mon_cmd
($vmid, 'query-pci');
3435 foreach my $pcibus (@$res) {
3436 foreach my $device (@{$pcibus->{devices
}}) {
3437 next if !$device->{'qdev_id'};
3438 if ($device->{'pci_bridge'}) {
3439 $devices->{$device->{'qdev_id'}} = 1;
3440 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3441 next if !$bridge_device->{'qdev_id'};
3442 $devices->{$bridge_device->{'qdev_id'}} = 1;
3443 $devices->{$device->{'qdev_id'}}++;
3446 $devices->{$device->{'qdev_id'}} = 1;
3451 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3452 foreach my $block (@$resblock) {
3453 if($block->{device
} =~ m/^drive-(\S+)/){
3458 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3459 foreach my $mice (@$resmice) {
3460 if ($mice->{name
} eq 'QEMU HID Tablet') {
3461 $devices->{tablet
} = 1;
3470 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3472 my $q35 = machine_type_is_q35
($conf);
3474 my $devices_list = vm_devices_list
($vmid);
3475 return 1 if defined($devices_list->{$deviceid});
3477 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3479 if ($deviceid eq 'tablet') {
3481 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3483 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3485 qemu_iothread_add
($vmid, $deviceid, $device);
3487 qemu_driveadd
($storecfg, $vmid, $device);
3488 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3490 qemu_deviceadd
($vmid, $devicefull);
3491 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3493 eval { qemu_drivedel
($vmid, $deviceid); };
3498 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3501 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3502 my $pciaddr = print_pci_addr
($deviceid);
3503 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3505 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3507 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3508 qemu_iothread_add
($vmid, $deviceid, $device);
3509 $devicefull .= ",iothread=iothread-$deviceid";
3512 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3513 $devicefull .= ",num_queues=$device->{queues}";
3516 qemu_deviceadd
($vmid, $devicefull);
3517 qemu_deviceaddverify
($vmid, $deviceid);
3519 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3521 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3522 qemu_driveadd
($storecfg, $vmid, $device);
3524 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3525 eval { qemu_deviceadd
($vmid, $devicefull); };
3527 eval { qemu_drivedel
($vmid, $deviceid); };
3532 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3534 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3536 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3537 my $use_old_bios_files = undef;
3538 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3540 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3541 qemu_deviceadd
($vmid, $netdevicefull);
3542 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3544 eval { qemu_netdevdel
($vmid, $deviceid); };
3549 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3552 my $pciaddr = print_pci_addr
($deviceid);
3553 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3555 qemu_deviceadd
($vmid, $devicefull);
3556 qemu_deviceaddverify
($vmid, $deviceid);
3559 die "can't hotplug device '$deviceid'\n";
3565 # fixme: this should raise exceptions on error!
3566 sub vm_deviceunplug
{
3567 my ($vmid, $conf, $deviceid) = @_;
3569 my $devices_list = vm_devices_list
($vmid);
3570 return 1 if !defined($devices_list->{$deviceid});
3572 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3574 if ($deviceid eq 'tablet') {
3576 qemu_devicedel
($vmid, $deviceid);
3578 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3580 qemu_devicedel
($vmid, $deviceid);
3581 qemu_devicedelverify
($vmid, $deviceid);
3582 qemu_drivedel
($vmid, $deviceid);
3583 qemu_iothread_del
($conf, $vmid, $deviceid);
3585 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3587 qemu_devicedel
($vmid, $deviceid);
3588 qemu_devicedelverify
($vmid, $deviceid);
3589 qemu_iothread_del
($conf, $vmid, $deviceid);
3591 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3593 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3594 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3595 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3597 qemu_devicedel
($vmid, $deviceid);
3598 qemu_drivedel
($vmid, $deviceid);
3599 qemu_deletescsihw
($conf, $vmid, $deviceid);
3601 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3603 qemu_devicedel
($vmid, $deviceid);
3604 qemu_devicedelverify
($vmid, $deviceid);
3605 qemu_netdevdel
($vmid, $deviceid);
3608 die "can't unplug device '$deviceid'\n";
3614 sub qemu_deviceadd
{
3615 my ($vmid, $devicefull) = @_;
3617 $devicefull = "driver=".$devicefull;
3618 my %options = split(/[=,]/, $devicefull);
3620 vm_mon_cmd
($vmid, "device_add" , %options);
3623 sub qemu_devicedel
{
3624 my ($vmid, $deviceid) = @_;
3626 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3629 sub qemu_iothread_add
{
3630 my($vmid, $deviceid, $device) = @_;
3632 if ($device->{iothread
}) {
3633 my $iothreads = vm_iothreads_list
($vmid);
3634 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3638 sub qemu_iothread_del
{
3639 my($conf, $vmid, $deviceid) = @_;
3641 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3642 if ($device->{iothread
}) {
3643 my $iothreads = vm_iothreads_list
($vmid);
3644 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3648 sub qemu_objectadd
{
3649 my($vmid, $objectid, $qomtype) = @_;
3651 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3656 sub qemu_objectdel
{
3657 my($vmid, $objectid) = @_;
3659 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3665 my ($storecfg, $vmid, $device) = @_;
3667 my $drive = print_drive_full
($storecfg, $vmid, $device);
3668 $drive =~ s/\\/\\\\/g;
3669 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3671 # If the command succeeds qemu prints: "OK
"
3672 return 1 if $ret =~ m/OK/s;
3674 die "adding drive failed
: $ret\n";
3678 my($vmid, $deviceid) = @_;
3680 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3683 return 1 if $ret eq "";
3685 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3686 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3688 die "deleting drive
$deviceid failed
: $ret\n";
3691 sub qemu_deviceaddverify {
3692 my ($vmid, $deviceid) = @_;
3694 for (my $i = 0; $i <= 5; $i++) {
3695 my $devices_list = vm_devices_list($vmid);
3696 return 1 if defined($devices_list->{$deviceid});
3700 die "error on hotplug device
'$deviceid'\n";
3704 sub qemu_devicedelverify {
3705 my ($vmid, $deviceid) = @_;
3707 # need to verify that the device is correctly removed as device_del
3708 # is async and empty return is not reliable
3710 for (my $i = 0; $i <= 5; $i++) {
3711 my $devices_list = vm_devices_list($vmid);
3712 return 1 if !defined($devices_list->{$deviceid});
3716 die "error on hot-unplugging device
'$deviceid'\n";
3719 sub qemu_findorcreatescsihw {
3720 my ($storecfg, $conf, $vmid, $device) = @_;
3722 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3724 my $scsihwid="$controller_prefix$controller";
3725 my $devices_list = vm_devices_list($vmid);
3727 if(!defined($devices_list->{$scsihwid})) {
3728 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3734 sub qemu_deletescsihw {
3735 my ($conf, $vmid, $opt) = @_;
3737 my $device = parse_drive($opt, $conf->{$opt});
3739 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3740 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3744 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3746 my $devices_list = vm_devices_list($vmid);
3747 foreach my $opt (keys %{$devices_list}) {
3748 if (PVE::QemuServer::is_valid_drivename($opt)) {
3749 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3750 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3756 my $scsihwid="scsihw
$controller";
3758 vm_deviceunplug($vmid, $conf, $scsihwid);
3763 sub qemu_add_pci_bridge {
3764 my ($storecfg, $conf, $vmid, $device) = @_;
3770 print_pci_addr($device, $bridges);
3772 while (my ($k, $v) = each %$bridges) {
3775 return 1 if !defined($bridgeid) || $bridgeid < 1;
3777 my $bridge = "pci
.$bridgeid";
3778 my $devices_list = vm_devices_list($vmid);
3780 if (!defined($devices_list->{$bridge})) {
3781 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3787 sub qemu_set_link_status {
3788 my ($vmid, $device, $up) = @_;
3790 vm_mon_cmd($vmid, "set_link
", name => $device,
3791 up => $up ? JSON::true : JSON::false);
3794 sub qemu_netdevadd {
3795 my ($vmid, $conf, $device, $deviceid) = @_;
3797 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3798 my %options = split(/[=,]/, $netdev);
3800 vm_mon_cmd($vmid, "netdev_add
", %options);
3804 sub qemu_netdevdel {
3805 my ($vmid, $deviceid) = @_;
3807 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3810 sub qemu_cpu_hotplug {
3811 my ($vmid, $conf, $vcpus) = @_;
3814 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3815 $sockets = $conf->{sockets} if $conf->{sockets};
3816 my $cores = $conf->{cores} || 1;
3817 my $maxcpus = $sockets * $cores;
3819 $vcpus = $maxcpus if !$vcpus;
3821 die "you can
't add more vcpus than maxcpus\n"
3822 if $vcpus > $maxcpus;
3824 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3825 die "online cpu unplug is not yet possible\n"
3826 if $vcpus < $currentvcpus;
3828 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3829 die "vcpus in running vm is different than configuration\n"
3830 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3832 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3833 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3837 sub qemu_memory_hotplug {
3838 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3840 return $value if !check_running($vmid);
3842 my $memory = $conf->{memory} || $defaults->{memory};
3843 $value = $defaults->{memory} if !$value;
3844 return $value if $value == $memory;
3846 my $static_memory = $STATICMEM;
3847 my $dimm_memory = $memory - $static_memory;
3849 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3850 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3854 $sockets = $conf->{sockets} if $conf->{sockets};
3856 if($value > $memory) {
3858 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3859 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3861 return if $current_size <= $conf->{memory};
3863 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3865 eval { qemu_objectdel($vmid, "mem-
$name"); };
3869 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3871 eval { qemu_objectdel($vmid, "mem-
$name"); };
3874 #update conf after each succesful module hotplug
3875 $conf->{memory} = $current_size;
3876 PVE::QemuConfig->write_config($vmid, $conf);
3881 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3882 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3884 return if $current_size >= $conf->{memory};
3885 print "try to unplug memory dimm
$name\n";
3889 eval { qemu_devicedel($vmid, $name) };
3891 my $dimm_list = qemu_dimm_list($vmid);
3892 last if !$dimm_list->{$name};
3893 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3897 #update conf after each succesful module unplug
3898 $conf->{memory} = $current_size;
3900 eval { qemu_objectdel($vmid, "mem-
$name"); };
3901 PVE::QemuConfig->write_config($vmid, $conf);
3906 sub qemu_dimm_list {
3909 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3912 foreach my $dimm (@$dimmarray) {
3914 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3915 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3916 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3917 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3918 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3923 sub qemu_block_set_io_throttle {
3924 my ($vmid, $deviceid,
3925 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3926 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3928 return if !check_running($vmid) ;
3930 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3932 bps_rd => int($bps_rd),
3933 bps_wr => int($bps_wr),
3935 iops_rd => int($iops_rd),
3936 iops_wr => int($iops_wr),
3937 bps_max => int($bps_max),
3938 bps_rd_max => int($bps_rd_max),
3939 bps_wr_max => int($bps_wr_max),
3940 iops_max => int($iops_max),
3941 iops_rd_max => int($iops_rd_max),
3942 iops_wr_max => int($iops_wr_max)
3947 # old code, only used to shutdown old VM after update
3949 my ($fh, $timeout) = @_;
3951 my $sel = new IO::Select;
3958 while (scalar (@ready = $sel->can_read($timeout))) {
3960 if ($count = $fh->sysread($buf, 8192)) {
3961 if ($buf =~ /^(.*)\(qemu\) $/s) {
3968 if (!defined($count)) {
3975 die "monitor
read timeout
\n" if !scalar(@ready);
3980 # old code, only used to shutdown old VM after update
3981 sub vm_monitor_command {
3982 my ($vmid, $cmdstr, $nocheck) = @_;
3987 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3989 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3991 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3992 die "unable to
connect to VM
$vmid socket - $!\n";
3996 # hack: migrate sometime blocks the monitor (when migrate_downtime
3998 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3999 $timeout = 60*60; # 1 hour
4003 my $data = __read_avail($sock, $timeout);
4005 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4006 die "got unexpected qemu monitor banner
\n";
4009 my $sel = new IO::Select;
4012 if (!scalar(my @ready = $sel->can_write($timeout))) {
4013 die "monitor
write error
- timeout
";
4016 my $fullcmd = "$cmdstr\r";
4018 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
4021 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4022 die "monitor
write error
- $!";
4025 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4029 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4030 $timeout = 60*60; # 1 hour
4031 } elsif ($cmdstr =~ m/^(eject|change)/) {
4032 $timeout = 60; # note: cdrom mount command is slow
4034 if ($res = __read_avail($sock, $timeout)) {
4036 my @lines = split("\r?
\n", $res);
4038 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4040 $res = join("\n", @lines);
4048 syslog("err
", "VM
$vmid monitor command failed
- $err");
4055 sub qemu_block_resize {
4056 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4058 my $running = check_running($vmid);
4060 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4062 return if !$running;
4064 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4068 sub qemu_volume_snapshot {
4069 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4071 my $running = check_running($vmid);
4073 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4074 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4076 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4080 sub qemu_volume_snapshot_delete {
4081 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4083 my $running = check_running($vmid);
4085 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4087 return if !$running;
4089 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4092 sub set_migration_caps {
4098 "auto-converge
" => 1,
4100 "x-rdma-pin-all
" => 0,
4105 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4107 for my $supported_capability (@$supported_capabilities) {
4109 capability => $supported_capability->{capability},
4110 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4114 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4117 my $fast_plug_option = {
4126 # hotplug changes in [PENDING]
4127 # $selection hash can be used to only apply specified options, for
4128 # example: { cores => 1 } (only apply changed 'cores')
4129 # $errors ref is used to return error messages
4130 sub vmconfig_hotplug_pending {
4131 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4133 my $defaults = load_defaults();
4135 # commit values which do not have any impact on running VM first
4136 # Note: those option cannot raise errors, we we do not care about
4137 # $selection and always apply them.
4139 my $add_error = sub {
4140 my ($opt, $msg) = @_;
4141 $errors->{$opt} = "hotplug problem
- $msg";
4145 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4146 if ($fast_plug_option->{$opt}) {
4147 $conf->{$opt} = $conf->{pending}->{$opt};
4148 delete $conf->{pending}->{$opt};
4154 PVE::QemuConfig->write_config($vmid, $conf);
4155 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4158 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4160 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4161 while (my ($opt, $force) = each %$pending_delete_hash) {
4162 next if $selection && !$selection->{$opt};
4164 if ($opt eq 'hotplug') {
4165 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4166 } elsif ($opt eq 'tablet') {
4167 die "skip
\n" if !$hotplug_features->{usb};
4168 if ($defaults->{tablet}) {
4169 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4171 vm_deviceunplug($vmid, $conf, $opt);
4173 } elsif ($opt eq 'vcpus') {
4174 die "skip
\n" if !$hotplug_features->{cpu};
4175 qemu_cpu_hotplug($vmid, $conf, undef);
4176 } elsif ($opt eq 'balloon') {
4177 # enable balloon device is not hotpluggable
4178 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4179 } elsif ($fast_plug_option->{$opt}) {
4181 } elsif ($opt =~ m/^net(\d+)$/) {
4182 die "skip
\n" if !$hotplug_features->{network};
4183 vm_deviceunplug($vmid, $conf, $opt);
4184 } elsif (is_valid_drivename($opt)) {
4185 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4186 vm_deviceunplug($vmid, $conf, $opt);
4187 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4188 } elsif ($opt =~ m/^memory$/) {
4189 die "skip
\n" if !$hotplug_features->{memory};
4190 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4191 } elsif ($opt eq 'cpuunits') {
4192 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4193 } elsif ($opt eq 'cpulimit') {
4194 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4200 &$add_error($opt, $err) if $err ne "skip
\n";
4202 # save new config if hotplug was successful
4203 delete $conf->{$opt};
4204 vmconfig_undelete_pending_option($conf, $opt);
4205 PVE::QemuConfig->write_config($vmid, $conf);
4206 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4210 foreach my $opt (keys %{$conf->{pending}}) {
4211 next if $selection && !$selection->{$opt};
4212 my $value = $conf->{pending}->{$opt};
4214 if ($opt eq 'hotplug') {
4215 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4216 } elsif ($opt eq 'tablet') {
4217 die "skip
\n" if !$hotplug_features->{usb};
4219 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4220 } elsif ($value == 0) {
4221 vm_deviceunplug($vmid, $conf, $opt);
4223 } elsif ($opt eq 'vcpus') {
4224 die "skip
\n" if !$hotplug_features->{cpu};
4225 qemu_cpu_hotplug($vmid, $conf, $value);
4226 } elsif ($opt eq 'balloon') {
4227 # enable/disable balloning device is not hotpluggable
4228 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4229 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4230 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4232 # allow manual ballooning if shares is set to zero
4233 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4234 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4235 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4237 } elsif ($opt =~ m/^net(\d+)$/) {
4238 # some changes can be done without hotplug
4239 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4240 $vmid, $opt, $value);
4241 } elsif (is_valid_drivename($opt)) {
4242 # some changes can be done without hotplug
4243 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4244 $vmid, $opt, $value, 1);
4245 } elsif ($opt =~ m/^memory$/) { #dimms
4246 die "skip
\n" if !$hotplug_features->{memory};
4247 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4248 } elsif ($opt eq 'cpuunits') {
4249 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4250 } elsif ($opt eq 'cpulimit') {
4251 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4252 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4254 die "skip
\n"; # skip non-hot-pluggable options
4258 &$add_error($opt, $err) if $err ne "skip
\n";
4260 # save new config if hotplug was successful
4261 $conf->{$opt} = $value;
4262 delete $conf->{pending}->{$opt};
4263 PVE::QemuConfig->write_config($vmid, $conf);
4264 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4269 sub try_deallocate_drive {
4270 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4272 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4273 my $volid = $drive->{file};
4274 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4275 my $sid = PVE::Storage::parse_volume_id($volid);
4276 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4278 # check if the disk is really unused
4279 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4280 if is_volume_in_use($storecfg, $conf, $key, $volid);
4281 PVE::Storage::vdisk_free($storecfg, $volid);
4284 # If vm is not owner of this disk remove from config
4292 sub vmconfig_delete_or_detach_drive {
4293 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4295 my $drive = parse_drive($opt, $conf->{$opt});
4297 my $rpcenv = PVE::RPCEnvironment::get();
4298 my $authuser = $rpcenv->get_user();
4301 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4302 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4304 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4308 sub vmconfig_apply_pending {
4309 my ($vmid, $conf, $storecfg) = @_;
4313 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4314 while (my ($opt, $force) = each %$pending_delete_hash) {
4315 die "internal error
" if $opt =~ m/^unused/;
4316 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4317 if (!defined($conf->{$opt})) {
4318 vmconfig_undelete_pending_option($conf, $opt);
4319 PVE::QemuConfig->write_config($vmid, $conf);
4320 } elsif (is_valid_drivename($opt)) {
4321 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4322 vmconfig_undelete_pending_option($conf, $opt);
4323 delete $conf->{$opt};
4324 PVE::QemuConfig->write_config($vmid, $conf);
4326 vmconfig_undelete_pending_option($conf, $opt);
4327 delete $conf->{$opt};
4328 PVE::QemuConfig->write_config($vmid, $conf);
4332 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4334 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4335 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4337 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4338 # skip if nothing changed
4339 } elsif (is_valid_drivename($opt)) {
4340 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4341 if defined($conf->{$opt});
4342 $conf->{$opt} = $conf->{pending}->{$opt};
4344 $conf->{$opt} = $conf->{pending}->{$opt};
4347 delete $conf->{pending}->{$opt};
4348 PVE::QemuConfig->write_config($vmid, $conf);
4352 my $safe_num_ne = sub {
4355 return 0 if !defined($a) && !defined($b);
4356 return 1 if !defined($a);
4357 return 1 if !defined($b);
4362 my $safe_string_ne = sub {
4365 return 0 if !defined($a) && !defined($b);
4366 return 1 if !defined($a);
4367 return 1 if !defined($b);
4372 sub vmconfig_update_net {
4373 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4375 my $newnet = parse_net($value);
4377 if ($conf->{$opt}) {
4378 my $oldnet = parse_net($conf->{$opt});
4380 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4381 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4382 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4383 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4385 # for non online change, we try to hot-unplug
4386 die "skip
\n" if !$hotplug;
4387 vm_deviceunplug($vmid, $conf, $opt);
4390 die "internal error
" if $opt !~ m/net(\d+)/;
4391 my $iface = "tap
${vmid
}i
$1";
4393 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4394 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4395 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4396 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4397 PVE::Network::tap_unplug($iface);
4398 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4399 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4400 # Rate can be applied on its own but any change above needs to
4401 # include the rate in tap_plug since OVS resets everything.
4402 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4405 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4406 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4414 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4420 sub vmconfig_update_disk {
4421 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4423 # fixme: do we need force?
4425 my $drive = parse_drive($opt, $value);
4427 if ($conf->{$opt}) {
4429 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4431 my $media = $drive->{media} || 'disk';
4432 my $oldmedia = $old_drive->{media} || 'disk';
4433 die "unable to change media type
\n" if $media ne $oldmedia;
4435 if (!drive_is_cdrom($old_drive)) {
4437 if ($drive->{file} ne $old_drive->{file}) {
4439 die "skip
\n" if !$hotplug;
4441 # unplug and register as unused
4442 vm_deviceunplug($vmid, $conf, $opt);
4443 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4446 # update existing disk
4448 # skip non hotpluggable value
4449 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4450 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4451 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4452 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4457 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4458 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4459 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4460 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4461 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4462 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4463 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4464 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4465 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4466 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4467 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4468 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4470 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4471 ($drive->{mbps} || 0)*1024*1024,
4472 ($drive->{mbps_rd} || 0)*1024*1024,
4473 ($drive->{mbps_wr} || 0)*1024*1024,
4474 $drive->{iops} || 0,
4475 $drive->{iops_rd} || 0,
4476 $drive->{iops_wr} || 0,
4477 ($drive->{mbps_max} || 0)*1024*1024,
4478 ($drive->{mbps_rd_max} || 0)*1024*1024,
4479 ($drive->{mbps_wr_max} || 0)*1024*1024,
4480 $drive->{iops_max} || 0,
4481 $drive->{iops_rd_max} || 0,
4482 $drive->{iops_wr_max} || 0);
4491 if ($drive->{file} eq 'none') {
4492 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4494 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4495 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4496 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4504 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4506 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4507 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4511 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4512 $forcemachine, $spice_ticket) = @_;
4514 PVE::QemuConfig->lock_config($vmid, sub {
4515 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4517 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4519 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4521 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4523 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4524 vmconfig_apply_pending($vmid, $conf, $storecfg);
4525 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4528 my $defaults = load_defaults();
4530 # set environment variable useful inside network script
4531 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4533 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4535 my $migrate_port = 0;
4538 if ($statefile eq 'tcp') {
4539 my $localip = "localhost
";
4540 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4541 my $nodename = PVE::INotify::nodename();
4542 if ($datacenterconf->{migration_unsecure}) {
4543 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4544 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4546 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4547 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4548 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4549 push @$cmd, '-incoming', $migrate_uri;
4552 push @$cmd, '-loadstate', $statefile;
4559 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4560 my $d = parse_hostpci($conf->{"hostpci
$i"});
4562 my $pcidevices = $d->{pciid};
4563 foreach my $pcidevice (@$pcidevices) {
4564 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4566 my $info = pci_device_info("0000:$pciid");
4567 die "IOMMU
not present
\n" if !check_iommu_support();
4568 die "no pci device info
for device
'$pciid'\n" if !$info;
4569 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4570 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4574 PVE::Storage::activate_volumes($storecfg, $vollist);
4576 if (!check_running($vmid, 1) && -d "/sys/fs
/cgroup
/systemd
/qemu
.slice
/$vmid.scope
") {
4578 push @$cmd, '/bin/systemctl', 'stop', "$vmid.scope
";
4579 eval { run_command($cmd); };
4582 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4586 # deactivate volumes if start fails
4587 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4588 die "start failed
: $err";
4591 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4593 if ($statefile && $statefile ne 'tcp') {
4594 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4598 if ($migratedfrom) {
4601 set_migration_caps($vmid);
4606 print "spice listens on port
$spice_port\n";
4607 if ($spice_ticket) {
4608 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4609 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4615 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4616 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4617 if $conf->{balloon};
4620 foreach my $opt (keys %$conf) {
4621 next if $opt !~ m/^net\d+$/;
4622 my $nicconf = parse_net($conf->{$opt});
4623 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4627 vm_mon_cmd_nocheck($vmid, 'qom-set',
4628 path => "machine
/peripheral/balloon0
",
4629 property => "guest-stats-polling-interval
",
4630 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4636 my ($vmid, $execute, %params) = @_;
4638 my $cmd = { execute => $execute, arguments => \%params };
4639 vm_qmp_command($vmid, $cmd);
4642 sub vm_mon_cmd_nocheck {
4643 my ($vmid, $execute, %params) = @_;
4645 my $cmd = { execute => $execute, arguments => \%params };
4646 vm_qmp_command($vmid, $cmd, 1);
4649 sub vm_qmp_command {
4650 my ($vmid, $cmd, $nocheck) = @_;
4655 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4656 $timeout = $cmd->{arguments}->{timeout};
4657 delete $cmd->{arguments}->{timeout};
4661 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4662 my $sname = qmp_socket($vmid);
4663 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4664 my $qmpclient = PVE::QMPClient->new();
4666 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4667 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4668 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4669 if scalar(%{$cmd->{arguments}});
4670 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4672 die "unable to open monitor socket\n";
4676 syslog("err", "VM $vmid qmp command failed - $err");
4683 sub vm_human_monitor_command {
4684 my ($vmid, $cmdline) = @_;
4689 execute => 'human-monitor-command
',
4690 arguments => { 'command-line
' => $cmdline},
4693 return vm_qmp_command($vmid, $cmd);
4696 sub vm_commandline {
4697 my ($storecfg, $vmid) = @_;
4699 my $conf = PVE::QemuConfig->load_config($vmid);
4701 my $defaults = load_defaults();
4703 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4705 return join(' ', @$cmd);
4709 my ($vmid, $skiplock) = @_;
4711 PVE::QemuConfig->lock_config($vmid, sub {
4713 my $conf = PVE::QemuConfig->load_config($vmid);
4715 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4717 vm_mon_cmd($vmid, "system_reset");
4721 sub get_vm_volumes {
4725 foreach_volid($conf, sub {
4726 my ($volid, $is_cdrom) = @_;
4728 return if $volid =~ m|^/|;
4730 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4733 push @$vollist, $volid;
4739 sub vm_stop_cleanup {
4740 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4745 my $vollist = get_vm_volumes($conf);
4746 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4749 foreach my $ext (qw(mon qmp pid vnc qga)) {
4750 unlink "/var/run/qemu-server/${vmid}.$ext";
4753 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4755 warn $@ if $@; # avoid errors - just warn
4758 # Note: use $nockeck to skip tests if VM configuration file exists.
4759 # We need that when migration VMs to other nodes (files already moved)
4760 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4762 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4764 $force = 1 if !defined($force) && !$shutdown;
4767 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4768 kill 15, $pid if $pid;
4769 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4770 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4774 PVE
::QemuConfig-
>lock_config($vmid, sub {
4776 my $pid = check_running
($vmid, $nocheck);
4781 $conf = PVE
::QemuConfig-
>load_config($vmid);
4782 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4783 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4784 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4785 $timeout = $opts->{down
} if $opts->{down
};
4789 $timeout = 60 if !defined($timeout);
4793 if (defined($conf) && $conf->{agent
}) {
4794 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4796 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4799 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4806 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4811 if ($count >= $timeout) {
4813 warn "VM still running - terminating now with SIGTERM\n";
4816 die "VM quit/powerdown failed - got timeout\n";
4819 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4824 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4827 die "VM quit/powerdown failed\n";
4835 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4840 if ($count >= $timeout) {
4841 warn "VM still running - terminating now with SIGKILL\n";
4846 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4851 my ($vmid, $skiplock) = @_;
4853 PVE
::QemuConfig-
>lock_config($vmid, sub {
4855 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4857 PVE
::QemuConfig-
>check_lock($conf)
4858 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4860 vm_mon_cmd
($vmid, "stop");
4865 my ($vmid, $skiplock, $nocheck) = @_;
4867 PVE
::QemuConfig-
>lock_config($vmid, sub {
4871 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4873 PVE
::QemuConfig-
>check_lock($conf)
4874 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4876 vm_mon_cmd
($vmid, "cont");
4879 vm_mon_cmd_nocheck
($vmid, "cont");
4885 my ($vmid, $skiplock, $key) = @_;
4887 PVE
::QemuConfig-
>lock_config($vmid, sub {
4889 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4891 # there is no qmp command, so we use the human monitor command
4892 vm_human_monitor_command
($vmid, "sendkey $key");
4897 my ($storecfg, $vmid, $skiplock) = @_;
4899 PVE
::QemuConfig-
>lock_config($vmid, sub {
4901 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4903 if (!check_running
($vmid)) {
4904 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4906 die "VM $vmid is running - destroy failed\n";
4914 my ($filename, $buf) = @_;
4916 my $fh = IO
::File-
>new($filename, "w");
4917 return undef if !$fh;
4919 my $res = print $fh $buf;
4926 sub pci_device_info
{
4931 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4932 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4934 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4935 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4937 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4938 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4940 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4941 return undef if !defined($product) || $product !~ s/^0x//;
4946 product
=> $product,
4952 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4961 my $name = $dev->{name
};
4963 my $fn = "$pcisysfs/devices/$name/reset";
4965 return file_write
($fn, "1");
4968 sub pci_dev_bind_to_vfio
{
4971 my $name = $dev->{name
};
4973 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4975 if (!-d
$vfio_basedir) {
4976 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4978 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4980 my $testdir = "$vfio_basedir/$name";
4981 return 1 if -d
$testdir;
4983 my $data = "$dev->{vendor} $dev->{product}";
4984 return undef if !file_write
("$vfio_basedir/new_id", $data);
4986 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4987 if (!file_write
($fn, $name)) {
4988 return undef if -f
$fn;
4991 $fn = "$vfio_basedir/bind";
4992 if (! -d
$testdir) {
4993 return undef if !file_write
($fn, $name);
4999 sub pci_dev_group_bind_to_vfio
{
5002 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5004 if (!-d
$vfio_basedir) {
5005 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5007 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5009 # get IOMMU group devices
5010 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5011 my @devs = grep /^0000:/, readdir($D);
5014 foreach my $pciid (@devs) {
5015 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5017 # pci bridges, switches or root ports are not supported
5018 # they have a pci_bus subdirectory so skip them
5019 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5021 my $info = pci_device_info
($1);
5022 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5028 sub print_pci_addr
{
5029 my ($id, $bridges) = @_;
5033 piix3
=> { bus
=> 0, addr
=> 1 },
5034 #addr2 : first videocard
5035 balloon0
=> { bus
=> 0, addr
=> 3 },
5036 watchdog
=> { bus
=> 0, addr
=> 4 },
5037 scsihw0
=> { bus
=> 0, addr
=> 5 },
5038 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
5039 scsihw1
=> { bus
=> 0, addr
=> 6 },
5040 ahci0
=> { bus
=> 0, addr
=> 7 },
5041 qga0
=> { bus
=> 0, addr
=> 8 },
5042 spice
=> { bus
=> 0, addr
=> 9 },
5043 virtio0
=> { bus
=> 0, addr
=> 10 },
5044 virtio1
=> { bus
=> 0, addr
=> 11 },
5045 virtio2
=> { bus
=> 0, addr
=> 12 },
5046 virtio3
=> { bus
=> 0, addr
=> 13 },
5047 virtio4
=> { bus
=> 0, addr
=> 14 },
5048 virtio5
=> { bus
=> 0, addr
=> 15 },
5049 hostpci0
=> { bus
=> 0, addr
=> 16 },
5050 hostpci1
=> { bus
=> 0, addr
=> 17 },
5051 net0
=> { bus
=> 0, addr
=> 18 },
5052 net1
=> { bus
=> 0, addr
=> 19 },
5053 net2
=> { bus
=> 0, addr
=> 20 },
5054 net3
=> { bus
=> 0, addr
=> 21 },
5055 net4
=> { bus
=> 0, addr
=> 22 },
5056 net5
=> { bus
=> 0, addr
=> 23 },
5057 vga1
=> { bus
=> 0, addr
=> 24 },
5058 vga2
=> { bus
=> 0, addr
=> 25 },
5059 vga3
=> { bus
=> 0, addr
=> 26 },
5060 hostpci2
=> { bus
=> 0, addr
=> 27 },
5061 hostpci3
=> { bus
=> 0, addr
=> 28 },
5062 #addr29 : usb-host (pve-usb.cfg)
5063 'pci.1' => { bus
=> 0, addr
=> 30 },
5064 'pci.2' => { bus
=> 0, addr
=> 31 },
5065 'net6' => { bus
=> 1, addr
=> 1 },
5066 'net7' => { bus
=> 1, addr
=> 2 },
5067 'net8' => { bus
=> 1, addr
=> 3 },
5068 'net9' => { bus
=> 1, addr
=> 4 },
5069 'net10' => { bus
=> 1, addr
=> 5 },
5070 'net11' => { bus
=> 1, addr
=> 6 },
5071 'net12' => { bus
=> 1, addr
=> 7 },
5072 'net13' => { bus
=> 1, addr
=> 8 },
5073 'net14' => { bus
=> 1, addr
=> 9 },
5074 'net15' => { bus
=> 1, addr
=> 10 },
5075 'net16' => { bus
=> 1, addr
=> 11 },
5076 'net17' => { bus
=> 1, addr
=> 12 },
5077 'net18' => { bus
=> 1, addr
=> 13 },
5078 'net19' => { bus
=> 1, addr
=> 14 },
5079 'net20' => { bus
=> 1, addr
=> 15 },
5080 'net21' => { bus
=> 1, addr
=> 16 },
5081 'net22' => { bus
=> 1, addr
=> 17 },
5082 'net23' => { bus
=> 1, addr
=> 18 },
5083 'net24' => { bus
=> 1, addr
=> 19 },
5084 'net25' => { bus
=> 1, addr
=> 20 },
5085 'net26' => { bus
=> 1, addr
=> 21 },
5086 'net27' => { bus
=> 1, addr
=> 22 },
5087 'net28' => { bus
=> 1, addr
=> 23 },
5088 'net29' => { bus
=> 1, addr
=> 24 },
5089 'net30' => { bus
=> 1, addr
=> 25 },
5090 'net31' => { bus
=> 1, addr
=> 26 },
5091 'xhci' => { bus
=> 1, addr
=> 27 },
5092 'virtio6' => { bus
=> 2, addr
=> 1 },
5093 'virtio7' => { bus
=> 2, addr
=> 2 },
5094 'virtio8' => { bus
=> 2, addr
=> 3 },
5095 'virtio9' => { bus
=> 2, addr
=> 4 },
5096 'virtio10' => { bus
=> 2, addr
=> 5 },
5097 'virtio11' => { bus
=> 2, addr
=> 6 },
5098 'virtio12' => { bus
=> 2, addr
=> 7 },
5099 'virtio13' => { bus
=> 2, addr
=> 8 },
5100 'virtio14' => { bus
=> 2, addr
=> 9 },
5101 'virtio15' => { bus
=> 2, addr
=> 10 },
5102 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5103 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5104 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5105 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5106 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5107 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5108 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5109 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5110 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5111 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5112 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5113 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5114 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5115 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5116 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5117 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5118 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5119 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5120 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5121 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5122 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5123 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5124 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5125 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5126 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5127 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5128 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5129 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5130 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5131 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5132 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5136 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5137 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5138 my $bus = $devices->{$id}->{bus
};
5139 $res = ",bus=pci.$bus,addr=$addr";
5140 $bridges->{$bus} = 1 if $bridges;
5146 sub print_pcie_addr
{
5151 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5152 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5153 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5154 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5157 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5158 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5159 my $bus = $devices->{$id}->{bus
};
5160 $res = ",bus=$bus,addr=$addr";
5166 # vzdump restore implementaion
5168 sub tar_archive_read_firstfile
{
5169 my $archive = shift;
5171 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5173 # try to detect archive type first
5174 my $pid = open (TMP
, "tar tf '$archive'|") ||
5175 die "unable to open file '$archive'\n";
5176 my $firstfile = <TMP
>;
5180 die "ERROR: archive contaions no data\n" if !$firstfile;
5186 sub tar_restore_cleanup
{
5187 my ($storecfg, $statfile) = @_;
5189 print STDERR
"starting cleanup\n";
5191 if (my $fd = IO
::File-
>new($statfile, "r")) {
5192 while (defined(my $line = <$fd>)) {
5193 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5196 if ($volid =~ m
|^/|) {
5197 unlink $volid || die 'unlink failed\n';
5199 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5201 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5203 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5205 print STDERR
"unable to parse line in statfile - $line";
5212 sub restore_archive
{
5213 my ($archive, $vmid, $user, $opts) = @_;
5215 my $format = $opts->{format
};
5218 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5219 $format = 'tar' if !$format;
5221 } elsif ($archive =~ m/\.tar$/) {
5222 $format = 'tar' if !$format;
5223 } elsif ($archive =~ m/.tar.lzo$/) {
5224 $format = 'tar' if !$format;
5226 } elsif ($archive =~ m/\.vma$/) {
5227 $format = 'vma' if !$format;
5228 } elsif ($archive =~ m/\.vma\.gz$/) {
5229 $format = 'vma' if !$format;
5231 } elsif ($archive =~ m/\.vma\.lzo$/) {
5232 $format = 'vma' if !$format;
5235 $format = 'vma' if !$format; # default
5238 # try to detect archive format
5239 if ($format eq 'tar') {
5240 return restore_tar_archive
($archive, $vmid, $user, $opts);
5242 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5246 sub restore_update_config_line
{
5247 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5249 return if $line =~ m/^\#qmdump\#/;
5250 return if $line =~ m/^\#vzdump\#/;
5251 return if $line =~ m/^lock:/;
5252 return if $line =~ m/^unused\d+:/;
5253 return if $line =~ m/^parent:/;
5254 return if $line =~ m/^template:/; # restored VM is never a template
5256 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5257 # try to convert old 1.X settings
5258 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5259 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5260 my ($model, $macaddr) = split(/\=/, $devconfig);
5261 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5264 bridge
=> "vmbr$ind",
5265 macaddr
=> $macaddr,
5267 my $netstr = print_net
($net);
5269 print $outfd "net$cookie->{netcount}: $netstr\n";
5270 $cookie->{netcount
}++;
5272 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5273 my ($id, $netstr) = ($1, $2);
5274 my $net = parse_net
($netstr);
5275 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5276 $netstr = print_net
($net);
5277 print $outfd "$id: $netstr\n";
5278 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5281 my $di = parse_drive
($virtdev, $value);
5282 if (defined($di->{backup
}) && !$di->{backup
}) {
5283 print $outfd "#$line";
5284 } elsif ($map->{$virtdev}) {
5285 delete $di->{format
}; # format can change on restore
5286 $di->{file
} = $map->{$virtdev};
5287 $value = print_drive
($vmid, $di);
5288 print $outfd "$virtdev: $value\n";
5298 my ($cfg, $vmid) = @_;
5300 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5302 my $volid_hash = {};
5303 foreach my $storeid (keys %$info) {
5304 foreach my $item (@{$info->{$storeid}}) {
5305 next if !($item->{volid
} && $item->{size
});
5306 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5307 $volid_hash->{$item->{volid
}} = $item;
5314 sub is_volume_in_use
{
5315 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5317 my $path = PVE
::Storage
::path
($storecfg, $volid);
5319 my $scan_config = sub {
5320 my ($cref, $snapname) = @_;
5322 foreach my $key (keys %$cref) {
5323 my $value = $cref->{$key};
5324 if (is_valid_drivename
($key)) {
5325 next if $skip_drive && $key eq $skip_drive;
5326 my $drive = parse_drive
($key, $value);
5327 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5328 return 1 if $volid eq $drive->{file
};
5329 if ($drive->{file
} =~ m!^/!) {
5330 return 1 if $drive->{file
} eq $path;
5332 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5334 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5336 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5344 return 1 if &$scan_config($conf);
5348 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5349 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5355 sub update_disksize
{
5356 my ($vmid, $conf, $volid_hash) = @_;
5362 # Note: it is allowed to define multiple storages with same path (alias), so
5363 # we need to check both 'volid' and real 'path' (two different volid can point
5364 # to the same path).
5369 foreach my $opt (keys %$conf) {
5370 if (is_valid_drivename
($opt)) {
5371 my $drive = parse_drive
($opt, $conf->{$opt});
5372 my $volid = $drive->{file
};
5375 $used->{$volid} = 1;
5376 if ($volid_hash->{$volid} &&
5377 (my $path = $volid_hash->{$volid}->{path
})) {
5378 $usedpath->{$path} = 1;
5381 next if drive_is_cdrom
($drive);
5382 next if !$volid_hash->{$volid};
5384 $drive->{size
} = $volid_hash->{$volid}->{size
};
5385 my $new = print_drive
($vmid, $drive);
5386 if ($new ne $conf->{$opt}) {
5388 $conf->{$opt} = $new;
5393 # remove 'unusedX' entry if volume is used
5394 foreach my $opt (keys %$conf) {
5395 next if $opt !~ m/^unused\d+$/;
5396 my $volid = $conf->{$opt};
5397 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5398 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5400 delete $conf->{$opt};
5404 foreach my $volid (sort keys %$volid_hash) {
5405 next if $volid =~ m/vm-$vmid-state-/;
5406 next if $used->{$volid};
5407 my $path = $volid_hash->{$volid}->{path
};
5408 next if !$path; # just to be sure
5409 next if $usedpath->{$path};
5411 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5412 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5419 my ($vmid, $nolock) = @_;
5421 my $cfg = PVE
::Storage
::config
();
5423 my $volid_hash = scan_volids
($cfg, $vmid);
5425 my $updatefn = sub {
5428 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5430 PVE
::QemuConfig-
>check_lock($conf);
5433 foreach my $volid (keys %$volid_hash) {
5434 my $info = $volid_hash->{$volid};
5435 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5438 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5440 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5443 if (defined($vmid)) {
5447 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5450 my $vmlist = config_list
();
5451 foreach my $vmid (keys %$vmlist) {
5455 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5461 sub restore_vma_archive
{
5462 my ($archive, $vmid, $user, $opts, $comp) = @_;
5464 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5465 my $readfrom = $archive;
5470 my $qarchive = PVE
::Tools
::shellquote
($archive);
5471 if ($comp eq 'gzip') {
5472 $uncomp = "zcat $qarchive|";
5473 } elsif ($comp eq 'lzop') {
5474 $uncomp = "lzop -d -c $qarchive|";
5476 die "unknown compression method '$comp'\n";
5481 my $tmpdir = "/var/tmp/vzdumptmp$$";
5484 # disable interrupts (always do cleanups)
5485 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5486 warn "got interrupt - ignored\n";
5489 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5490 POSIX
::mkfifo
($mapfifo, 0600);
5493 my $openfifo = sub {
5494 open($fifofh, '>', $mapfifo) || die $!;
5497 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5504 my $rpcenv = PVE
::RPCEnvironment
::get
();
5506 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5507 my $tmpfn = "$conffile.$$.tmp";
5509 # Note: $oldconf is undef if VM does not exists
5510 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5511 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5513 my $print_devmap = sub {
5514 my $virtdev_hash = {};
5516 my $cfgfn = "$tmpdir/qemu-server.conf";
5518 # we can read the config - that is already extracted
5519 my $fh = IO
::File-
>new($cfgfn, "r") ||
5520 "unable to read qemu-server.conf - $!\n";
5522 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5524 my $pve_firewall_dir = '/etc/pve/firewall';
5525 mkdir $pve_firewall_dir; # make sure the dir exists
5526 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5529 while (defined(my $line = <$fh>)) {
5530 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5531 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5532 die "archive does not contain data for drive '$virtdev'\n"
5533 if !$devinfo->{$devname};
5534 if (defined($opts->{storage
})) {
5535 $storeid = $opts->{storage
} || 'local';
5536 } elsif (!$storeid) {
5539 $format = 'raw' if !$format;
5540 $devinfo->{$devname}->{devname
} = $devname;
5541 $devinfo->{$devname}->{virtdev
} = $virtdev;
5542 $devinfo->{$devname}->{format
} = $format;
5543 $devinfo->{$devname}->{storeid
} = $storeid;
5545 # check permission on storage
5546 my $pool = $opts->{pool
}; # todo: do we need that?
5547 if ($user ne 'root@pam') {
5548 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5551 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5555 foreach my $devname (keys %$devinfo) {
5556 die "found no device mapping information for device '$devname'\n"
5557 if !$devinfo->{$devname}->{virtdev
};
5560 my $cfg = PVE
::Storage
::config
();
5562 # create empty/temp config
5564 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5565 foreach_drive
($oldconf, sub {
5566 my ($ds, $drive) = @_;
5568 return if drive_is_cdrom
($drive);
5570 my $volid = $drive->{file
};
5572 return if !$volid || $volid =~ m
|^/|;
5574 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5575 return if !$path || !$owner || ($owner != $vmid);
5577 # Note: only delete disk we want to restore
5578 # other volumes will become unused
5579 if ($virtdev_hash->{$ds}) {
5580 PVE
::Storage
::vdisk_free
($cfg, $volid);
5584 # delete vmstate files
5585 # since after the restore we have no snapshots anymore
5586 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5587 my $snap = $oldconf->{snapshots
}->{$snapname};
5588 if ($snap->{vmstate
}) {
5589 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5598 foreach my $virtdev (sort keys %$virtdev_hash) {
5599 my $d = $virtdev_hash->{$virtdev};
5600 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5601 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5603 # test if requested format is supported
5604 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5605 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5606 $d->{format
} = $defFormat if !$supported;
5608 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5609 $d->{format
}, undef, $alloc_size);
5610 print STDERR
"new volume ID is '$volid'\n";
5611 $d->{volid
} = $volid;
5612 my $path = PVE
::Storage
::path
($cfg, $volid);
5614 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5616 my $write_zeros = 1;
5617 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5621 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5623 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5624 $map->{$virtdev} = $volid;
5627 $fh->seek(0, 0) || die "seek failed - $!\n";
5629 my $outfd = new IO
::File
($tmpfn, "w") ||
5630 die "unable to write config for VM $vmid\n";
5632 my $cookie = { netcount
=> 0 };
5633 while (defined(my $line = <$fh>)) {
5634 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5643 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5644 die "interrupted by signal\n";
5646 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5648 $oldtimeout = alarm($timeout);
5655 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5656 my ($dev_id, $size, $devname) = ($1, $2, $3);
5657 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5658 } elsif ($line =~ m/^CTIME: /) {
5659 # we correctly received the vma config, so we can disable
5660 # the timeout now for disk allocation (set to 10 minutes, so
5661 # that we always timeout if something goes wrong)
5664 print $fifofh "done\n";
5665 my $tmp = $oldtimeout || 0;
5666 $oldtimeout = undef;
5672 print "restore vma archive: $cmd\n";
5673 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5677 alarm($oldtimeout) if $oldtimeout;
5680 foreach my $devname (keys %$devinfo) {
5681 my $volid = $devinfo->{$devname}->{volid
};
5682 push @$vollist, $volid if $volid;
5685 my $cfg = PVE
::Storage
::config
();
5686 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5694 foreach my $devname (keys %$devinfo) {
5695 my $volid = $devinfo->{$devname}->{volid
};
5698 if ($volid =~ m
|^/|) {
5699 unlink $volid || die 'unlink failed\n';
5701 PVE
::Storage
::vdisk_free
($cfg, $volid);
5703 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5705 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5712 rename($tmpfn, $conffile) ||
5713 die "unable to commit configuration file '$conffile'\n";
5715 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5717 eval { rescan
($vmid, 1); };
5721 sub restore_tar_archive
{
5722 my ($archive, $vmid, $user, $opts) = @_;
5724 if ($archive ne '-') {
5725 my $firstfile = tar_archive_read_firstfile
($archive);
5726 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5727 if $firstfile ne 'qemu-server.conf';
5730 my $storecfg = PVE
::Storage
::config
();
5732 # destroy existing data - keep empty config
5733 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5734 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5736 my $tocmd = "/usr/lib/qemu-server/qmextract";
5738 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5739 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5740 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5741 $tocmd .= ' --info' if $opts->{info
};
5743 # tar option "xf" does not autodetect compression when read from STDIN,
5744 # so we pipe to zcat
5745 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5746 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5748 my $tmpdir = "/var/tmp/vzdumptmp$$";
5751 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5752 local $ENV{VZDUMP_VMID
} = $vmid;
5753 local $ENV{VZDUMP_USER
} = $user;
5755 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5756 my $tmpfn = "$conffile.$$.tmp";
5758 # disable interrupts (always do cleanups)
5759 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5760 print STDERR
"got interrupt - ignored\n";
5765 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5766 die "interrupted by signal\n";
5769 if ($archive eq '-') {
5770 print "extracting archive from STDIN\n";
5771 run_command
($cmd, input
=> "<&STDIN");
5773 print "extracting archive '$archive'\n";
5777 return if $opts->{info
};
5781 my $statfile = "$tmpdir/qmrestore.stat";
5782 if (my $fd = IO
::File-
>new($statfile, "r")) {
5783 while (defined (my $line = <$fd>)) {
5784 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5785 $map->{$1} = $2 if $1;
5787 print STDERR
"unable to parse line in statfile - $line\n";
5793 my $confsrc = "$tmpdir/qemu-server.conf";
5795 my $srcfd = new IO
::File
($confsrc, "r") ||
5796 die "unable to open file '$confsrc'\n";
5798 my $outfd = new IO
::File
($tmpfn, "w") ||
5799 die "unable to write config for VM $vmid\n";
5801 my $cookie = { netcount
=> 0 };
5802 while (defined (my $line = <$srcfd>)) {
5803 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5815 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5822 rename $tmpfn, $conffile ||
5823 die "unable to commit configuration file '$conffile'\n";
5825 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5827 eval { rescan
($vmid, 1); };
5831 sub foreach_writable_storage
{
5832 my ($conf, $func) = @_;
5836 foreach my $ds (keys %$conf) {
5837 next if !is_valid_drivename
($ds);
5839 my $drive = parse_drive
($ds, $conf->{$ds});
5841 next if drive_is_cdrom
($drive);
5843 my $volid = $drive->{file
};
5845 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5846 $sidhash->{$sid} = $sid if $sid;
5849 foreach my $sid (sort keys %$sidhash) {
5854 sub do_snapshots_with_qemu
{
5855 my ($storecfg, $volid) = @_;
5857 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5859 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5860 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5864 if ($volid =~ m/\.(qcow2|qed)$/){
5871 sub qga_check_running
{
5874 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5876 warn "Qemu Guest Agent are not running - $@";
5882 sub template_create
{
5883 my ($vmid, $conf, $disk) = @_;
5885 my $storecfg = PVE
::Storage
::config
();
5887 foreach_drive
($conf, sub {
5888 my ($ds, $drive) = @_;
5890 return if drive_is_cdrom
($drive);
5891 return if $disk && $ds ne $disk;
5893 my $volid = $drive->{file
};
5894 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5896 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5897 $drive->{file
} = $voliddst;
5898 $conf->{$ds} = print_drive
($vmid, $drive);
5899 PVE
::QemuConfig-
>write_config($vmid, $conf);
5903 sub qemu_img_convert
{
5904 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5906 my $storecfg = PVE
::Storage
::config
();
5907 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5908 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5910 if ($src_storeid && $dst_storeid) {
5912 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5914 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5915 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5917 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5918 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5920 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5921 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5924 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5925 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5926 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5927 if ($is_zero_initialized) {
5928 push @$cmd, "zeroinit:$dst_path";
5930 push @$cmd, $dst_path;
5935 if($line =~ m/\((\S+)\/100\
%\)/){
5937 my $transferred = int($size * $percent / 100);
5938 my $remaining = $size - $transferred;
5940 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5945 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5947 die "copy failed: $err" if $err;
5951 sub qemu_img_format
{
5952 my ($scfg, $volname) = @_;
5954 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5961 sub qemu_drive_mirror
{
5962 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5964 my $storecfg = PVE
::Storage
::config
();
5965 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5967 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5969 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5971 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5973 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5975 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5976 $opts->{format
} = $format if $format;
5978 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5980 my $finish_job = sub {
5982 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5983 my $stat = @$stats[0];
5990 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5992 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5993 my $stat = @$stats[0];
5994 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5995 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5997 my $busy = $stat->{busy
};
5998 my $ready = $stat->{ready
};
6000 if (my $total = $stat->{len
}) {
6001 my $transferred = $stat->{offset
} || 0;
6002 my $remaining = $total - $transferred;
6003 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6005 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6009 if ($stat->{ready
} eq 'true') {
6011 last if $vmiddst != $vmid;
6013 # try to switch the disk if source and destination are on the same guest
6014 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6019 die $@ if $@ !~ m/cannot be completed/;
6028 my $cancel_job = sub {
6029 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6034 eval { &$cancel_job(); };
6035 die "mirroring error: $err";
6038 if ($vmiddst != $vmid) {
6039 # if we clone a disk for a new target vm, we don't switch the disk
6040 &$cancel_job(); # so we call block-job-cancel
6045 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6046 $newvmid, $storage, $format, $full, $newvollist) = @_;
6051 print "create linked clone of drive $drivename ($drive->{file})\n";
6052 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6053 push @$newvollist, $newvolid;
6055 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6056 $storeid = $storage if $storage;
6058 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6060 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6061 $format = qemu_img_format
($scfg, $volname);
6064 # test if requested format is supported - else use default
6065 my $supported = grep { $_ eq $format } @$validFormats;
6066 $format = $defFormat if !$supported;
6068 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6070 print "create full clone of drive $drivename ($drive->{file})\n";
6071 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6072 push @$newvollist, $newvolid;
6074 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6076 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6077 if (!$running || $snapname) {
6078 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6080 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
6084 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6087 $disk->{format
} = undef;
6088 $disk->{file
} = $newvolid;
6089 $disk->{size
} = $size;
6094 # this only works if VM is running
6095 sub get_current_qemu_machine
{
6098 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6099 my $res = vm_qmp_command
($vmid, $cmd);
6101 my ($current, $default);
6102 foreach my $e (@$res) {
6103 $default = $e->{name
} if $e->{'is-default'};
6104 $current = $e->{name
} if $e->{'is-current'};
6107 # fallback to the default machine if current is not supported by qemu
6108 return $current || $default || 'pc';
6111 sub qemu_machine_feature_enabled
{
6112 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6117 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6119 $current_major = $3;
6120 $current_minor = $4;
6122 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6124 $current_major = $1;
6125 $current_minor = $2;
6128 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6133 sub qemu_machine_pxe
{
6134 my ($vmid, $conf, $machine) = @_;
6136 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6138 foreach my $opt (keys %$conf) {
6139 next if $opt !~ m/^net(\d+)$/;
6140 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6142 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6143 return $machine.".pxe" if $romfile =~ m/pxe/;
6150 sub qemu_use_old_bios_files
{
6151 my ($machine_type) = @_;
6153 return if !$machine_type;
6155 my $use_old_bios_files = undef;
6157 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6159 $use_old_bios_files = 1;
6161 my $kvmver = kvm_user_version
();
6162 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6163 # load new efi bios files on migration. So this hack is required to allow
6164 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6165 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6166 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6169 return ($use_old_bios_files, $machine_type);
6176 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6177 my (undef, $id, $function) = @_;
6178 my $res = { id
=> $id, function
=> $function};
6179 push @{$devices->{$id}}, $res;
6185 sub vm_iothreads_list
{
6188 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6191 foreach my $iothread (@$res) {
6192 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6199 my ($conf, $drive) = @_;
6203 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6205 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6211 my $controller = int($drive->{index} / $maxdev);
6212 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6214 return ($maxdev, $controller, $controller_prefix);
6217 # bash completion helper
6219 sub complete_backup_archives
{
6220 my ($cmdname, $pname, $cvalue) = @_;
6222 my $cfg = PVE
::Storage
::config
();
6226 if ($cvalue =~ m/^([^:]+):/) {
6230 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6233 foreach my $id (keys %$data) {
6234 foreach my $item (@{$data->{$id}}) {
6235 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6236 push @$res, $item->{volid
} if defined($item->{volid
});
6243 my $complete_vmid_full = sub {
6246 my $idlist = vmstatus
();
6250 foreach my $id (keys %$idlist) {
6251 my $d = $idlist->{$id};
6252 if (defined($running)) {
6253 next if $d->{template
};
6254 next if $running && $d->{status
} ne 'running';
6255 next if !$running && $d->{status
} eq 'running';
6264 return &$complete_vmid_full();
6267 sub complete_vmid_stopped
{
6268 return &$complete_vmid_full(0);
6271 sub complete_vmid_running
{
6272 return &$complete_vmid_full(1);
6275 sub complete_storage
{
6277 my $cfg = PVE
::Storage
::config
();
6278 my $ids = $cfg->{ids
};
6281 foreach my $sid (keys %$ids) {
6282 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6283 next if !$ids->{$sid}->{content
}->{images
};