1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
33 use File
::Copy
qw(copy);
35 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
37 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
39 # Note about locking: we use flock on the config file protect
40 # against concurent actions.
41 # Aditionaly, we have a 'lock' setting in the config file. This
42 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
43 # allowed when such lock is set. But you can ignore this kind of
44 # lock with the --skiplock flag.
46 cfs_register_file
('/qemu-server/',
50 PVE
::JSONSchema
::register_standard_option
('skiplock', {
51 description
=> "Ignore locks - only root is allowed to use this option.",
56 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
57 description
=> "Some command save/restore state from this location.",
63 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
64 description
=> "The name of the snapshot.",
65 type
=> 'string', format
=> 'pve-configid',
69 #no warnings 'redefine';
72 my ($controller, $vmid, $option, $value) = @_;
74 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
75 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
79 my $nodename = PVE
::INotify
::nodename
();
81 mkdir "/etc/pve/nodes/$nodename";
82 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
85 my $var_run_tmpdir = "/var/run/qemu-server";
86 mkdir $var_run_tmpdir;
88 my $lock_dir = "/var/lock/qemu-server";
91 my $pcisysfs = "/sys/bus/pci";
95 description
=> "Emulated CPU type.",
97 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Haswell-noTSX Broadwell Broadwell-noTSX Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
102 description
=> "Do not identify as a KVM virtual machine.",
113 description
=> "Specifies whether a VM will be started during system bootup.",
119 description
=> "Automatic restart after crash (currently ignored).",
124 type
=> 'string', format
=> 'pve-hotplug-features',
125 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'.",
126 default => 'network,disk,usb',
131 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
137 description
=> "Lock/unlock the VM.",
138 enum
=> [qw(migrate backup snapshot rollback)],
143 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
151 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.",
159 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
166 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
172 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",
180 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
181 enum
=> PVE
::Tools
::kvmkeymaplist
(),
186 type
=> 'string', format
=> 'dns-name',
187 description
=> "Set a name for the VM. Only used on the configuration web interface.",
192 description
=> "scsi controller model",
193 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
199 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
204 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
205 description
=> <<EODESC,
206 Used to enable special optimization/features for specific
209 other => unspecified OS
210 wxp => Microsoft Windows XP
211 w2k => Microsoft Windows 2000
212 w2k3 => Microsoft Windows 2003
213 w2k8 => Microsoft Windows 2008
214 wvista => Microsoft Windows Vista
215 win7 => Microsoft Windows 7
216 win8 => Microsoft Windows 8/2012
217 l24 => Linux 2.4 Kernel
218 l26 => Linux 2.6/3.X Kernel
219 solaris => solaris/opensolaris/openindiania kernel
221 other|l24|l26|solaris ... no special behaviour
222 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
228 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
229 pattern
=> '[acdn]{1,4}',
234 type
=> 'string', format
=> 'pve-qm-bootdisk',
235 description
=> "Enable booting from specified disk.",
236 pattern
=> '(ide|sata|scsi|virtio)\d+',
241 description
=> "The number of CPUs. Please use option -sockets instead.",
248 description
=> "The number of CPU sockets.",
255 description
=> "The number of cores per socket.",
262 description
=> "Enable/disable Numa.",
268 description
=> "Number of hotplugged vcpus.",
275 description
=> "Enable/disable ACPI.",
281 description
=> "Enable/disable Qemu GuestAgent.",
287 description
=> "Enable/disable KVM hardware virtualization.",
293 description
=> "Enable/disable time drift fix.",
299 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
304 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
309 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
310 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
314 type
=> 'string', format
=> 'pve-qm-watchdog',
315 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
316 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
321 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
322 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'.",
323 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
326 startup
=> get_standard_option
('pve-startup-order'),
330 description
=> "Enable/disable Template.",
336 description
=> <<EODESCR,
337 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
339 args: -no-reboot -no-hpet
346 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
351 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
355 migrate_downtime
=> {
358 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
364 type
=> 'string', format
=> 'pve-qm-drive',
365 typetext
=> 'volume',
366 description
=> "This is an alias for option -ide2",
370 description
=> "Emulated CPU type.",
374 parent
=> get_standard_option
('pve-snapshot-name', {
376 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
380 description
=> "Timestamp for snapshots.",
386 type
=> 'string', format
=> 'pve-volume-id',
387 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
390 description
=> "Specific the Qemu machine type.",
392 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
397 description
=> "Specify SMBIOS type 1 fields.",
398 type
=> 'string', format
=> 'pve-qm-smbios1',
405 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
411 enum
=> [ qw(seabios ovmf) ],
412 description
=> "Select BIOS implementation.",
413 default => 'seabios',
417 # what about other qemu settings ?
419 #machine => 'string',
432 ##soundhw => 'string',
434 while (my ($k, $v) = each %$confdesc) {
435 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
438 my $MAX_IDE_DISKS = 4;
439 my $MAX_SCSI_DISKS = 14;
440 my $MAX_VIRTIO_DISKS = 16;
441 my $MAX_SATA_DISKS = 6;
442 my $MAX_USB_DEVICES = 5;
444 my $MAX_UNUSED_DISKS = 8;
445 my $MAX_HOSTPCI_DEVICES = 4;
446 my $MAX_SERIAL_PORTS = 4;
447 my $MAX_PARALLEL_PORTS = 3;
449 my $MAX_MEM = 4194304;
450 my $STATICMEM = 1024;
454 type
=> 'string', format
=> 'pve-qm-numanode',
455 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
456 description
=> "numa topology",
458 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
460 for (my $i = 0; $i < $MAX_NUMA; $i++) {
461 $confdesc->{"numa$i"} = $numadesc;
464 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
465 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
466 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
467 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
471 type
=> 'string', format
=> 'pve-qm-net',
472 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,trunks=<vlanid[;vlanid]>][,firewall=0|1],link_down=0|1]",
473 description
=> <<EODESCR,
474 Specify network devices.
476 MODEL is one of: $nic_model_list_txt
478 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
479 automatically generated if not specified.
481 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
483 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'.
485 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
491 The DHCP server assign addresses to the guest starting from 10.0.2.15.
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
497 for (my $i = 0; $i < $MAX_NETS; $i++) {
498 $confdesc->{"net$i"} = $netdesc;
503 my %drivedesc_base = (
504 volume
=> { alias
=> 'file' },
506 type
=> 'pve-volume-id',
508 format_description
=> 'volume',
509 description
=> "The drive's backing volume.",
513 format_description
=> 'cdrom|disk',
514 enum
=> [qw(cdrom disk)],
515 description
=> "The drive's media type.",
521 format_description
=> 'count',
522 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
527 format_description
=> 'count',
528 description
=> "Force the drive's physical geometry to have a specific head count.",
533 format_description
=> 'count',
534 description
=> "Force the drive's physical geometry to have a specific sector count.",
539 format_description
=> 'none|lba|auto',
540 enum
=> [qw(none lba auto)],
541 description
=> "Force disk geometry bios translation mode.",
546 format_description
=> 'on|off',
547 description
=> "Whether the drive should be included when making snapshots.",
552 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
553 enum
=> [qw(none writethrough writeback unsafe directsync)],
554 description
=> "The drive's cache mode",
559 format_description
=> 'drive format',
560 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
561 description
=> "The drive's backing file's data format.",
566 format
=> 'disk-size',
567 description
=> "Disk size. This is purely informational and has no effect.",
572 format_description
=> 'on|off',
573 description
=> "Whether the drive should be included when making backups.",
578 format_description
=> 'enospc|ignore|report|stop',
579 enum
=> [qw(enospc ignore report stop)],
580 description
=> 'Write error action.',
585 format_description
=> 'native|threads',
586 enum
=> [qw(native threads)],
587 description
=> 'AIO type to use.',
592 format_description
=> 'ignore|on',
593 enum
=> [qw(ignore on)],
594 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
599 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
604 format_description
=> 'serial',
605 description
=> "The drive's reported serial number.",
613 format_description
=> 'ignore|report|stop',
614 enum
=> [qw(ignore report stop)],
615 description
=> 'Read error action.',
620 my %iothread_fmt = ( iothread
=> {
622 format_description
=> 'off|on',
623 description
=> "Whether to use iothreads for this drive",
630 format_description
=> 'model',
631 description
=> "The drive's reported model name.",
639 format_description
=> 'nbqueues',
640 description
=> "Number of queues.",
646 my $add_throttle_desc = sub {
647 my ($key, $type, $what, $size, $longsize) = @_;
648 $drivedesc_base{$key} = {
650 format_description
=> $size,
651 description
=> "Maximum $what speed in $longsize per second.",
655 # throughput: (leaky bucket)
656 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
657 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
658 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
659 $add_throttle_desc->('mbps', 'float', 'r/w speed', 'mbps', 'megabytes');
660 $add_throttle_desc->('mbps_rd', 'float', 'read speed', 'mbps', 'megabytes');
661 $add_throttle_desc->('mbps_wr', 'float', 'write speed', 'mbps', 'megabytes');
662 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
663 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
664 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
666 # pools: (pool of IO before throttling starts taking effect)
667 $add_throttle_desc->('mbps_max', 'float', 'unthrottled r/w pool', 'mbps', 'megabytes');
668 $add_throttle_desc->('mbps_rd_max', 'float', 'unthrottled read pool', 'mbps', 'megabytes');
669 $add_throttle_desc->('mbps_wr_max', 'float', 'unthrottled write pool', 'mbps', 'megabytes');
670 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
671 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
672 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
682 type
=> 'string', format
=> $ide_fmt,
683 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
685 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
694 type
=> 'string', format
=> $scsi_fmt,
695 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
697 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
705 type
=> 'string', format
=> $sata_fmt,
706 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
708 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
717 type
=> 'string', format
=> $virtio_fmt,
718 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
720 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
732 type
=> 'string', format
=> 'pve-qm-usb-device',
733 typetext
=> 'host=HOSTUSBDEVICE|spice',
734 description
=> <<EODESCR,
735 Configure an USB device (n is 0 to 4). This can be used to
736 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
738 'bus-port(.port)*' (decimal numbers) or
739 'vendor_id:product_id' (hexadeciaml numbers)
741 You can use the 'lsusb -t' command to list existing usb devices.
743 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
745 The value 'spice' can be used to add a usb redirection devices for spice.
749 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
753 type
=> 'string', format
=> 'pve-qm-hostpci',
754 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
755 description
=> <<EODESCR,
756 Map host pci devices. HOSTPCIDEVICE syntax is:
758 'bus:dev.func' (hexadecimal numbers)
760 You can us the 'lspci' command to list existing pci devices.
762 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
764 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
766 Experimental: user reported problems with this option.
769 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
774 pattern
=> '(/dev/.+|socket)',
775 description
=> <<EODESCR,
776 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).
778 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
780 Experimental: user reported problems with this option.
787 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
788 description
=> <<EODESCR,
789 Map host parallel devices (n is 0 to 2).
791 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
793 Experimental: user reported problems with this option.
797 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
798 $confdesc->{"parallel$i"} = $paralleldesc;
801 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
802 $confdesc->{"serial$i"} = $serialdesc;
805 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
806 $confdesc->{"hostpci$i"} = $hostpcidesc;
809 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
810 $drivename_hash->{"ide$i"} = 1;
811 $confdesc->{"ide$i"} = $idedesc;
814 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
815 $drivename_hash->{"sata$i"} = 1;
816 $confdesc->{"sata$i"} = $satadesc;
819 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
820 $drivename_hash->{"scsi$i"} = 1;
821 $confdesc->{"scsi$i"} = $scsidesc ;
824 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
825 $drivename_hash->{"virtio$i"} = 1;
826 $confdesc->{"virtio$i"} = $virtiodesc;
829 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
830 $confdesc->{"usb$i"} = $usbdesc;
835 type
=> 'string', format
=> 'pve-volume-id',
836 description
=> "Reference to unused volumes.",
839 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
840 $confdesc->{"unused$i"} = $unuseddesc;
843 my $kvm_api_version = 0;
847 return $kvm_api_version if $kvm_api_version;
849 my $fh = IO
::File-
>new("</dev/kvm") ||
852 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
853 $kvm_api_version = $v;
858 return $kvm_api_version;
861 my $kvm_user_version;
863 sub kvm_user_version
{
865 return $kvm_user_version if $kvm_user_version;
867 $kvm_user_version = 'unknown';
869 my $tmp = `kvm -help 2>/dev/null`;
871 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
872 $kvm_user_version = $2;
875 return $kvm_user_version;
879 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
882 # order is important - used to autoselect boot disk
883 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
884 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
885 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
886 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
889 sub valid_drivename
{
892 return defined($drivename_hash->{$dev});
897 return defined($confdesc->{$key});
901 return $nic_model_list;
904 sub os_list_description
{
909 w2k
=> 'Windows 2000',
910 w2k3
=>, 'Windows 2003',
911 w2k8
=> 'Windows 2008',
912 wvista
=> 'Windows Vista',
914 win8
=> 'Windows 8/2012',
924 return $cdrom_path if $cdrom_path;
926 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
927 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
928 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
932 my ($storecfg, $vmid, $cdrom) = @_;
934 if ($cdrom eq 'cdrom') {
935 return get_cdrom_path
();
936 } elsif ($cdrom eq 'none') {
938 } elsif ($cdrom =~ m
|^/|) {
941 return PVE
::Storage
::path
($storecfg, $cdrom);
945 # try to convert old style file names to volume IDs
946 sub filename_to_volume_id
{
947 my ($vmid, $file, $media) = @_;
949 if (!($file eq 'none' || $file eq 'cdrom' ||
950 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
952 return undef if $file =~ m
|/|;
954 if ($media && $media eq 'cdrom') {
955 $file = "local:iso/$file";
957 $file = "local:$vmid/$file";
964 sub verify_media_type
{
965 my ($opt, $vtype, $media) = @_;
970 if ($media eq 'disk') {
972 } elsif ($media eq 'cdrom') {
975 die "internal error";
978 return if ($vtype eq $etype);
980 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
983 sub cleanup_drive_path
{
984 my ($opt, $storecfg, $drive) = @_;
986 # try to convert filesystem paths to volume IDs
988 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
989 ($drive->{file
} !~ m
|^/dev/.+|) &&
990 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
991 ($drive->{file
} !~ m/^\d+$/)) {
992 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
993 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
994 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
995 verify_media_type
($opt, $vtype, $drive->{media
});
996 $drive->{file
} = $volid;
999 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1002 sub create_conf_nolock
{
1003 my ($vmid, $settings) = @_;
1005 my $filename = config_file
($vmid);
1007 die "configuration file '$filename' already exists\n" if -f
$filename;
1009 my $defaults = load_defaults
();
1011 $settings->{name
} = "vm$vmid" if !$settings->{name
};
1012 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
1015 foreach my $opt (keys %$settings) {
1016 next if !$confdesc->{$opt};
1018 my $value = $settings->{$opt};
1021 $data .= "$opt: $value\n";
1024 PVE
::Tools
::file_set_contents
($filename, $data);
1027 sub parse_hotplug_features
{
1032 return $res if $data eq '0';
1034 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1036 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1037 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1040 warn "ignoring unknown hotplug feature '$feature'\n";
1046 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1047 sub pve_verify_hotplug_features
{
1048 my ($value, $noerr) = @_;
1050 return $value if parse_hotplug_features
($value);
1052 return undef if $noerr;
1054 die "unable to parse hotplug option\n";
1057 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1058 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1059 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1060 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1061 # [,iothread=on][,serial=serial][,model=model]
1064 my ($key, $data) = @_;
1066 my ($interface, $index);
1068 if ($key =~ m/^([^\d]+)(\d+)$/) {
1075 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1076 : $confdesc->{$key}->{format
};
1078 warn "invalid drive key: $key\n";
1081 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1082 return undef if !$res;
1083 $res->{interface
} = $interface;
1084 $res->{index} = $index;
1087 foreach my $opt (qw(bps bps_rd bps_wr)) {
1088 if (my $bps = defined(delete $res->{$opt})) {
1089 if (defined($res->{"m$opt"})) {
1090 warn "both $opt and m$opt specified\n";
1094 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1097 return undef if $error;
1099 return undef if $res->{mbps_rd
} && $res->{mbps
};
1100 return undef if $res->{mbps_wr
} && $res->{mbps
};
1101 return undef if $res->{iops_rd
} && $res->{iops
};
1102 return undef if $res->{iops_wr
} && $res->{iops
};
1104 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1105 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1106 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1107 return undef if $res->{interface
} eq 'virtio';
1110 if (my $size = $res->{size
}) {
1111 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1118 my ($vmid, $drive) = @_;
1119 my $data = { %$drive };
1120 delete $data->{$_} for qw(index interface);
1121 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1125 my($fh, $noerr) = @_;
1128 my $SG_GET_VERSION_NUM = 0x2282;
1130 my $versionbuf = "\x00" x
8;
1131 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1133 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1136 my $version = unpack("I", $versionbuf);
1137 if ($version < 30000) {
1138 die "scsi generic interface too old\n" if !$noerr;
1142 my $buf = "\x00" x
36;
1143 my $sensebuf = "\x00" x
8;
1144 my $cmd = pack("C x3 C x1", 0x12, 36);
1146 # see /usr/include/scsi/sg.h
1147 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";
1149 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1150 length($sensebuf), 0, length($buf), $buf,
1151 $cmd, $sensebuf, 6000);
1153 $ret = ioctl($fh, $SG_IO, $packet);
1155 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1159 my @res = unpack($sg_io_hdr_t, $packet);
1160 if ($res[17] || $res[18]) {
1161 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1166 (my $byte0, my $byte1, $res->{vendor
},
1167 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1169 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1170 $res->{type
} = $byte0 & 31;
1178 my $fh = IO
::File-
>new("+<$path") || return undef;
1179 my $res = scsi_inquiry
($fh, 1);
1185 sub machine_type_is_q35
{
1188 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1191 sub print_tabletdevice_full
{
1194 my $q35 = machine_type_is_q35
($conf);
1196 # we use uhci for old VMs because tablet driver was buggy in older qemu
1197 my $usbbus = $q35 ?
"ehci" : "uhci";
1199 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1202 sub print_drivedevice_full
{
1203 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1208 if ($drive->{interface
} eq 'virtio') {
1209 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1210 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1211 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1212 } elsif ($drive->{interface
} eq 'scsi') {
1214 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1215 my $unit = $drive->{index} % $maxdev;
1216 my $devicetype = 'hd';
1218 if (drive_is_cdrom
($drive)) {
1221 if ($drive->{file
} =~ m
|^/|) {
1222 $path = $drive->{file
};
1224 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1227 if($path =~ m/^iscsi\:\/\
//){
1228 $devicetype = 'generic';
1230 if (my $info = path_is_scsi
($path)) {
1231 if ($info->{type
} == 0) {
1232 $devicetype = 'block';
1233 } elsif ($info->{type
} == 1) { # tape
1234 $devicetype = 'generic';
1240 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1241 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1243 $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}";
1246 } elsif ($drive->{interface
} eq 'ide'){
1248 my $controller = int($drive->{index} / $maxdev);
1249 my $unit = $drive->{index} % $maxdev;
1250 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1252 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1253 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1254 $device .= ",model=$model";
1256 } elsif ($drive->{interface
} eq 'sata'){
1257 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1258 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1259 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1260 } elsif ($drive->{interface
} eq 'usb') {
1262 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1264 die "unsupported interface type";
1267 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1272 sub get_initiator_name
{
1275 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1276 while (defined(my $line = <$fh>)) {
1277 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1286 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
1287 sub print_drive_full
{
1288 my ($storecfg, $vmid, $drive) = @_;
1291 my $volid = $drive->{file
};
1294 if (drive_is_cdrom
($drive)) {
1295 $path = get_iso_path
($storecfg, $vmid, $volid);
1297 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1299 $path = PVE
::Storage
::path
($storecfg, $volid);
1300 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1301 $format = qemu_img_format
($scfg, $volname);
1309 foreach my $o (@qemu_drive_options) {
1310 next if $o eq 'bootindex';
1311 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1314 $opts .= ",format=$format" if $format && !$drive->{format
};
1316 foreach my $o (qw(bps bps_rd bps_wr)) {
1317 my $v = $drive->{"m$o"};
1318 $opts .= ",$o=" . int($v*1024*1024) if $v;
1321 my $cache_direct = 0;
1323 if (my $cache = $drive->{cache
}) {
1324 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1325 } elsif (!drive_is_cdrom
($drive)) {
1326 $opts .= ",cache=none";
1330 # aio native works only with O_DIRECT
1331 if (!$drive->{aio
}) {
1333 $opts .= ",aio=native";
1335 $opts .= ",aio=threads";
1339 if (!drive_is_cdrom
($drive)) {
1341 if ($drive->{detect_zeroes
} && $drive->{detect_zeroes
} eq 'off') {
1342 $detectzeroes = 'off';
1343 } elsif ($drive->{discard
}) {
1344 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1346 # This used to be our default with discard not being specified:
1347 $detectzeroes = 'on';
1349 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1352 my $pathinfo = $path ?
"file=$path," : '';
1354 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1357 sub print_netdevice_full
{
1358 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1360 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1362 my $device = $net->{model
};
1363 if ($net->{model
} eq 'virtio') {
1364 $device = 'virtio-net-pci';
1367 my $pciaddr = print_pci_addr
("$netid", $bridges);
1368 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1369 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1370 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1371 my $vectors = $net->{queues
} * 2 + 2;
1372 $tmpstr .= ",vectors=$vectors,mq=on";
1374 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1376 if ($use_old_bios_files) {
1378 if ($device eq 'virtio-net-pci') {
1379 $romfile = 'pxe-virtio.rom';
1380 } elsif ($device eq 'e1000') {
1381 $romfile = 'pxe-e1000.rom';
1382 } elsif ($device eq 'ne2k') {
1383 $romfile = 'pxe-ne2k_pci.rom';
1384 } elsif ($device eq 'pcnet') {
1385 $romfile = 'pxe-pcnet.rom';
1386 } elsif ($device eq 'rtl8139') {
1387 $romfile = 'pxe-rtl8139.rom';
1389 $tmpstr .= ",romfile=$romfile" if $romfile;
1395 sub print_netdev_full
{
1396 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1399 if ($netid =~ m/^net(\d+)$/) {
1403 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1405 my $ifname = "tap${vmid}i$i";
1407 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1408 die "interface name '$ifname' is too long (max 15 character)\n"
1409 if length($ifname) >= 16;
1411 my $vhostparam = '';
1412 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1414 my $vmname = $conf->{name
} || "vm$vmid";
1417 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1419 if ($net->{bridge
}) {
1420 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1422 $netdev = "type=user,id=$netid,hostname=$vmname";
1425 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1430 sub drive_is_cdrom
{
1433 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1442 foreach my $kvp (split(/,/, $data)) {
1444 if ($kvp =~ m/^memory=(\S+)$/) {
1445 $res->{memory
} = $1;
1446 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1447 $res->{policy
} = $1;
1448 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1449 $res->{cpus
}->{start
} = $1;
1450 $res->{cpus
}->{end
} = $3;
1451 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1452 $res->{hostnodes
}->{start
} = $1;
1453 $res->{hostnodes
}->{end
} = $3;
1465 return undef if !$value;
1468 my @list = split(/,/, $value);
1472 foreach my $kv (@list) {
1474 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1477 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1480 my $pcidevices = lspci
($2);
1481 $res->{pciid
} = $pcidevices->{$2};
1483 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1484 $res->{rombar
} = $1;
1485 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1486 $res->{'x-vga'} = $1;
1487 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1488 $res->{pcie
} = 1 if $1 == 1;
1490 warn "unknown hostpci setting '$kv'\n";
1494 return undef if !$found;
1499 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1505 foreach my $kvp (split(/,/, $data)) {
1507 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1509 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1510 $res->{model
} = $model;
1511 $res->{macaddr
} = $mac;
1512 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1513 $res->{bridge
} = $1;
1514 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1515 $res->{queues
} = $1;
1516 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1518 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1520 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1521 $res->{trunks
} = $1;
1522 } elsif ($kvp =~ m/^firewall=([01])$/) {
1523 $res->{firewall
} = $1;
1524 } elsif ($kvp =~ m/^link_down=([01])$/) {
1525 $res->{link_down
} = $1;
1532 return undef if !$res->{model
};
1540 my $res = "$net->{model}";
1541 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1542 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1543 $res .= ",rate=$net->{rate}" if $net->{rate
};
1544 $res .= ",tag=$net->{tag}" if $net->{tag
};
1545 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1546 $res .= ",firewall=1" if $net->{firewall
};
1547 $res .= ",link_down=1" if $net->{link_down
};
1548 $res .= ",queues=$net->{queues}" if $net->{queues
};
1553 sub add_random_macs
{
1554 my ($settings) = @_;
1556 foreach my $opt (keys %$settings) {
1557 next if $opt !~ m/^net(\d+)$/;
1558 my $net = parse_net
($settings->{$opt});
1560 $settings->{$opt} = print_net
($net);
1564 sub add_unused_volume
{
1565 my ($config, $volid) = @_;
1568 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1569 my $test = "unused$ind";
1570 if (my $vid = $config->{$test}) {
1571 return if $vid eq $volid; # do not add duplicates
1577 die "To many unused volume - please delete them first.\n" if !$key;
1579 $config->{$key} = $volid;
1584 sub vm_is_volid_owner
{
1585 my ($storecfg, $vmid, $volid) = @_;
1587 if ($volid !~ m
|^/|) {
1589 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1590 if ($owner && ($owner == $vmid)) {
1598 sub split_flagged_list
{
1599 my $text = shift || '';
1600 $text =~ s/[,;]/ /g;
1602 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1605 sub join_flagged_list
{
1606 my ($how, $lst) = @_;
1607 join $how, map { $lst->{$_} . $_ } keys %$lst;
1610 sub vmconfig_delete_pending_option
{
1611 my ($conf, $key, $force) = @_;
1613 delete $conf->{pending
}->{$key};
1614 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1615 $pending_delete_hash->{$key} = $force ?
'!' : '';
1616 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1619 sub vmconfig_undelete_pending_option
{
1620 my ($conf, $key) = @_;
1622 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1623 delete $pending_delete_hash->{$key};
1625 if (%$pending_delete_hash) {
1626 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1628 delete $conf->{pending
}->{delete};
1632 sub vmconfig_register_unused_drive
{
1633 my ($storecfg, $vmid, $conf, $drive) = @_;
1635 if (!drive_is_cdrom
($drive)) {
1636 my $volid = $drive->{file
};
1637 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1638 add_unused_volume
($conf, $volid, $vmid);
1643 sub vmconfig_cleanup_pending
{
1646 # remove pending changes when nothing changed
1648 foreach my $opt (keys %{$conf->{pending
}}) {
1649 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1651 delete $conf->{pending
}->{$opt};
1655 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1656 my $pending_delete_hash = {};
1657 while (my ($opt, $force) = each %$current_delete_hash) {
1658 if (defined($conf->{$opt})) {
1659 $pending_delete_hash->{$opt} = $force;
1665 if (%$pending_delete_hash) {
1666 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1668 delete $conf->{pending
}->{delete};
1674 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1675 my $smbios1_desc = {
1678 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1679 format_description
=> 'UUID',
1685 format_description
=> 'str',
1691 format_description
=> 'str',
1697 format_description
=> 'name',
1703 format_description
=> 'name',
1709 format_description
=> 'str',
1715 format_description
=> 'str',
1723 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1730 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1733 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1735 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1736 sub verify_bootdisk
{
1737 my ($value, $noerr) = @_;
1739 return $value if valid_drivename
($value);
1741 return undef if $noerr;
1743 die "invalid boot disk '$value'\n";
1746 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1748 my ($value, $noerr) = @_;
1750 return $value if parse_numa
($value);
1752 return undef if $noerr;
1754 die "unable to parse numa options\n";
1757 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1759 my ($value, $noerr) = @_;
1761 return $value if parse_net
($value);
1763 return undef if $noerr;
1765 die "unable to parse network options\n";
1768 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1769 sub verify_hostpci
{
1770 my ($value, $noerr) = @_;
1772 return $value if parse_hostpci
($value);
1774 return undef if $noerr;
1776 die "unable to parse pci id\n";
1779 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1780 sub verify_watchdog
{
1781 my ($value, $noerr) = @_;
1783 return $value if parse_watchdog
($value);
1785 return undef if $noerr;
1787 die "unable to parse watchdog options\n";
1790 sub parse_watchdog
{
1793 return undef if !$value;
1797 foreach my $p (split(/,/, $value)) {
1798 next if $p =~ m/^\s*$/;
1800 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1802 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1803 $res->{action
} = $2;
1812 sub parse_usb_device
{
1815 return undef if !$value;
1817 my @dl = split(/,/, $value);
1821 foreach my $v (@dl) {
1822 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1824 $res->{vendorid
} = $2;
1825 $res->{productid
} = $4;
1826 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1828 $res->{hostbus
} = $1;
1829 $res->{hostport
} = $2;
1830 } elsif ($v =~ m/^spice$/) {
1837 return undef if !$found;
1842 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1843 sub verify_usb_device
{
1844 my ($value, $noerr) = @_;
1846 return $value if parse_usb_device
($value);
1848 return undef if $noerr;
1850 die "unable to parse usb device\n";
1853 # add JSON properties for create and set function
1854 sub json_config_properties
{
1857 foreach my $opt (keys %$confdesc) {
1858 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1859 $prop->{$opt} = $confdesc->{$opt};
1866 my ($key, $value) = @_;
1868 die "unknown setting '$key'\n" if !$confdesc->{$key};
1870 my $type = $confdesc->{$key}->{type
};
1872 if (!defined($value)) {
1873 die "got undefined value\n";
1876 if ($value =~ m/[\n\r]/) {
1877 die "property contains a line feed\n";
1880 if ($type eq 'boolean') {
1881 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1882 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1883 die "type check ('boolean') failed - got '$value'\n";
1884 } elsif ($type eq 'integer') {
1885 return int($1) if $value =~ m/^(\d+)$/;
1886 die "type check ('integer') failed - got '$value'\n";
1887 } elsif ($type eq 'number') {
1888 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1889 die "type check ('number') failed - got '$value'\n";
1890 } elsif ($type eq 'string') {
1891 if (my $fmt = $confdesc->{$key}->{format
}) {
1892 if ($fmt eq 'pve-qm-drive') {
1893 # special case - we need to pass $key to parse_drive()
1894 my $drive = parse_drive
($key, $value);
1895 return $value if $drive;
1896 die "unable to parse drive options\n";
1898 PVE
::JSONSchema
::check_format
($fmt, $value);
1901 $value =~ s/^\"(.*)\"$/$1/;
1904 die "internal error"
1908 sub lock_config_full
{
1909 my ($vmid, $timeout, $code, @param) = @_;
1911 my $filename = config_file_lock
($vmid);
1913 my $res = lock_file
($filename, $timeout, $code, @param);
1920 sub lock_config_mode
{
1921 my ($vmid, $timeout, $shared, $code, @param) = @_;
1923 my $filename = config_file_lock
($vmid);
1925 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1933 my ($vmid, $code, @param) = @_;
1935 return lock_config_full
($vmid, 10, $code, @param);
1938 sub cfs_config_path
{
1939 my ($vmid, $node) = @_;
1941 $node = $nodename if !$node;
1942 return "nodes/$node/qemu-server/$vmid.conf";
1945 sub check_iommu_support
{
1946 #fixme : need to check IOMMU support
1947 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1955 my ($vmid, $node) = @_;
1957 my $cfspath = cfs_config_path
($vmid, $node);
1958 return "/etc/pve/$cfspath";
1961 sub config_file_lock
{
1964 return "$lock_dir/lock-$vmid.conf";
1970 my $conf = config_file
($vmid);
1971 utime undef, undef, $conf;
1975 my ($storecfg, $vmid, $keep_empty_config) = @_;
1977 my $conffile = config_file
($vmid);
1979 my $conf = load_config
($vmid);
1983 # only remove disks owned by this VM
1984 foreach_drive
($conf, sub {
1985 my ($ds, $drive) = @_;
1987 return if drive_is_cdrom
($drive);
1989 my $volid = $drive->{file
};
1991 return if !$volid || $volid =~ m
|^/|;
1993 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1994 return if !$path || !$owner || ($owner != $vmid);
1996 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1999 if ($keep_empty_config) {
2000 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2005 # also remove unused disk
2007 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2010 PVE
::Storage
::foreach_volid
($dl, sub {
2011 my ($volid, $sid, $volname, $d) = @_;
2012 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2022 my ($vmid, $node) = @_;
2024 my $cfspath = cfs_config_path
($vmid, $node);
2026 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
2028 die "no such VM ('$vmid')\n" if !defined($conf);
2033 sub parse_vm_config
{
2034 my ($filename, $raw) = @_;
2036 return undef if !defined($raw);
2039 digest
=> Digest
::SHA
::sha1_hex
($raw),
2044 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2045 || die "got strange filename '$filename'";
2053 my @lines = split(/\n/, $raw);
2054 foreach my $line (@lines) {
2055 next if $line =~ m/^\s*$/;
2057 if ($line =~ m/^\[PENDING\]\s*$/i) {
2058 $section = 'pending';
2059 if (defined($descr)) {
2061 $conf->{description
} = $descr;
2064 $conf = $res->{$section} = {};
2067 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2069 if (defined($descr)) {
2071 $conf->{description
} = $descr;
2074 $conf = $res->{snapshots
}->{$section} = {};
2078 if ($line =~ m/^\#(.*)\s*$/) {
2079 $descr = '' if !defined($descr);
2080 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2084 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2085 $descr = '' if !defined($descr);
2086 $descr .= PVE
::Tools
::decode_text
($2);
2087 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2088 $conf->{snapstate
} = $1;
2089 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2092 $conf->{$key} = $value;
2093 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2095 if ($section eq 'pending') {
2096 $conf->{delete} = $value; # we parse this later
2098 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2100 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2103 eval { $value = check_type
($key, $value); };
2105 warn "vm $vmid - unable to parse value of '$key' - $@";
2107 my $fmt = $confdesc->{$key}->{format
};
2108 if ($fmt && $fmt eq 'pve-qm-drive') {
2109 my $v = parse_drive
($key, $value);
2110 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2111 $v->{file
} = $volid;
2112 $value = print_drive
($vmid, $v);
2114 warn "vm $vmid - unable to parse value of '$key'\n";
2119 if ($key eq 'cdrom') {
2120 $conf->{ide2
} = $value;
2122 $conf->{$key} = $value;
2128 if (defined($descr)) {
2130 $conf->{description
} = $descr;
2132 delete $res->{snapstate
}; # just to be sure
2137 sub write_vm_config
{
2138 my ($filename, $conf) = @_;
2140 delete $conf->{snapstate
}; # just to be sure
2142 if ($conf->{cdrom
}) {
2143 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2144 $conf->{ide2
} = $conf->{cdrom
};
2145 delete $conf->{cdrom
};
2148 # we do not use 'smp' any longer
2149 if ($conf->{sockets
}) {
2150 delete $conf->{smp
};
2151 } elsif ($conf->{smp
}) {
2152 $conf->{sockets
} = $conf->{smp
};
2153 delete $conf->{cores
};
2154 delete $conf->{smp
};
2157 my $used_volids = {};
2159 my $cleanup_config = sub {
2160 my ($cref, $pending, $snapname) = @_;
2162 foreach my $key (keys %$cref) {
2163 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2164 $key eq 'snapstate' || $key eq 'pending';
2165 my $value = $cref->{$key};
2166 if ($key eq 'delete') {
2167 die "propertry 'delete' is only allowed in [PENDING]\n"
2169 # fixme: check syntax?
2172 eval { $value = check_type
($key, $value); };
2173 die "unable to parse value of '$key' - $@" if $@;
2175 $cref->{$key} = $value;
2177 if (!$snapname && valid_drivename
($key)) {
2178 my $drive = parse_drive
($key, $value);
2179 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2184 &$cleanup_config($conf);
2186 &$cleanup_config($conf->{pending
}, 1);
2188 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2189 die "internal error" if $snapname eq 'pending';
2190 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2193 # remove 'unusedX' settings if we re-add a volume
2194 foreach my $key (keys %$conf) {
2195 my $value = $conf->{$key};
2196 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2197 delete $conf->{$key};
2201 my $generate_raw_config = sub {
2202 my ($conf, $pending) = @_;
2206 # add description as comment to top of file
2207 if (defined(my $descr = $conf->{description
})) {
2209 foreach my $cl (split(/\n/, $descr)) {
2210 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2213 $raw .= "#\n" if $pending;
2217 foreach my $key (sort keys %$conf) {
2218 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2219 $raw .= "$key: $conf->{$key}\n";
2224 my $raw = &$generate_raw_config($conf);
2226 if (scalar(keys %{$conf->{pending
}})){
2227 $raw .= "\n[PENDING]\n";
2228 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2231 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2232 $raw .= "\n[$snapname]\n";
2233 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2239 sub update_config_nolock
{
2240 my ($vmid, $conf, $skiplock) = @_;
2242 check_lock
($conf) if !$skiplock;
2244 my $cfspath = cfs_config_path
($vmid);
2246 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2250 my ($vmid, $conf, $skiplock) = @_;
2252 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2259 # we use static defaults from our JSON schema configuration
2260 foreach my $key (keys %$confdesc) {
2261 if (defined(my $default = $confdesc->{$key}->{default})) {
2262 $res->{$key} = $default;
2266 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2267 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2273 my $vmlist = PVE
::Cluster
::get_vmlist
();
2275 return $res if !$vmlist || !$vmlist->{ids
};
2276 my $ids = $vmlist->{ids
};
2278 foreach my $vmid (keys %$ids) {
2279 my $d = $ids->{$vmid};
2280 next if !$d->{node
} || $d->{node
} ne $nodename;
2281 next if !$d->{type
} || $d->{type
} ne 'qemu';
2282 $res->{$vmid}->{exists} = 1;
2287 # test if VM uses local resources (to prevent migration)
2288 sub check_local_resources
{
2289 my ($conf, $noerr) = @_;
2293 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2294 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2296 foreach my $k (keys %$conf) {
2297 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2298 # sockets are safe: they will recreated be on the target side post-migrate
2299 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2300 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2303 die "VM uses local resources\n" if $loc_res && !$noerr;
2308 # check if used storages are available on all nodes (use by migrate)
2309 sub check_storage_availability
{
2310 my ($storecfg, $conf, $node) = @_;
2312 foreach_drive
($conf, sub {
2313 my ($ds, $drive) = @_;
2315 my $volid = $drive->{file
};
2318 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2321 # check if storage is available on both nodes
2322 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2323 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2327 # list nodes where all VM images are available (used by has_feature API)
2329 my ($conf, $storecfg) = @_;
2331 my $nodelist = PVE
::Cluster
::get_nodelist
();
2332 my $nodehash = { map { $_ => 1 } @$nodelist };
2333 my $nodename = PVE
::INotify
::nodename
();
2335 foreach_drive
($conf, sub {
2336 my ($ds, $drive) = @_;
2338 my $volid = $drive->{file
};
2341 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2343 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2344 if ($scfg->{disable
}) {
2346 } elsif (my $avail = $scfg->{nodes
}) {
2347 foreach my $node (keys %$nodehash) {
2348 delete $nodehash->{$node} if !$avail->{$node};
2350 } elsif (!$scfg->{shared
}) {
2351 foreach my $node (keys %$nodehash) {
2352 delete $nodehash->{$node} if $node ne $nodename
2364 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2368 my ($pidfile, $pid) = @_;
2370 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2374 return undef if !$line;
2375 my @param = split(/\0/, $line);
2377 my $cmd = $param[0];
2378 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2380 for (my $i = 0; $i < scalar (@param); $i++) {
2383 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2384 my $p = $param[$i+1];
2385 return 1 if $p && ($p eq $pidfile);
2394 my ($vmid, $nocheck, $node) = @_;
2396 my $filename = config_file
($vmid, $node);
2398 die "unable to find configuration file for VM $vmid - no such machine\n"
2399 if !$nocheck && ! -f
$filename;
2401 my $pidfile = pidfile_name
($vmid);
2403 if (my $fd = IO
::File-
>new("<$pidfile")) {
2408 my $mtime = $st->mtime;
2409 if ($mtime > time()) {
2410 warn "file '$filename' modified in future\n";
2413 if ($line =~ m/^(\d+)$/) {
2415 if (check_cmdline
($pidfile, $pid)) {
2416 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2428 my $vzlist = config_list
();
2430 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2432 while (defined(my $de = $fd->read)) {
2433 next if $de !~ m/^(\d+)\.pid$/;
2435 next if !defined($vzlist->{$vmid});
2436 if (my $pid = check_running
($vmid)) {
2437 $vzlist->{$vmid}->{pid
} = $pid;
2445 my ($storecfg, $conf) = @_;
2447 my $bootdisk = $conf->{bootdisk
};
2448 return undef if !$bootdisk;
2449 return undef if !valid_drivename
($bootdisk);
2451 return undef if !$conf->{$bootdisk};
2453 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2454 return undef if !defined($drive);
2456 return undef if drive_is_cdrom
($drive);
2458 my $volid = $drive->{file
};
2459 return undef if !$volid;
2461 return $drive->{size
};
2464 my $last_proc_pid_stat;
2466 # get VM status information
2467 # This must be fast and should not block ($full == false)
2468 # We only query KVM using QMP if $full == true (this can be slow)
2470 my ($opt_vmid, $full) = @_;
2474 my $storecfg = PVE
::Storage
::config
();
2476 my $list = vzlist
();
2477 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2479 my $cpucount = $cpuinfo->{cpus
} || 1;
2481 foreach my $vmid (keys %$list) {
2482 next if $opt_vmid && ($vmid ne $opt_vmid);
2484 my $cfspath = cfs_config_path
($vmid);
2485 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2488 $d->{pid
} = $list->{$vmid}->{pid
};
2490 # fixme: better status?
2491 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2493 my $size = disksize
($storecfg, $conf);
2494 if (defined($size)) {
2495 $d->{disk
} = 0; # no info available
2496 $d->{maxdisk
} = $size;
2502 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2503 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2504 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2506 $d->{name
} = $conf->{name
} || "VM $vmid";
2507 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2509 if ($conf->{balloon
}) {
2510 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2511 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2522 $d->{diskwrite
} = 0;
2524 $d->{template
} = is_template
($conf);
2529 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2530 foreach my $dev (keys %$netdev) {
2531 next if $dev !~ m/^tap([1-9]\d*)i/;
2533 my $d = $res->{$vmid};
2536 $d->{netout
} += $netdev->{$dev}->{receive
};
2537 $d->{netin
} += $netdev->{$dev}->{transmit
};
2540 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2541 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2546 my $ctime = gettimeofday
;
2548 foreach my $vmid (keys %$list) {
2550 my $d = $res->{$vmid};
2551 my $pid = $d->{pid
};
2554 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2555 next if !$pstat; # not running
2557 my $used = $pstat->{utime} + $pstat->{stime
};
2559 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2561 if ($pstat->{vsize
}) {
2562 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2565 my $old = $last_proc_pid_stat->{$pid};
2567 $last_proc_pid_stat->{$pid} = {
2575 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2577 if ($dtime > 1000) {
2578 my $dutime = $used - $old->{used
};
2580 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2581 $last_proc_pid_stat->{$pid} = {
2587 $d->{cpu
} = $old->{cpu
};
2591 return $res if !$full;
2593 my $qmpclient = PVE
::QMPClient-
>new();
2595 my $ballooncb = sub {
2596 my ($vmid, $resp) = @_;
2598 my $info = $resp->{'return'};
2599 return if !$info->{max_mem
};
2601 my $d = $res->{$vmid};
2603 # use memory assigned to VM
2604 $d->{maxmem
} = $info->{max_mem
};
2605 $d->{balloon
} = $info->{actual
};
2607 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2608 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2609 $d->{freemem
} = $info->{free_mem
};
2612 $d->{ballooninfo
} = $info;
2615 my $blockstatscb = sub {
2616 my ($vmid, $resp) = @_;
2617 my $data = $resp->{'return'} || [];
2618 my $totalrdbytes = 0;
2619 my $totalwrbytes = 0;
2621 for my $blockstat (@$data) {
2622 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2623 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2625 $blockstat->{device
} =~ s/drive-//;
2626 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2628 $res->{$vmid}->{diskread
} = $totalrdbytes;
2629 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2632 my $statuscb = sub {
2633 my ($vmid, $resp) = @_;
2635 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2636 # this fails if ballon driver is not loaded, so this must be
2637 # the last commnand (following command are aborted if this fails).
2638 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2640 my $status = 'unknown';
2641 if (!defined($status = $resp->{'return'}->{status
})) {
2642 warn "unable to get VM status\n";
2646 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2649 foreach my $vmid (keys %$list) {
2650 next if $opt_vmid && ($vmid ne $opt_vmid);
2651 next if !$res->{$vmid}->{pid
}; # not running
2652 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2655 $qmpclient->queue_execute(undef, 1);
2657 foreach my $vmid (keys %$list) {
2658 next if $opt_vmid && ($vmid ne $opt_vmid);
2659 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2666 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2669 my $current_size = 1024;
2670 my $dimm_size = 512;
2671 return if $current_size == $memory;
2673 for (my $j = 0; $j < 8; $j++) {
2674 for (my $i = 0; $i < 32; $i++) {
2675 my $name = "dimm${dimm_id}";
2677 my $numanode = $i % $sockets;
2678 $current_size += $dimm_size;
2679 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2680 return $current_size if $current_size >= $memory;
2686 sub foreach_reverse_dimm
{
2687 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2690 my $current_size = 4177920;
2691 my $dimm_size = 65536;
2692 return if $current_size == $memory;
2694 for (my $j = 0; $j < 8; $j++) {
2695 for (my $i = 0; $i < 32; $i++) {
2696 my $name = "dimm${dimm_id}";
2698 my $numanode = $i % $sockets;
2699 $current_size -= $dimm_size;
2700 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2701 return $current_size if $current_size <= $memory;
2708 my ($conf, $func) = @_;
2710 foreach my $ds (keys %$conf) {
2711 next if !valid_drivename
($ds);
2713 my $drive = parse_drive
($ds, $conf->{$ds});
2716 &$func($ds, $drive);
2721 my ($conf, $func) = @_;
2725 my $test_volid = sub {
2726 my ($volid, $is_cdrom) = @_;
2730 $volhash->{$volid} = $is_cdrom || 0;
2733 foreach_drive
($conf, sub {
2734 my ($ds, $drive) = @_;
2735 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2738 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2739 my $snap = $conf->{snapshots
}->{$snapname};
2740 &$test_volid($snap->{vmstate
}, 0);
2741 foreach_drive
($snap, sub {
2742 my ($ds, $drive) = @_;
2743 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2747 foreach my $volid (keys %$volhash) {
2748 &$func($volid, $volhash->{$volid});
2752 sub vga_conf_has_spice
{
2755 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2760 sub config_to_command
{
2761 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2764 my $globalFlags = [];
2765 my $machineFlags = [];
2771 my $kvmver = kvm_user_version
();
2772 my $vernum = 0; # unknown
2773 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2774 $vernum = $1*1000000+$2*1000;
2775 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2776 $vernum = $1*1000000+$2*1000+$3;
2779 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2781 my $have_ovz = -f
'/proc/vz/vestat';
2783 my $q35 = machine_type_is_q35
($conf);
2784 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2785 my $machine_type = $forcemachine || $conf->{machine
};
2786 my $use_old_bios_files = undef;
2787 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2789 my $cpuunits = defined($conf->{cpuunits
}) ?
2790 $conf->{cpuunits
} : $defaults->{cpuunits
};
2792 push @$cmd, '/usr/bin/systemd-run';
2793 push @$cmd, '--scope';
2794 push @$cmd, '--slice', "qemu";
2795 push @$cmd, '--unit', $vmid;
2796 # set KillMode=none, so that systemd don't kill those scopes
2797 # at shutdown (pve-manager service should stop the VMs instead)
2798 push @$cmd, '-p', "KillMode=none";
2799 push @$cmd, '-p', "CPUShares=$cpuunits";
2800 if ($conf->{cpulimit
}) {
2801 my $cpulimit = int($conf->{cpulimit
} * 100);
2802 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2805 push @$cmd, '/usr/bin/kvm';
2807 push @$cmd, '-id', $vmid;
2811 my $qmpsocket = qmp_socket
($vmid);
2812 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2813 push @$cmd, '-mon', "chardev=qmp,mode=control";
2815 my $socket = vnc_socket
($vmid);
2816 push @$cmd, '-vnc', "unix:$socket,x509,password";
2818 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2820 push @$cmd, '-daemonize';
2822 if ($conf->{smbios1
}) {
2823 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2826 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2827 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2828 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2829 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2830 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2831 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2832 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2836 # the q35 chipset support native usb2, so we enable usb controller
2837 # by default for this machine type
2838 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2840 $pciaddr = print_pci_addr
("piix3", $bridges);
2841 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2844 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2845 next if !$conf->{"usb$i"};
2848 # include usb device config
2849 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2852 my $vga = $conf->{vga
};
2854 my $qxlnum = vga_conf_has_spice
($vga);
2855 $vga = 'qxl' if $qxlnum;
2858 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2859 $conf->{ostype
} eq 'win7' ||
2860 $conf->{ostype
} eq 'w2k8')) {
2867 # enable absolute mouse coordinates (needed by vnc)
2869 if (defined($conf->{tablet
})) {
2870 $tablet = $conf->{tablet
};
2872 $tablet = $defaults->{tablet
};
2873 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2874 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2877 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2882 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2883 my $d = parse_hostpci
($conf->{"hostpci$i"});
2886 my $pcie = $d->{pcie
};
2888 die "q35 machine model is not enabled" if !$q35;
2889 $pciaddr = print_pcie_addr
("hostpci$i");
2891 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2894 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2895 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2896 if ($xvga && $xvga ne '') {
2900 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2904 my $pcidevices = $d->{pciid
};
2905 my $multifunction = 1 if @$pcidevices > 1;
2908 foreach my $pcidevice (@$pcidevices) {
2910 my $id = "hostpci$i";
2911 $id .= ".$j" if $multifunction;
2912 my $addr = $pciaddr;
2913 $addr .= ".$j" if $multifunction;
2914 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2917 $devicestr .= "$rombar$xvga";
2918 $devicestr .= ",multifunction=on" if $multifunction;
2921 push @$devices, '-device', $devicestr;
2927 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2928 my $d = parse_usb_device
($conf->{"usb$i"});
2930 if ($d->{vendorid
} && $d->{productid
}) {
2931 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2932 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2933 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2934 } elsif ($d->{spice
}) {
2935 # usb redir support for spice
2936 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2937 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2942 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2943 if (my $path = $conf->{"serial$i"}) {
2944 if ($path eq 'socket') {
2945 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2946 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2947 push @$devices, '-device', "isa-serial,chardev=serial$i";
2949 die "no such serial device\n" if ! -c
$path;
2950 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2951 push @$devices, '-device', "isa-serial,chardev=serial$i";
2957 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2958 if (my $path = $conf->{"parallel$i"}) {
2959 die "no such parallel device\n" if ! -c
$path;
2960 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2961 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2962 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2966 my $vmname = $conf->{name
} || "vm$vmid";
2968 push @$cmd, '-name', $vmname;
2971 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2972 $sockets = $conf->{sockets
} if $conf->{sockets
};
2974 my $cores = $conf->{cores
} || 1;
2976 my $maxcpus = $sockets * $cores;
2978 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2980 my $allowed_vcpus = $cpuinfo->{cpus
};
2982 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2983 if ($allowed_vcpus < $maxcpus);
2985 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2987 push @$cmd, '-nodefaults';
2989 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2991 my $bootindex_hash = {};
2993 foreach my $o (split(//, $bootorder)) {
2994 $bootindex_hash->{$o} = $i*100;
2998 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
3000 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3002 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3004 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3007 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3009 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3010 my $useLocaltime = $conf->{localtime};
3012 if (my $ost = $conf->{ostype
}) {
3013 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3015 if ($ost =~ m/^w/) { # windows
3016 $useLocaltime = 1 if !defined($conf->{localtime});
3018 # use time drift fix when acpi is enabled
3019 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3020 $tdf = 1 if !defined($conf->{tdf
});
3024 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
3026 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3027 push @$cmd, '-no-hpet';
3028 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3029 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm && !$nohyperv;
3030 push @$cpuFlags , 'hv_vapic' if !$nokvm && !$nohyperv;
3031 push @$cpuFlags , 'hv_time' if !$nokvm && !$nohyperv;
3034 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm && !$nohyperv;
3038 if ($ost eq 'win7' || $ost eq 'win8') {
3039 push @$cpuFlags , 'hv_relaxed' if !$nokvm && !$nohyperv;
3043 push @$rtcFlags, 'driftfix=slew' if $tdf;
3046 push @$machineFlags, 'accel=tcg';
3048 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3051 if ($machine_type) {
3052 push @$machineFlags, "type=${machine_type}";
3055 if ($conf->{startdate
}) {
3056 push @$rtcFlags, "base=$conf->{startdate}";
3057 } elsif ($useLocaltime) {
3058 push @$rtcFlags, 'base=localtime';
3061 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3062 if (my $cputype = $conf->{cpu
}) {
3063 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3064 or die "Cannot parse cpu description: $cputype\n";
3065 $cpu = $cpuconf->{cputype
};
3066 $kvm_off = 1 if $cpuconf->{hidden
};
3069 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3071 push @$cpuFlags , '-x2apic'
3072 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3074 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3076 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3078 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3080 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3081 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3084 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3086 push @$cpuFlags, 'kvm=off' if $kvm_off;
3088 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3090 push @$cmd, '-cpu', $cpu;
3092 my $memory = $conf->{memory
} || $defaults->{memory
};
3093 my $static_memory = 0;
3094 my $dimm_memory = 0;
3096 if ($hotplug_features->{memory
}) {
3097 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3098 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3099 $static_memory = $STATICMEM;
3100 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3101 $dimm_memory = $memory - $static_memory;
3102 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3106 $static_memory = $memory;
3107 push @$cmd, '-m', $static_memory;
3110 if ($conf->{numa
}) {
3112 my $numa_totalmemory = undef;
3113 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3114 next if !$conf->{"numa$i"};
3115 my $numa = parse_numa
($conf->{"numa$i"});
3118 die "missing numa node$i memory value\n" if !$numa->{memory
};
3119 my $numa_memory = $numa->{memory
};
3120 $numa_totalmemory += $numa_memory;
3121 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3124 my $cpus_start = $numa->{cpus
}->{start
};
3125 die "missing numa node$i cpus\n" if !defined($cpus_start);
3126 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3127 my $cpus = $cpus_start;
3128 if (defined($cpus_end)) {
3129 $cpus .= "-$cpus_end";
3130 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3134 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3135 if (defined($hostnodes_start)) {
3136 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3137 my $hostnodes = $hostnodes_start;
3138 if (defined($hostnodes_end)) {
3139 $hostnodes .= "-$hostnodes_end";
3140 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3143 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3144 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3145 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3149 my $policy = $numa->{policy
};
3150 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3151 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3154 push @$cmd, '-object', $numa_object;
3155 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3158 die "total memory for NUMA nodes must be equal to vm static memory\n"
3159 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3161 #if no custom tology, we split memory and cores across numa nodes
3162 if(!$numa_totalmemory) {
3164 my $numa_memory = ($static_memory / $sockets) . "M";
3166 for (my $i = 0; $i < $sockets; $i++) {
3168 my $cpustart = ($cores * $i);
3169 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3170 my $cpus = $cpustart;
3171 $cpus .= "-$cpuend" if $cpuend;
3173 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3174 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3179 if ($hotplug_features->{memory
}) {
3180 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3181 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3182 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3183 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3185 #if dimm_memory is not aligned to dimm map
3186 if($current_size > $memory) {
3187 $conf->{memory
} = $current_size;
3188 update_config_nolock
($vmid, $conf, 1);
3193 push @$cmd, '-S' if $conf->{freeze
};
3195 # set keyboard layout
3196 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3197 push @$cmd, '-k', $kb if $kb;
3200 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3201 #push @$cmd, '-soundhw', 'es1370';
3202 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3204 if($conf->{agent
}) {
3205 my $qgasocket = qmp_socket
($vmid, 1);
3206 my $pciaddr = print_pci_addr
("qga0", $bridges);
3207 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3208 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3209 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3216 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3217 for(my $i = 1; $i < $qxlnum; $i++){
3218 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3219 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3222 # assume other OS works like Linux
3223 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3224 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3228 my $pciaddr = print_pci_addr
("spice", $bridges);
3230 my $nodename = PVE
::INotify
::nodename
();
3231 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3232 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3234 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3236 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3237 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3238 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3241 # enable balloon by default, unless explicitly disabled
3242 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3243 $pciaddr = print_pci_addr
("balloon0", $bridges);
3244 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3247 if ($conf->{watchdog
}) {
3248 my $wdopts = parse_watchdog
($conf->{watchdog
});
3249 $pciaddr = print_pci_addr
("watchdog", $bridges);
3250 my $watchdog = $wdopts->{model
} || 'i6300esb';
3251 push @$devices, '-device', "$watchdog$pciaddr";
3252 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3256 my $scsicontroller = {};
3257 my $ahcicontroller = {};
3258 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3260 # Add iscsi initiator name if available
3261 if (my $initiator = get_initiator_name
()) {
3262 push @$devices, '-iscsi', "initiator-name=$initiator";
3265 foreach_drive
($conf, sub {
3266 my ($ds, $drive) = @_;
3268 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3269 push @$vollist, $drive->{file
};
3272 $use_virtio = 1 if $ds =~ m/^virtio/;
3274 if (drive_is_cdrom
($drive)) {
3275 if ($bootindex_hash->{d
}) {
3276 $drive->{bootindex
} = $bootindex_hash->{d
};
3277 $bootindex_hash->{d
} += 1;
3280 if ($bootindex_hash->{c
}) {
3281 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3282 $bootindex_hash->{c
} += 1;
3286 if($drive->{interface
} eq 'virtio'){
3287 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3290 if ($drive->{interface
} eq 'scsi') {
3292 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3294 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3295 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3298 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3299 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3300 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3304 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3305 $queues = ",num_queues=$drive->{queues}";
3308 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3309 $scsicontroller->{$controller}=1;
3312 if ($drive->{interface
} eq 'sata') {
3313 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3314 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3315 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3316 $ahcicontroller->{$controller}=1;
3319 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3320 push @$devices, '-drive',$drive_cmd;
3321 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3324 for (my $i = 0; $i < $MAX_NETS; $i++) {
3325 next if !$conf->{"net$i"};
3326 my $d = parse_net
($conf->{"net$i"});
3329 $use_virtio = 1 if $d->{model
} eq 'virtio';
3331 if ($bootindex_hash->{n
}) {
3332 $d->{bootindex
} = $bootindex_hash->{n
};
3333 $bootindex_hash->{n
} += 1;
3336 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3337 push @$devices, '-netdev', $netdevfull;
3339 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3340 push @$devices, '-device', $netdevicefull;
3345 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3350 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3352 while (my ($k, $v) = each %$bridges) {
3353 $pciaddr = print_pci_addr
("pci.$k");
3354 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3359 if ($conf->{args
}) {
3360 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3364 push @$cmd, @$devices;
3365 push @$cmd, '-rtc', join(',', @$rtcFlags)
3366 if scalar(@$rtcFlags);
3367 push @$cmd, '-machine', join(',', @$machineFlags)
3368 if scalar(@$machineFlags);
3369 push @$cmd, '-global', join(',', @$globalFlags)
3370 if scalar(@$globalFlags);
3372 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3377 return "${var_run_tmpdir}/$vmid.vnc";
3383 my $res = vm_mon_cmd
($vmid, 'query-spice');
3385 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3389 my ($vmid, $qga) = @_;
3390 my $sockettype = $qga ?
'qga' : 'qmp';
3391 return "${var_run_tmpdir}/$vmid.$sockettype";
3396 return "${var_run_tmpdir}/$vmid.pid";
3399 sub vm_devices_list
{
3402 my $res = vm_mon_cmd
($vmid, 'query-pci');
3404 foreach my $pcibus (@$res) {
3405 foreach my $device (@{$pcibus->{devices
}}) {
3406 next if !$device->{'qdev_id'};
3407 if ($device->{'pci_bridge'}) {
3408 $devices->{$device->{'qdev_id'}} = 1;
3409 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3410 next if !$bridge_device->{'qdev_id'};
3411 $devices->{$bridge_device->{'qdev_id'}} = 1;
3412 $devices->{$device->{'qdev_id'}}++;
3415 $devices->{$device->{'qdev_id'}} = 1;
3420 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3421 foreach my $block (@$resblock) {
3422 if($block->{device
} =~ m/^drive-(\S+)/){
3427 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3428 foreach my $mice (@$resmice) {
3429 if ($mice->{name
} eq 'QEMU HID Tablet') {
3430 $devices->{tablet
} = 1;
3439 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3441 my $q35 = machine_type_is_q35
($conf);
3443 my $devices_list = vm_devices_list
($vmid);
3444 return 1 if defined($devices_list->{$deviceid});
3446 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3448 if ($deviceid eq 'tablet') {
3450 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3452 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3454 qemu_iothread_add
($vmid, $deviceid, $device);
3456 qemu_driveadd
($storecfg, $vmid, $device);
3457 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3459 qemu_deviceadd
($vmid, $devicefull);
3460 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3462 eval { qemu_drivedel
($vmid, $deviceid); };
3467 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3470 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3471 my $pciaddr = print_pci_addr
($deviceid);
3472 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3474 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3476 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3477 qemu_iothread_add
($vmid, $deviceid, $device);
3478 $devicefull .= ",iothread=iothread-$deviceid";
3481 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3482 $devicefull .= ",num_queues=$device->{queues}";
3485 qemu_deviceadd
($vmid, $devicefull);
3486 qemu_deviceaddverify
($vmid, $deviceid);
3488 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3490 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3491 qemu_driveadd
($storecfg, $vmid, $device);
3493 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3494 eval { qemu_deviceadd
($vmid, $devicefull); };
3496 eval { qemu_drivedel
($vmid, $deviceid); };
3501 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3503 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3505 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3506 my $use_old_bios_files = undef;
3507 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3509 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3510 qemu_deviceadd
($vmid, $netdevicefull);
3511 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3513 eval { qemu_netdevdel
($vmid, $deviceid); };
3518 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3521 my $pciaddr = print_pci_addr
($deviceid);
3522 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3524 qemu_deviceadd
($vmid, $devicefull);
3525 qemu_deviceaddverify
($vmid, $deviceid);
3528 die "can't hotplug device '$deviceid'\n";
3534 # fixme: this should raise exceptions on error!
3535 sub vm_deviceunplug
{
3536 my ($vmid, $conf, $deviceid) = @_;
3538 my $devices_list = vm_devices_list
($vmid);
3539 return 1 if !defined($devices_list->{$deviceid});
3541 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3543 if ($deviceid eq 'tablet') {
3545 qemu_devicedel
($vmid, $deviceid);
3547 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3549 qemu_devicedel
($vmid, $deviceid);
3550 qemu_devicedelverify
($vmid, $deviceid);
3551 qemu_drivedel
($vmid, $deviceid);
3552 qemu_iothread_del
($conf, $vmid, $deviceid);
3554 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3556 qemu_devicedel
($vmid, $deviceid);
3557 qemu_devicedelverify
($vmid, $deviceid);
3558 qemu_iothread_del
($conf, $vmid, $deviceid);
3560 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3562 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3563 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3564 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3566 qemu_devicedel
($vmid, $deviceid);
3567 qemu_drivedel
($vmid, $deviceid);
3568 qemu_deletescsihw
($conf, $vmid, $deviceid);
3570 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3572 qemu_devicedel
($vmid, $deviceid);
3573 qemu_devicedelverify
($vmid, $deviceid);
3574 qemu_netdevdel
($vmid, $deviceid);
3577 die "can't unplug device '$deviceid'\n";
3583 sub qemu_deviceadd
{
3584 my ($vmid, $devicefull) = @_;
3586 $devicefull = "driver=".$devicefull;
3587 my %options = split(/[=,]/, $devicefull);
3589 vm_mon_cmd
($vmid, "device_add" , %options);
3592 sub qemu_devicedel
{
3593 my ($vmid, $deviceid) = @_;
3595 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3598 sub qemu_iothread_add
{
3599 my($vmid, $deviceid, $device) = @_;
3601 if ($device->{iothread
}) {
3602 my $iothreads = vm_iothreads_list
($vmid);
3603 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3607 sub qemu_iothread_del
{
3608 my($conf, $vmid, $deviceid) = @_;
3610 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3611 if ($device->{iothread
}) {
3612 my $iothreads = vm_iothreads_list
($vmid);
3613 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3617 sub qemu_objectadd
{
3618 my($vmid, $objectid, $qomtype) = @_;
3620 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3625 sub qemu_objectdel
{
3626 my($vmid, $objectid) = @_;
3628 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3634 my ($storecfg, $vmid, $device) = @_;
3636 my $drive = print_drive_full
($storecfg, $vmid, $device);
3637 $drive =~ s/\\/\\\\/g;
3638 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3640 # If the command succeeds qemu prints: "OK
"
3641 return 1 if $ret =~ m/OK/s;
3643 die "adding drive failed
: $ret\n";
3647 my($vmid, $deviceid) = @_;
3649 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3652 return 1 if $ret eq "";
3654 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3655 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3657 die "deleting drive
$deviceid failed
: $ret\n";
3660 sub qemu_deviceaddverify {
3661 my ($vmid, $deviceid) = @_;
3663 for (my $i = 0; $i <= 5; $i++) {
3664 my $devices_list = vm_devices_list($vmid);
3665 return 1 if defined($devices_list->{$deviceid});
3669 die "error on hotplug device
'$deviceid'\n";
3673 sub qemu_devicedelverify {
3674 my ($vmid, $deviceid) = @_;
3676 # need to verify that the device is correctly removed as device_del
3677 # is async and empty return is not reliable
3679 for (my $i = 0; $i <= 5; $i++) {
3680 my $devices_list = vm_devices_list($vmid);
3681 return 1 if !defined($devices_list->{$deviceid});
3685 die "error on hot-unplugging device
'$deviceid'\n";
3688 sub qemu_findorcreatescsihw {
3689 my ($storecfg, $conf, $vmid, $device) = @_;
3691 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3693 my $scsihwid="$controller_prefix$controller";
3694 my $devices_list = vm_devices_list($vmid);
3696 if(!defined($devices_list->{$scsihwid})) {
3697 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3703 sub qemu_deletescsihw {
3704 my ($conf, $vmid, $opt) = @_;
3706 my $device = parse_drive($opt, $conf->{$opt});
3708 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3709 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3713 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3715 my $devices_list = vm_devices_list($vmid);
3716 foreach my $opt (keys %{$devices_list}) {
3717 if (PVE::QemuServer::valid_drivename($opt)) {
3718 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3719 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3725 my $scsihwid="scsihw
$controller";
3727 vm_deviceunplug($vmid, $conf, $scsihwid);
3732 sub qemu_add_pci_bridge {
3733 my ($storecfg, $conf, $vmid, $device) = @_;
3739 print_pci_addr($device, $bridges);
3741 while (my ($k, $v) = each %$bridges) {
3744 return 1 if !defined($bridgeid) || $bridgeid < 1;
3746 my $bridge = "pci
.$bridgeid";
3747 my $devices_list = vm_devices_list($vmid);
3749 if (!defined($devices_list->{$bridge})) {
3750 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3756 sub qemu_set_link_status {
3757 my ($vmid, $device, $up) = @_;
3759 vm_mon_cmd($vmid, "set_link
", name => $device,
3760 up => $up ? JSON::true : JSON::false);
3763 sub qemu_netdevadd {
3764 my ($vmid, $conf, $device, $deviceid) = @_;
3766 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3767 my %options = split(/[=,]/, $netdev);
3769 vm_mon_cmd($vmid, "netdev_add
", %options);
3773 sub qemu_netdevdel {
3774 my ($vmid, $deviceid) = @_;
3776 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3779 sub qemu_cpu_hotplug {
3780 my ($vmid, $conf, $vcpus) = @_;
3783 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3784 $sockets = $conf->{sockets} if $conf->{sockets};
3785 my $cores = $conf->{cores} || 1;
3786 my $maxcpus = $sockets * $cores;
3788 $vcpus = $maxcpus if !$vcpus;
3790 die "you can
't add more vcpus than maxcpus\n"
3791 if $vcpus > $maxcpus;
3793 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3794 die "online cpu unplug is not yet possible\n"
3795 if $vcpus < $currentvcpus;
3797 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3798 die "vcpus in running vm is different than configuration\n"
3799 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3801 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3802 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3806 sub qemu_memory_hotplug {
3807 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3809 return $value if !check_running($vmid);
3811 my $memory = $conf->{memory} || $defaults->{memory};
3812 $value = $defaults->{memory} if !$value;
3813 return $value if $value == $memory;
3815 my $static_memory = $STATICMEM;
3816 my $dimm_memory = $memory - $static_memory;
3818 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3819 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3823 $sockets = $conf->{sockets} if $conf->{sockets};
3825 if($value > $memory) {
3827 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3828 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3830 return if $current_size <= $conf->{memory};
3832 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3834 eval { qemu_objectdel($vmid, "mem-
$name"); };
3838 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3840 eval { qemu_objectdel($vmid, "mem-
$name"); };
3843 #update conf after each succesful module hotplug
3844 $conf->{memory} = $current_size;
3845 update_config_nolock($vmid, $conf, 1);
3850 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3851 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3853 return if $current_size >= $conf->{memory};
3854 print "try to unplug memory dimm
$name\n";
3858 eval { qemu_devicedel($vmid, $name) };
3860 my $dimm_list = qemu_dimm_list($vmid);
3861 last if !$dimm_list->{$name};
3862 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3866 #update conf after each succesful module unplug
3867 $conf->{memory} = $current_size;
3869 eval { qemu_objectdel($vmid, "mem-
$name"); };
3870 update_config_nolock($vmid, $conf, 1);
3875 sub qemu_dimm_list {
3878 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3881 foreach my $dimm (@$dimmarray) {
3883 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3884 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3885 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3886 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3887 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3892 sub qemu_block_set_io_throttle {
3893 my ($vmid, $deviceid,
3894 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3895 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3897 return if !check_running($vmid) ;
3899 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3901 bps_rd => int($bps_rd),
3902 bps_wr => int($bps_wr),
3904 iops_rd => int($iops_rd),
3905 iops_wr => int($iops_wr),
3906 bps_max => int($bps_max),
3907 bps_rd_max => int($bps_rd_max),
3908 bps_wr_max => int($bps_wr_max),
3909 iops_max => int($iops_max),
3910 iops_rd_max => int($iops_rd_max),
3911 iops_wr_max => int($iops_wr_max)
3916 # old code, only used to shutdown old VM after update
3918 my ($fh, $timeout) = @_;
3920 my $sel = new IO::Select;
3927 while (scalar (@ready = $sel->can_read($timeout))) {
3929 if ($count = $fh->sysread($buf, 8192)) {
3930 if ($buf =~ /^(.*)\(qemu\) $/s) {
3937 if (!defined($count)) {
3944 die "monitor
read timeout
\n" if !scalar(@ready);
3949 # old code, only used to shutdown old VM after update
3950 sub vm_monitor_command {
3951 my ($vmid, $cmdstr, $nocheck) = @_;
3956 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3958 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3960 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3961 die "unable to
connect to VM
$vmid socket - $!\n";
3965 # hack: migrate sometime blocks the monitor (when migrate_downtime
3967 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3968 $timeout = 60*60; # 1 hour
3972 my $data = __read_avail($sock, $timeout);
3974 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3975 die "got unexpected qemu monitor banner
\n";
3978 my $sel = new IO::Select;
3981 if (!scalar(my @ready = $sel->can_write($timeout))) {
3982 die "monitor
write error
- timeout
";
3985 my $fullcmd = "$cmdstr\r";
3987 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3990 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3991 die "monitor
write error
- $!";
3994 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3998 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3999 $timeout = 60*60; # 1 hour
4000 } elsif ($cmdstr =~ m/^(eject|change)/) {
4001 $timeout = 60; # note: cdrom mount command is slow
4003 if ($res = __read_avail($sock, $timeout)) {
4005 my @lines = split("\r?
\n", $res);
4007 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4009 $res = join("\n", @lines);
4017 syslog("err
", "VM
$vmid monitor command failed
- $err");
4024 sub qemu_block_resize {
4025 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4027 my $running = check_running($vmid);
4029 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4031 return if !$running;
4033 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4037 sub qemu_volume_snapshot {
4038 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4040 my $running = check_running($vmid);
4042 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4043 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4045 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4049 sub qemu_volume_snapshot_delete {
4050 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4052 my $running = check_running($vmid);
4054 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4056 return if !$running;
4058 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4061 sub set_migration_caps {
4067 "auto-converge
" => 1,
4069 "x-rdma-pin-all
" => 0,
4074 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4076 for my $supported_capability (@$supported_capabilities) {
4078 capability => $supported_capability->{capability},
4079 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4083 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4086 my $fast_plug_option = {
4095 # hotplug changes in [PENDING]
4096 # $selection hash can be used to only apply specified options, for
4097 # example: { cores => 1 } (only apply changed 'cores')
4098 # $errors ref is used to return error messages
4099 sub vmconfig_hotplug_pending {
4100 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4102 my $defaults = load_defaults();
4104 # commit values which do not have any impact on running VM first
4105 # Note: those option cannot raise errors, we we do not care about
4106 # $selection and always apply them.
4108 my $add_error = sub {
4109 my ($opt, $msg) = @_;
4110 $errors->{$opt} = "hotplug problem
- $msg";
4114 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4115 if ($fast_plug_option->{$opt}) {
4116 $conf->{$opt} = $conf->{pending}->{$opt};
4117 delete $conf->{pending}->{$opt};
4123 update_config_nolock($vmid, $conf, 1);
4124 $conf = load_config($vmid); # update/reload
4127 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4129 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4130 while (my ($opt, $force) = each %$pending_delete_hash) {
4131 next if $selection && !$selection->{$opt};
4133 if ($opt eq 'hotplug') {
4134 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4135 } elsif ($opt eq 'tablet') {
4136 die "skip
\n" if !$hotplug_features->{usb};
4137 if ($defaults->{tablet}) {
4138 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4140 vm_deviceunplug($vmid, $conf, $opt);
4142 } elsif ($opt eq 'vcpus') {
4143 die "skip
\n" if !$hotplug_features->{cpu};
4144 qemu_cpu_hotplug($vmid, $conf, undef);
4145 } elsif ($opt eq 'balloon') {
4146 # enable balloon device is not hotpluggable
4147 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4148 } elsif ($fast_plug_option->{$opt}) {
4150 } elsif ($opt =~ m/^net(\d+)$/) {
4151 die "skip
\n" if !$hotplug_features->{network};
4152 vm_deviceunplug($vmid, $conf, $opt);
4153 } elsif (valid_drivename($opt)) {
4154 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4155 vm_deviceunplug($vmid, $conf, $opt);
4156 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4157 } elsif ($opt =~ m/^memory$/) {
4158 die "skip
\n" if !$hotplug_features->{memory};
4159 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4160 } elsif ($opt eq 'cpuunits') {
4161 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4162 } elsif ($opt eq 'cpulimit') {
4163 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4169 &$add_error($opt, $err) if $err ne "skip
\n";
4171 # save new config if hotplug was successful
4172 delete $conf->{$opt};
4173 vmconfig_undelete_pending_option($conf, $opt);
4174 update_config_nolock($vmid, $conf, 1);
4175 $conf = load_config($vmid); # update/reload
4179 foreach my $opt (keys %{$conf->{pending}}) {
4180 next if $selection && !$selection->{$opt};
4181 my $value = $conf->{pending}->{$opt};
4183 if ($opt eq 'hotplug') {
4184 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4185 } elsif ($opt eq 'tablet') {
4186 die "skip
\n" if !$hotplug_features->{usb};
4188 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4189 } elsif ($value == 0) {
4190 vm_deviceunplug($vmid, $conf, $opt);
4192 } elsif ($opt eq 'vcpus') {
4193 die "skip
\n" if !$hotplug_features->{cpu};
4194 qemu_cpu_hotplug($vmid, $conf, $value);
4195 } elsif ($opt eq 'balloon') {
4196 # enable/disable balloning device is not hotpluggable
4197 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4198 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4199 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4201 # allow manual ballooning if shares is set to zero
4202 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4203 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4204 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4206 } elsif ($opt =~ m/^net(\d+)$/) {
4207 # some changes can be done without hotplug
4208 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4209 $vmid, $opt, $value);
4210 } elsif (valid_drivename($opt)) {
4211 # some changes can be done without hotplug
4212 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4213 $vmid, $opt, $value, 1);
4214 } elsif ($opt =~ m/^memory$/) { #dimms
4215 die "skip
\n" if !$hotplug_features->{memory};
4216 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4217 } elsif ($opt eq 'cpuunits') {
4218 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4219 } elsif ($opt eq 'cpulimit') {
4220 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4221 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4223 die "skip
\n"; # skip non-hot-pluggable options
4227 &$add_error($opt, $err) if $err ne "skip
\n";
4229 # save new config if hotplug was successful
4230 $conf->{$opt} = $value;
4231 delete $conf->{pending}->{$opt};
4232 update_config_nolock($vmid, $conf, 1);
4233 $conf = load_config($vmid); # update/reload
4238 sub try_deallocate_drive {
4239 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4241 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4242 my $volid = $drive->{file};
4243 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4244 my $sid = PVE::Storage::parse_volume_id($volid);
4245 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4247 # check if the disk is really unused
4248 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4249 if is_volume_in_use($storecfg, $conf, $key, $volid);
4250 PVE::Storage::vdisk_free($storecfg, $volid);
4253 # If vm is not owner of this disk remove from config
4261 sub vmconfig_delete_or_detach_drive {
4262 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4264 my $drive = parse_drive($opt, $conf->{$opt});
4266 my $rpcenv = PVE::RPCEnvironment::get();
4267 my $authuser = $rpcenv->get_user();
4270 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4271 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4273 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4277 sub vmconfig_apply_pending {
4278 my ($vmid, $conf, $storecfg) = @_;
4282 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4283 while (my ($opt, $force) = each %$pending_delete_hash) {
4284 die "internal error
" if $opt =~ m/^unused/;
4285 $conf = load_config($vmid); # update/reload
4286 if (!defined($conf->{$opt})) {
4287 vmconfig_undelete_pending_option($conf, $opt);
4288 update_config_nolock($vmid, $conf, 1);
4289 } elsif (valid_drivename($opt)) {
4290 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4291 vmconfig_undelete_pending_option($conf, $opt);
4292 delete $conf->{$opt};
4293 update_config_nolock($vmid, $conf, 1);
4295 vmconfig_undelete_pending_option($conf, $opt);
4296 delete $conf->{$opt};
4297 update_config_nolock($vmid, $conf, 1);
4301 $conf = load_config($vmid); # update/reload
4303 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4304 $conf = load_config($vmid); # update/reload
4306 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4307 # skip if nothing changed
4308 } elsif (valid_drivename($opt)) {
4309 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4310 if defined($conf->{$opt});
4311 $conf->{$opt} = $conf->{pending}->{$opt};
4313 $conf->{$opt} = $conf->{pending}->{$opt};
4316 delete $conf->{pending}->{$opt};
4317 update_config_nolock($vmid, $conf, 1);
4321 my $safe_num_ne = sub {
4324 return 0 if !defined($a) && !defined($b);
4325 return 1 if !defined($a);
4326 return 1 if !defined($b);
4331 my $safe_string_ne = sub {
4334 return 0 if !defined($a) && !defined($b);
4335 return 1 if !defined($a);
4336 return 1 if !defined($b);
4341 sub vmconfig_update_net {
4342 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4344 my $newnet = parse_net($value);
4346 if ($conf->{$opt}) {
4347 my $oldnet = parse_net($conf->{$opt});
4349 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4350 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4351 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4352 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4354 # for non online change, we try to hot-unplug
4355 die "skip
\n" if !$hotplug;
4356 vm_deviceunplug($vmid, $conf, $opt);
4359 die "internal error
" if $opt !~ m/net(\d+)/;
4360 my $iface = "tap
${vmid
}i
$1";
4362 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4363 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4366 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4367 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4368 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4369 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4370 PVE::Network::tap_unplug($iface);
4371 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4374 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4375 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4383 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4389 sub vmconfig_update_disk {
4390 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4392 # fixme: do we need force?
4394 my $drive = parse_drive($opt, $value);
4396 if ($conf->{$opt}) {
4398 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4400 my $media = $drive->{media} || 'disk';
4401 my $oldmedia = $old_drive->{media} || 'disk';
4402 die "unable to change media type
\n" if $media ne $oldmedia;
4404 if (!drive_is_cdrom($old_drive)) {
4406 if ($drive->{file} ne $old_drive->{file}) {
4408 die "skip
\n" if !$hotplug;
4410 # unplug and register as unused
4411 vm_deviceunplug($vmid, $conf, $opt);
4412 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4415 # update existing disk
4417 # skip non hotpluggable value
4418 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4419 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4420 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4421 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4426 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4427 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4428 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4429 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4430 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4431 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4432 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4433 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4434 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4435 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4436 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4437 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4439 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4440 ($drive->{mbps} || 0)*1024*1024,
4441 ($drive->{mbps_rd} || 0)*1024*1024,
4442 ($drive->{mbps_wr} || 0)*1024*1024,
4443 $drive->{iops} || 0,
4444 $drive->{iops_rd} || 0,
4445 $drive->{iops_wr} || 0,
4446 ($drive->{mbps_max} || 0)*1024*1024,
4447 ($drive->{mbps_rd_max} || 0)*1024*1024,
4448 ($drive->{mbps_wr_max} || 0)*1024*1024,
4449 $drive->{iops_max} || 0,
4450 $drive->{iops_rd_max} || 0,
4451 $drive->{iops_wr_max} || 0);
4460 if ($drive->{file} eq 'none') {
4461 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4463 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4464 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4465 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4473 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4475 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
4476 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4480 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4481 $forcemachine, $spice_ticket) = @_;
4483 lock_config($vmid, sub {
4484 my $conf = load_config($vmid, $migratedfrom);
4486 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4488 check_lock($conf) if !$skiplock;
4490 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4492 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4493 vmconfig_apply_pending($vmid, $conf, $storecfg);
4494 $conf = load_config($vmid); # update/reload
4497 my $defaults = load_defaults();
4499 # set environment variable useful inside network script
4500 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4502 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4504 my $migrate_port = 0;
4507 if ($statefile eq 'tcp') {
4508 my $localip = "localhost
";
4509 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4510 my $nodename = PVE::INotify::nodename();
4511 if ($datacenterconf->{migration_unsecure}) {
4512 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4513 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4515 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4516 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4517 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4518 push @$cmd, '-incoming', $migrate_uri;
4521 push @$cmd, '-loadstate', $statefile;
4528 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4529 my $d = parse_hostpci($conf->{"hostpci
$i"});
4531 my $pcidevices = $d->{pciid};
4532 foreach my $pcidevice (@$pcidevices) {
4533 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4535 my $info = pci_device_info("0000:$pciid");
4536 die "IOMMU
not present
\n" if !check_iommu_support();
4537 die "no pci device info
for device
'$pciid'\n" if !$info;
4538 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4539 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4543 PVE::Storage::activate_volumes($storecfg, $vollist);
4545 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4548 die "start failed
: $err" if $err;
4550 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4552 if ($statefile && $statefile ne 'tcp') {
4553 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4557 if ($migratedfrom) {
4560 set_migration_caps($vmid);
4565 print "spice listens on port
$spice_port\n";
4566 if ($spice_ticket) {
4567 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4568 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4574 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4575 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4576 if $conf->{balloon};
4579 foreach my $opt (keys %$conf) {
4580 next if $opt !~ m/^net\d+$/;
4581 my $nicconf = parse_net($conf->{$opt});
4582 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4586 vm_mon_cmd_nocheck($vmid, 'qom-set',
4587 path => "machine
/peripheral/balloon0
",
4588 property => "guest-stats-polling-interval
",
4589 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4595 my ($vmid, $execute, %params) = @_;
4597 my $cmd = { execute => $execute, arguments => \%params };
4598 vm_qmp_command($vmid, $cmd);
4601 sub vm_mon_cmd_nocheck {
4602 my ($vmid, $execute, %params) = @_;
4604 my $cmd = { execute => $execute, arguments => \%params };
4605 vm_qmp_command($vmid, $cmd, 1);
4608 sub vm_qmp_command {
4609 my ($vmid, $cmd, $nocheck) = @_;
4614 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4615 $timeout = $cmd->{arguments}->{timeout};
4616 delete $cmd->{arguments}->{timeout};
4620 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4621 my $sname = qmp_socket($vmid);
4622 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4623 my $qmpclient = PVE::QMPClient->new();
4625 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4626 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4627 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4628 if scalar(%{$cmd->{arguments}});
4629 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4631 die "unable to open monitor socket\n";
4635 syslog("err", "VM $vmid qmp command failed - $err");
4642 sub vm_human_monitor_command {
4643 my ($vmid, $cmdline) = @_;
4648 execute => 'human-monitor-command
',
4649 arguments => { 'command-line
' => $cmdline},
4652 return vm_qmp_command($vmid, $cmd);
4655 sub vm_commandline {
4656 my ($storecfg, $vmid) = @_;
4658 my $conf = load_config($vmid);
4660 my $defaults = load_defaults();
4662 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4664 return join(' ', @$cmd);
4668 my ($vmid, $skiplock) = @_;
4670 lock_config($vmid, sub {
4672 my $conf = load_config($vmid);
4674 check_lock($conf) if !$skiplock;
4676 vm_mon_cmd($vmid, "system_reset");
4680 sub get_vm_volumes {
4684 foreach_volid($conf, sub {
4685 my ($volid, $is_cdrom) = @_;
4687 return if $volid =~ m|^/|;
4689 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4692 push @$vollist, $volid;
4698 sub vm_stop_cleanup {
4699 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4704 my $vollist = get_vm_volumes($conf);
4705 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4708 foreach my $ext (qw(mon qmp pid vnc qga)) {
4709 unlink "/var/run/qemu-server/${vmid}.$ext";
4712 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4714 warn $@ if $@; # avoid errors - just warn
4717 # Note: use $nockeck to skip tests if VM configuration file exists.
4718 # We need that when migration VMs to other nodes (files already moved)
4719 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4721 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4723 $force = 1 if !defined($force) && !$shutdown;
4726 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4727 kill 15, $pid if $pid;
4728 my $conf = load_config
($vmid, $migratedfrom);
4729 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4733 lock_config
($vmid, sub {
4735 my $pid = check_running
($vmid, $nocheck);
4740 $conf = load_config
($vmid);
4741 check_lock
($conf) if !$skiplock;
4742 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4743 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4744 $timeout = $opts->{down
} if $opts->{down
};
4748 $timeout = 60 if !defined($timeout);
4752 if (defined($conf) && $conf->{agent
}) {
4753 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4755 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4758 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4765 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4770 if ($count >= $timeout) {
4772 warn "VM still running - terminating now with SIGTERM\n";
4775 die "VM quit/powerdown failed - got timeout\n";
4778 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4783 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4786 die "VM quit/powerdown failed\n";
4794 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4799 if ($count >= $timeout) {
4800 warn "VM still running - terminating now with SIGKILL\n";
4805 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4810 my ($vmid, $skiplock) = @_;
4812 lock_config
($vmid, sub {
4814 my $conf = load_config
($vmid);
4816 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4818 vm_mon_cmd
($vmid, "stop");
4823 my ($vmid, $skiplock, $nocheck) = @_;
4825 lock_config
($vmid, sub {
4829 my $conf = load_config
($vmid);
4831 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4833 vm_mon_cmd
($vmid, "cont");
4836 vm_mon_cmd_nocheck
($vmid, "cont");
4842 my ($vmid, $skiplock, $key) = @_;
4844 lock_config
($vmid, sub {
4846 my $conf = load_config
($vmid);
4848 # there is no qmp command, so we use the human monitor command
4849 vm_human_monitor_command
($vmid, "sendkey $key");
4854 my ($storecfg, $vmid, $skiplock) = @_;
4856 lock_config
($vmid, sub {
4858 my $conf = load_config
($vmid);
4860 check_lock
($conf) if !$skiplock;
4862 if (!check_running
($vmid)) {
4863 destroy_vm
($storecfg, $vmid);
4865 die "VM $vmid is running - destroy failed\n";
4873 my ($filename, $buf) = @_;
4875 my $fh = IO
::File-
>new($filename, "w");
4876 return undef if !$fh;
4878 my $res = print $fh $buf;
4885 sub pci_device_info
{
4890 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4891 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4893 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4894 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4896 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4897 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4899 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4900 return undef if !defined($product) || $product !~ s/^0x//;
4905 product
=> $product,
4911 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4920 my $name = $dev->{name
};
4922 my $fn = "$pcisysfs/devices/$name/reset";
4924 return file_write
($fn, "1");
4927 sub pci_dev_bind_to_vfio
{
4930 my $name = $dev->{name
};
4932 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4934 if (!-d
$vfio_basedir) {
4935 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4937 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4939 my $testdir = "$vfio_basedir/$name";
4940 return 1 if -d
$testdir;
4942 my $data = "$dev->{vendor} $dev->{product}";
4943 return undef if !file_write
("$vfio_basedir/new_id", $data);
4945 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4946 if (!file_write
($fn, $name)) {
4947 return undef if -f
$fn;
4950 $fn = "$vfio_basedir/bind";
4951 if (! -d
$testdir) {
4952 return undef if !file_write
($fn, $name);
4958 sub pci_dev_group_bind_to_vfio
{
4961 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4963 if (!-d
$vfio_basedir) {
4964 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4966 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4968 # get IOMMU group devices
4969 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4970 my @devs = grep /^0000:/, readdir($D);
4973 foreach my $pciid (@devs) {
4974 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4976 # pci bridges, switches or root ports are not supported
4977 # they have a pci_bus subdirectory so skip them
4978 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4980 my $info = pci_device_info
($1);
4981 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4987 sub print_pci_addr
{
4988 my ($id, $bridges) = @_;
4992 piix3
=> { bus
=> 0, addr
=> 1 },
4993 #addr2 : first videocard
4994 balloon0
=> { bus
=> 0, addr
=> 3 },
4995 watchdog
=> { bus
=> 0, addr
=> 4 },
4996 scsihw0
=> { bus
=> 0, addr
=> 5 },
4997 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4998 scsihw1
=> { bus
=> 0, addr
=> 6 },
4999 ahci0
=> { bus
=> 0, addr
=> 7 },
5000 qga0
=> { bus
=> 0, addr
=> 8 },
5001 spice
=> { bus
=> 0, addr
=> 9 },
5002 virtio0
=> { bus
=> 0, addr
=> 10 },
5003 virtio1
=> { bus
=> 0, addr
=> 11 },
5004 virtio2
=> { bus
=> 0, addr
=> 12 },
5005 virtio3
=> { bus
=> 0, addr
=> 13 },
5006 virtio4
=> { bus
=> 0, addr
=> 14 },
5007 virtio5
=> { bus
=> 0, addr
=> 15 },
5008 hostpci0
=> { bus
=> 0, addr
=> 16 },
5009 hostpci1
=> { bus
=> 0, addr
=> 17 },
5010 net0
=> { bus
=> 0, addr
=> 18 },
5011 net1
=> { bus
=> 0, addr
=> 19 },
5012 net2
=> { bus
=> 0, addr
=> 20 },
5013 net3
=> { bus
=> 0, addr
=> 21 },
5014 net4
=> { bus
=> 0, addr
=> 22 },
5015 net5
=> { bus
=> 0, addr
=> 23 },
5016 vga1
=> { bus
=> 0, addr
=> 24 },
5017 vga2
=> { bus
=> 0, addr
=> 25 },
5018 vga3
=> { bus
=> 0, addr
=> 26 },
5019 hostpci2
=> { bus
=> 0, addr
=> 27 },
5020 hostpci3
=> { bus
=> 0, addr
=> 28 },
5021 #addr29 : usb-host (pve-usb.cfg)
5022 'pci.1' => { bus
=> 0, addr
=> 30 },
5023 'pci.2' => { bus
=> 0, addr
=> 31 },
5024 'net6' => { bus
=> 1, addr
=> 1 },
5025 'net7' => { bus
=> 1, addr
=> 2 },
5026 'net8' => { bus
=> 1, addr
=> 3 },
5027 'net9' => { bus
=> 1, addr
=> 4 },
5028 'net10' => { bus
=> 1, addr
=> 5 },
5029 'net11' => { bus
=> 1, addr
=> 6 },
5030 'net12' => { bus
=> 1, addr
=> 7 },
5031 'net13' => { bus
=> 1, addr
=> 8 },
5032 'net14' => { bus
=> 1, addr
=> 9 },
5033 'net15' => { bus
=> 1, addr
=> 10 },
5034 'net16' => { bus
=> 1, addr
=> 11 },
5035 'net17' => { bus
=> 1, addr
=> 12 },
5036 'net18' => { bus
=> 1, addr
=> 13 },
5037 'net19' => { bus
=> 1, addr
=> 14 },
5038 'net20' => { bus
=> 1, addr
=> 15 },
5039 'net21' => { bus
=> 1, addr
=> 16 },
5040 'net22' => { bus
=> 1, addr
=> 17 },
5041 'net23' => { bus
=> 1, addr
=> 18 },
5042 'net24' => { bus
=> 1, addr
=> 19 },
5043 'net25' => { bus
=> 1, addr
=> 20 },
5044 'net26' => { bus
=> 1, addr
=> 21 },
5045 'net27' => { bus
=> 1, addr
=> 22 },
5046 'net28' => { bus
=> 1, addr
=> 23 },
5047 'net29' => { bus
=> 1, addr
=> 24 },
5048 'net30' => { bus
=> 1, addr
=> 25 },
5049 'net31' => { bus
=> 1, addr
=> 26 },
5050 'virtio6' => { bus
=> 2, addr
=> 1 },
5051 'virtio7' => { bus
=> 2, addr
=> 2 },
5052 'virtio8' => { bus
=> 2, addr
=> 3 },
5053 'virtio9' => { bus
=> 2, addr
=> 4 },
5054 'virtio10' => { bus
=> 2, addr
=> 5 },
5055 'virtio11' => { bus
=> 2, addr
=> 6 },
5056 'virtio12' => { bus
=> 2, addr
=> 7 },
5057 'virtio13' => { bus
=> 2, addr
=> 8 },
5058 'virtio14' => { bus
=> 2, addr
=> 9 },
5059 'virtio15' => { bus
=> 2, addr
=> 10 },
5060 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5061 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5062 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5063 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5064 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5065 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5066 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5067 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5068 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5069 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5070 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5071 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5072 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5073 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5074 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5075 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5076 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5077 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5078 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5079 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5080 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5081 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5082 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5083 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5084 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5085 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5086 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5087 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5088 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5089 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5090 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5094 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5095 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5096 my $bus = $devices->{$id}->{bus
};
5097 $res = ",bus=pci.$bus,addr=$addr";
5098 $bridges->{$bus} = 1 if $bridges;
5104 sub print_pcie_addr
{
5109 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5110 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5111 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5112 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5115 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5116 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5117 my $bus = $devices->{$id}->{bus
};
5118 $res = ",bus=$bus,addr=$addr";
5124 # vzdump restore implementaion
5126 sub tar_archive_read_firstfile
{
5127 my $archive = shift;
5129 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5131 # try to detect archive type first
5132 my $pid = open (TMP
, "tar tf '$archive'|") ||
5133 die "unable to open file '$archive'\n";
5134 my $firstfile = <TMP
>;
5138 die "ERROR: archive contaions no data\n" if !$firstfile;
5144 sub tar_restore_cleanup
{
5145 my ($storecfg, $statfile) = @_;
5147 print STDERR
"starting cleanup\n";
5149 if (my $fd = IO
::File-
>new($statfile, "r")) {
5150 while (defined(my $line = <$fd>)) {
5151 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5154 if ($volid =~ m
|^/|) {
5155 unlink $volid || die 'unlink failed\n';
5157 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5159 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5161 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5163 print STDERR
"unable to parse line in statfile - $line";
5170 sub restore_archive
{
5171 my ($archive, $vmid, $user, $opts) = @_;
5173 my $format = $opts->{format
};
5176 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5177 $format = 'tar' if !$format;
5179 } elsif ($archive =~ m/\.tar$/) {
5180 $format = 'tar' if !$format;
5181 } elsif ($archive =~ m/.tar.lzo$/) {
5182 $format = 'tar' if !$format;
5184 } elsif ($archive =~ m/\.vma$/) {
5185 $format = 'vma' if !$format;
5186 } elsif ($archive =~ m/\.vma\.gz$/) {
5187 $format = 'vma' if !$format;
5189 } elsif ($archive =~ m/\.vma\.lzo$/) {
5190 $format = 'vma' if !$format;
5193 $format = 'vma' if !$format; # default
5196 # try to detect archive format
5197 if ($format eq 'tar') {
5198 return restore_tar_archive
($archive, $vmid, $user, $opts);
5200 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5204 sub restore_update_config_line
{
5205 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5207 return if $line =~ m/^\#qmdump\#/;
5208 return if $line =~ m/^\#vzdump\#/;
5209 return if $line =~ m/^lock:/;
5210 return if $line =~ m/^unused\d+:/;
5211 return if $line =~ m/^parent:/;
5212 return if $line =~ m/^template:/; # restored VM is never a template
5214 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5215 # try to convert old 1.X settings
5216 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5217 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5218 my ($model, $macaddr) = split(/\=/, $devconfig);
5219 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5222 bridge
=> "vmbr$ind",
5223 macaddr
=> $macaddr,
5225 my $netstr = print_net
($net);
5227 print $outfd "net$cookie->{netcount}: $netstr\n";
5228 $cookie->{netcount
}++;
5230 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5231 my ($id, $netstr) = ($1, $2);
5232 my $net = parse_net
($netstr);
5233 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5234 $netstr = print_net
($net);
5235 print $outfd "$id: $netstr\n";
5236 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5239 if ($line =~ m/backup=no/) {
5240 print $outfd "#$line";
5241 } elsif ($virtdev && $map->{$virtdev}) {
5242 my $di = parse_drive
($virtdev, $value);
5243 delete $di->{format
}; # format can change on restore
5244 $di->{file
} = $map->{$virtdev};
5245 $value = print_drive
($vmid, $di);
5246 print $outfd "$virtdev: $value\n";
5256 my ($cfg, $vmid) = @_;
5258 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5260 my $volid_hash = {};
5261 foreach my $storeid (keys %$info) {
5262 foreach my $item (@{$info->{$storeid}}) {
5263 next if !($item->{volid
} && $item->{size
});
5264 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5265 $volid_hash->{$item->{volid
}} = $item;
5272 sub is_volume_in_use
{
5273 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5275 my $path = PVE
::Storage
::path
($storecfg, $volid);
5277 my $scan_config = sub {
5278 my ($cref, $snapname) = @_;
5280 foreach my $key (keys %$cref) {
5281 my $value = $cref->{$key};
5282 if (valid_drivename
($key)) {
5283 next if $skip_drive && $key eq $skip_drive;
5284 my $drive = parse_drive
($key, $value);
5285 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5286 return 1 if $volid eq $drive->{file
};
5287 if ($drive->{file
} =~ m!^/!) {
5288 return 1 if $drive->{file
} eq $path;
5290 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5292 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5294 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5302 return 1 if &$scan_config($conf);
5306 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5307 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5313 sub update_disksize
{
5314 my ($vmid, $conf, $volid_hash) = @_;
5320 # Note: it is allowed to define multiple storages with same path (alias), so
5321 # we need to check both 'volid' and real 'path' (two different volid can point
5322 # to the same path).
5327 foreach my $opt (keys %$conf) {
5328 if (valid_drivename
($opt)) {
5329 my $drive = parse_drive
($opt, $conf->{$opt});
5330 my $volid = $drive->{file
};
5333 $used->{$volid} = 1;
5334 if ($volid_hash->{$volid} &&
5335 (my $path = $volid_hash->{$volid}->{path
})) {
5336 $usedpath->{$path} = 1;
5339 next if drive_is_cdrom
($drive);
5340 next if !$volid_hash->{$volid};
5342 $drive->{size
} = $volid_hash->{$volid}->{size
};
5343 my $new = print_drive
($vmid, $drive);
5344 if ($new ne $conf->{$opt}) {
5346 $conf->{$opt} = $new;
5351 # remove 'unusedX' entry if volume is used
5352 foreach my $opt (keys %$conf) {
5353 next if $opt !~ m/^unused\d+$/;
5354 my $volid = $conf->{$opt};
5355 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5356 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5358 delete $conf->{$opt};
5362 foreach my $volid (sort keys %$volid_hash) {
5363 next if $volid =~ m/vm-$vmid-state-/;
5364 next if $used->{$volid};
5365 my $path = $volid_hash->{$volid}->{path
};
5366 next if !$path; # just to be sure
5367 next if $usedpath->{$path};
5369 add_unused_volume
($conf, $volid);
5370 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5377 my ($vmid, $nolock) = @_;
5379 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5381 my $volid_hash = scan_volids
($cfg, $vmid);
5383 my $updatefn = sub {
5386 my $conf = load_config
($vmid);
5391 foreach my $volid (keys %$volid_hash) {
5392 my $info = $volid_hash->{$volid};
5393 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5396 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5398 update_config_nolock
($vmid, $conf, 1) if $changes;
5401 if (defined($vmid)) {
5405 lock_config
($vmid, $updatefn, $vmid);
5408 my $vmlist = config_list
();
5409 foreach my $vmid (keys %$vmlist) {
5413 lock_config
($vmid, $updatefn, $vmid);
5419 sub restore_vma_archive
{
5420 my ($archive, $vmid, $user, $opts, $comp) = @_;
5422 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5423 my $readfrom = $archive;
5428 my $qarchive = PVE
::Tools
::shellquote
($archive);
5429 if ($comp eq 'gzip') {
5430 $uncomp = "zcat $qarchive|";
5431 } elsif ($comp eq 'lzop') {
5432 $uncomp = "lzop -d -c $qarchive|";
5434 die "unknown compression method '$comp'\n";
5439 my $tmpdir = "/var/tmp/vzdumptmp$$";
5442 # disable interrupts (always do cleanups)
5443 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5444 warn "got interrupt - ignored\n";
5447 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5448 POSIX
::mkfifo
($mapfifo, 0600);
5451 my $openfifo = sub {
5452 open($fifofh, '>', $mapfifo) || die $!;
5455 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5462 my $rpcenv = PVE
::RPCEnvironment
::get
();
5464 my $conffile = config_file
($vmid);
5465 my $tmpfn = "$conffile.$$.tmp";
5467 # Note: $oldconf is undef if VM does not exists
5468 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5470 my $print_devmap = sub {
5471 my $virtdev_hash = {};
5473 my $cfgfn = "$tmpdir/qemu-server.conf";
5475 # we can read the config - that is already extracted
5476 my $fh = IO
::File-
>new($cfgfn, "r") ||
5477 "unable to read qemu-server.conf - $!\n";
5479 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5481 my $pve_firewall_dir = '/etc/pve/firewall';
5482 mkdir $pve_firewall_dir; # make sure the dir exists
5483 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5486 while (defined(my $line = <$fh>)) {
5487 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5488 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5489 die "archive does not contain data for drive '$virtdev'\n"
5490 if !$devinfo->{$devname};
5491 if (defined($opts->{storage
})) {
5492 $storeid = $opts->{storage
} || 'local';
5493 } elsif (!$storeid) {
5496 $format = 'raw' if !$format;
5497 $devinfo->{$devname}->{devname
} = $devname;
5498 $devinfo->{$devname}->{virtdev
} = $virtdev;
5499 $devinfo->{$devname}->{format
} = $format;
5500 $devinfo->{$devname}->{storeid
} = $storeid;
5502 # check permission on storage
5503 my $pool = $opts->{pool
}; # todo: do we need that?
5504 if ($user ne 'root@pam') {
5505 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5508 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5512 foreach my $devname (keys %$devinfo) {
5513 die "found no device mapping information for device '$devname'\n"
5514 if !$devinfo->{$devname}->{virtdev
};
5517 my $cfg = cfs_read_file
('storage.cfg');
5519 # create empty/temp config
5521 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5522 foreach_drive
($oldconf, sub {
5523 my ($ds, $drive) = @_;
5525 return if drive_is_cdrom
($drive);
5527 my $volid = $drive->{file
};
5529 return if !$volid || $volid =~ m
|^/|;
5531 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5532 return if !$path || !$owner || ($owner != $vmid);
5534 # Note: only delete disk we want to restore
5535 # other volumes will become unused
5536 if ($virtdev_hash->{$ds}) {
5537 PVE
::Storage
::vdisk_free
($cfg, $volid);
5543 foreach my $virtdev (sort keys %$virtdev_hash) {
5544 my $d = $virtdev_hash->{$virtdev};
5545 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5546 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5548 # test if requested format is supported
5549 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5550 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5551 $d->{format
} = $defFormat if !$supported;
5553 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5554 $d->{format
}, undef, $alloc_size);
5555 print STDERR
"new volume ID is '$volid'\n";
5556 $d->{volid
} = $volid;
5557 my $path = PVE
::Storage
::path
($cfg, $volid);
5559 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5561 my $write_zeros = 1;
5562 # fixme: what other storages types initialize volumes with zero?
5563 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5564 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5568 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5570 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5571 $map->{$virtdev} = $volid;
5574 $fh->seek(0, 0) || die "seek failed - $!\n";
5576 my $outfd = new IO
::File
($tmpfn, "w") ||
5577 die "unable to write config for VM $vmid\n";
5579 my $cookie = { netcount
=> 0 };
5580 while (defined(my $line = <$fh>)) {
5581 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5590 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5591 die "interrupted by signal\n";
5593 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5595 $oldtimeout = alarm($timeout);
5602 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5603 my ($dev_id, $size, $devname) = ($1, $2, $3);
5604 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5605 } elsif ($line =~ m/^CTIME: /) {
5606 # we correctly received the vma config, so we can disable
5607 # the timeout now for disk allocation (set to 10 minutes, so
5608 # that we always timeout if something goes wrong)
5611 print $fifofh "done\n";
5612 my $tmp = $oldtimeout || 0;
5613 $oldtimeout = undef;
5619 print "restore vma archive: $cmd\n";
5620 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5624 alarm($oldtimeout) if $oldtimeout;
5627 foreach my $devname (keys %$devinfo) {
5628 my $volid = $devinfo->{$devname}->{volid
};
5629 push @$vollist, $volid if $volid;
5632 my $cfg = cfs_read_file
('storage.cfg');
5633 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5641 foreach my $devname (keys %$devinfo) {
5642 my $volid = $devinfo->{$devname}->{volid
};
5645 if ($volid =~ m
|^/|) {
5646 unlink $volid || die 'unlink failed\n';
5648 PVE
::Storage
::vdisk_free
($cfg, $volid);
5650 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5652 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5659 rename($tmpfn, $conffile) ||
5660 die "unable to commit configuration file '$conffile'\n";
5662 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5664 eval { rescan
($vmid, 1); };
5668 sub restore_tar_archive
{
5669 my ($archive, $vmid, $user, $opts) = @_;
5671 if ($archive ne '-') {
5672 my $firstfile = tar_archive_read_firstfile
($archive);
5673 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5674 if $firstfile ne 'qemu-server.conf';
5677 my $storecfg = cfs_read_file
('storage.cfg');
5679 # destroy existing data - keep empty config
5680 my $vmcfgfn = config_file
($vmid);
5681 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5683 my $tocmd = "/usr/lib/qemu-server/qmextract";
5685 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5686 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5687 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5688 $tocmd .= ' --info' if $opts->{info
};
5690 # tar option "xf" does not autodetect compression when read from STDIN,
5691 # so we pipe to zcat
5692 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5693 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5695 my $tmpdir = "/var/tmp/vzdumptmp$$";
5698 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5699 local $ENV{VZDUMP_VMID
} = $vmid;
5700 local $ENV{VZDUMP_USER
} = $user;
5702 my $conffile = config_file
($vmid);
5703 my $tmpfn = "$conffile.$$.tmp";
5705 # disable interrupts (always do cleanups)
5706 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5707 print STDERR
"got interrupt - ignored\n";
5712 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5713 die "interrupted by signal\n";
5716 if ($archive eq '-') {
5717 print "extracting archive from STDIN\n";
5718 run_command
($cmd, input
=> "<&STDIN");
5720 print "extracting archive '$archive'\n";
5724 return if $opts->{info
};
5728 my $statfile = "$tmpdir/qmrestore.stat";
5729 if (my $fd = IO
::File-
>new($statfile, "r")) {
5730 while (defined (my $line = <$fd>)) {
5731 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5732 $map->{$1} = $2 if $1;
5734 print STDERR
"unable to parse line in statfile - $line\n";
5740 my $confsrc = "$tmpdir/qemu-server.conf";
5742 my $srcfd = new IO
::File
($confsrc, "r") ||
5743 die "unable to open file '$confsrc'\n";
5745 my $outfd = new IO
::File
($tmpfn, "w") ||
5746 die "unable to write config for VM $vmid\n";
5748 my $cookie = { netcount
=> 0 };
5749 while (defined (my $line = <$srcfd>)) {
5750 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5762 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5769 rename $tmpfn, $conffile ||
5770 die "unable to commit configuration file '$conffile'\n";
5772 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5774 eval { rescan
($vmid, 1); };
5779 # Internal snapshots
5781 # NOTE: Snapshot create/delete involves several non-atomic
5782 # action, and can take a long time.
5783 # So we try to avoid locking the file and use 'lock' variable
5784 # inside the config file instead.
5786 my $snapshot_copy_config = sub {
5787 my ($source, $dest) = @_;
5789 foreach my $k (keys %$source) {
5790 next if $k eq 'snapshots';
5791 next if $k eq 'snapstate';
5792 next if $k eq 'snaptime';
5793 next if $k eq 'vmstate';
5794 next if $k eq 'lock';
5795 next if $k eq 'digest';
5796 next if $k eq 'description';
5797 next if $k =~ m/^unused\d+$/;
5799 $dest->{$k} = $source->{$k};
5803 my $snapshot_apply_config = sub {
5804 my ($conf, $snap) = @_;
5806 # copy snapshot list
5808 snapshots
=> $conf->{snapshots
},
5811 # keep description and list of unused disks
5812 foreach my $k (keys %$conf) {
5813 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5814 $newconf->{$k} = $conf->{$k};
5817 &$snapshot_copy_config($snap, $newconf);
5822 sub foreach_writable_storage
{
5823 my ($conf, $func) = @_;
5827 foreach my $ds (keys %$conf) {
5828 next if !valid_drivename
($ds);
5830 my $drive = parse_drive
($ds, $conf->{$ds});
5832 next if drive_is_cdrom
($drive);
5834 my $volid = $drive->{file
};
5836 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5837 $sidhash->{$sid} = $sid if $sid;
5840 foreach my $sid (sort keys %$sidhash) {
5845 my $alloc_vmstate_volid = sub {
5846 my ($storecfg, $vmid, $conf, $snapname) = @_;
5848 # Note: we try to be smart when selecting a $target storage
5852 # search shared storage first
5853 foreach_writable_storage
($conf, sub {
5855 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5856 return if !$scfg->{shared
};
5858 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5862 # now search local storage
5863 foreach_writable_storage
($conf, sub {
5865 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5866 return if $scfg->{shared
};
5868 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5872 $target = 'local' if !$target;
5874 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5875 # we abort live save after $conf->{memory}, so we need at max twice that space
5876 my $size = $conf->{memory
}*2 + $driver_state_size;
5878 my $name = "vm-$vmid-state-$snapname";
5879 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5880 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5881 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5886 my $snapshot_prepare = sub {
5887 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5891 my $updatefn = sub {
5893 my $conf = load_config
($vmid);
5895 die "you can't take a snapshot if it's a template\n"
5896 if is_template
($conf);
5900 $conf->{lock} = 'snapshot';
5902 die "snapshot name '$snapname' already used\n"
5903 if defined($conf->{snapshots
}->{$snapname});
5905 my $storecfg = PVE
::Storage
::config
();
5906 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5908 $snap = $conf->{snapshots
}->{$snapname} = {};
5910 if ($save_vmstate && check_running
($vmid)) {
5911 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5914 &$snapshot_copy_config($conf, $snap);
5916 $snap->{snapstate
} = "prepare";
5917 $snap->{snaptime
} = time();
5918 $snap->{description
} = $comment if $comment;
5920 # always overwrite machine if we save vmstate. This makes sure we
5921 # can restore it later using correct machine type
5922 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5924 update_config_nolock
($vmid, $conf, 1);
5927 lock_config
($vmid, $updatefn);
5932 my $snapshot_commit = sub {
5933 my ($vmid, $snapname) = @_;
5935 my $updatefn = sub {
5937 my $conf = load_config
($vmid);
5939 die "missing snapshot lock\n"
5940 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5942 my $has_machine_config = defined($conf->{machine
});
5944 my $snap = $conf->{snapshots
}->{$snapname};
5946 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5948 die "wrong snapshot state\n"
5949 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5951 delete $snap->{snapstate
};
5952 delete $conf->{lock};
5954 my $newconf = &$snapshot_apply_config($conf, $snap);
5956 delete $newconf->{machine
} if !$has_machine_config;
5958 $newconf->{parent
} = $snapname;
5960 update_config_nolock
($vmid, $newconf, 1);
5963 lock_config
($vmid, $updatefn);
5966 sub snapshot_rollback
{
5967 my ($vmid, $snapname) = @_;
5971 my $storecfg = PVE
::Storage
::config
();
5973 my $conf = load_config
($vmid);
5975 my $get_snapshot_config = sub {
5977 die "you can't rollback if vm is a template\n" if is_template
($conf);
5979 my $res = $conf->{snapshots
}->{$snapname};
5981 die "snapshot '$snapname' does not exist\n" if !defined($res);
5986 my $snap = &$get_snapshot_config();
5988 foreach_drive
($snap, sub {
5989 my ($ds, $drive) = @_;
5991 return if drive_is_cdrom
($drive);
5993 my $volid = $drive->{file
};
5995 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5998 my $updatefn = sub {
6000 $conf = load_config
($vmid);
6002 $snap = &$get_snapshot_config();
6004 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
6005 if $snap->{snapstate
};
6009 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
6012 die "unable to rollback vm $vmid: vm is running\n"
6013 if check_running
($vmid);
6016 $conf->{lock} = 'rollback';
6018 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
6019 delete $conf->{lock};
6025 my $has_machine_config = defined($conf->{machine
});
6027 # copy snapshot config to current config
6028 $conf = &$snapshot_apply_config($conf, $snap);
6029 $conf->{parent
} = $snapname;
6031 # Note: old code did not store 'machine', so we try to be smart
6032 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
6033 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
6034 # we remove the 'machine' configuration if not explicitly specified
6035 # in the original config.
6036 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
6039 update_config_nolock
($vmid, $conf, 1);
6041 if (!$prepare && $snap->{vmstate
}) {
6042 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6043 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
6047 lock_config
($vmid, $updatefn);
6049 foreach_drive
($snap, sub {
6050 my ($ds, $drive) = @_;
6052 return if drive_is_cdrom
($drive);
6054 my $volid = $drive->{file
};
6055 my $device = "drive-$ds";
6057 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
6061 lock_config
($vmid, $updatefn);
6064 my $savevm_wait = sub {
6068 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6069 if (!$stat->{status
}) {
6070 die "savevm not active\n";
6071 } elsif ($stat->{status
} eq 'active') {
6074 } elsif ($stat->{status
} eq 'completed') {
6077 die "query-savevm returned status '$stat->{status}'\n";
6082 sub do_snapshots_with_qemu
{
6083 my ($storecfg, $volid) = @_;
6085 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6087 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6088 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6092 if ($volid =~ m/\.(qcow2|qed)$/){
6099 sub snapshot_create
{
6100 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
6102 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
6104 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
6106 my $config = load_config
($vmid);
6108 my $running = check_running
($vmid);
6110 my $freezefs = $running && $config->{agent
};
6111 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
6116 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6117 warn "guest-fsfreeze-freeze problems - $@" if $@;
6121 # create internal snapshots of all drives
6123 my $storecfg = PVE
::Storage
::config
();
6126 if ($snap->{vmstate
}) {
6127 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6128 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
6129 &$savevm_wait($vmid);
6131 vm_mon_cmd
($vmid, "savevm-start");
6135 foreach_drive
($snap, sub {
6136 my ($ds, $drive) = @_;
6138 return if drive_is_cdrom
($drive);
6140 my $volid = $drive->{file
};
6141 my $device = "drive-$ds";
6143 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
6144 $drivehash->{$ds} = 1;
6150 eval { vm_mon_cmd
($vmid, "savevm-end") };
6154 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6155 warn "guest-fsfreeze-thaw problems - $@" if $@;
6158 # savevm-end is async, we need to wait
6160 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6161 if (!$stat->{bytes
}) {
6164 print "savevm not yet finished\n";
6172 warn "snapshot create failed: starting cleanup\n";
6173 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6178 &$snapshot_commit($vmid, $snapname);
6181 # Note: $drivehash is only set when called from snapshot_create.
6182 sub snapshot_delete
{
6183 my ($vmid, $snapname, $force, $drivehash) = @_;
6190 my $unlink_parent = sub {
6191 my ($confref, $new_parent) = @_;
6193 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6195 $confref->{parent
} = $new_parent;
6197 delete $confref->{parent
};
6202 my $updatefn = sub {
6203 my ($remove_drive) = @_;
6205 my $conf = load_config
($vmid);
6209 die "you can't delete a snapshot if vm is a template\n"
6210 if is_template
($conf);
6213 $snap = $conf->{snapshots
}->{$snapname};
6215 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6217 # remove parent refs
6219 &$unlink_parent($conf, $snap->{parent
});
6220 foreach my $sn (keys %{$conf->{snapshots
}}) {
6221 next if $sn eq $snapname;
6222 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6226 if ($remove_drive) {
6227 if ($remove_drive eq 'vmstate') {
6228 delete $snap->{$remove_drive};
6230 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6231 my $volid = $drive->{file
};
6232 delete $snap->{$remove_drive};
6233 add_unused_volume
($conf, $volid);
6238 $snap->{snapstate
} = 'delete';
6240 delete $conf->{snapshots
}->{$snapname};
6241 delete $conf->{lock} if $drivehash;
6242 foreach my $volid (@$unused) {
6243 add_unused_volume
($conf, $volid);
6247 update_config_nolock
($vmid, $conf, 1);
6250 lock_config
($vmid, $updatefn);
6252 # now remove vmstate file
6254 my $storecfg = PVE
::Storage
::config
();
6256 if ($snap->{vmstate
}) {
6257 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6259 die $err if !$force;
6262 # save changes (remove vmstate from snapshot)
6263 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6266 # now remove all internal snapshots
6267 foreach_drive
($snap, sub {
6268 my ($ds, $drive) = @_;
6270 return if drive_is_cdrom
($drive);
6272 my $volid = $drive->{file
};
6273 my $device = "drive-$ds";
6275 if (!$drivehash || $drivehash->{$ds}) {
6276 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6278 die $err if !$force;
6283 # save changes (remove drive fron snapshot)
6284 lock_config
($vmid, $updatefn, $ds) if !$force;
6285 push @$unused, $volid;
6288 # now cleanup config
6290 lock_config
($vmid, $updatefn);
6294 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6297 foreach_drive
($conf, sub {
6298 my ($ds, $drive) = @_;
6300 return if drive_is_cdrom
($drive);
6301 my $volid = $drive->{file
};
6302 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6305 return $err ?
0 : 1;
6308 sub template_create
{
6309 my ($vmid, $conf, $disk) = @_;
6311 my $storecfg = PVE
::Storage
::config
();
6313 foreach_drive
($conf, sub {
6314 my ($ds, $drive) = @_;
6316 return if drive_is_cdrom
($drive);
6317 return if $disk && $ds ne $disk;
6319 my $volid = $drive->{file
};
6320 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6322 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6323 $drive->{file
} = $voliddst;
6324 $conf->{$ds} = print_drive
($vmid, $drive);
6325 update_config_nolock
($vmid, $conf, 1);
6332 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6335 sub qemu_img_convert
{
6336 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6338 my $storecfg = PVE
::Storage
::config
();
6339 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6340 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6342 if ($src_storeid && $dst_storeid) {
6344 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6346 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6347 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6349 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6350 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6352 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6353 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6356 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6357 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6358 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6362 if($line =~ m/\((\S+)\/100\
%\)/){
6364 my $transferred = int($size * $percent / 100);
6365 my $remaining = $size - $transferred;
6367 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6372 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6374 die "copy failed: $err" if $err;
6378 sub qemu_img_format
{
6379 my ($scfg, $volname) = @_;
6381 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6388 sub qemu_drive_mirror
{
6389 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6391 my $storecfg = PVE
::Storage
::config
();
6392 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6394 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6396 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6398 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6400 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6401 $opts->{format
} = $format if $format;
6403 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6406 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6408 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6409 my $stat = @$stats[0];
6410 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6411 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6413 my $busy = $stat->{busy
};
6414 my $ready = $stat->{ready
};
6416 if (my $total = $stat->{len
}) {
6417 my $transferred = $stat->{offset
} || 0;
6418 my $remaining = $total - $transferred;
6419 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6421 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6425 if ($stat->{ready
} eq 'true') {
6427 last if $vmiddst != $vmid;
6429 # try to switch the disk if source and destination are on the same guest
6430 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6432 die $@ if $@ !~ m/cannot be completed/;
6441 my $cancel_job = sub {
6442 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6444 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6445 my $stat = @$stats[0];
6452 eval { &$cancel_job(); };
6453 die "mirroring error: $err";
6456 if ($vmiddst != $vmid) {
6457 # if we clone a disk for a new target vm, we don't switch the disk
6458 &$cancel_job(); # so we call block-job-cancel
6463 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6464 $newvmid, $storage, $format, $full, $newvollist) = @_;
6469 print "create linked clone of drive $drivename ($drive->{file})\n";
6470 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6471 push @$newvollist, $newvolid;
6473 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6474 $storeid = $storage if $storage;
6476 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6478 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6479 $format = qemu_img_format
($scfg, $volname);
6482 # test if requested format is supported - else use default
6483 my $supported = grep { $_ eq $format } @$validFormats;
6484 $format = $defFormat if !$supported;
6486 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6488 print "create full clone of drive $drivename ($drive->{file})\n";
6489 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6490 push @$newvollist, $newvolid;
6492 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6494 if (!$running || $snapname) {
6495 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6497 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6501 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6504 $disk->{format
} = undef;
6505 $disk->{file
} = $newvolid;
6506 $disk->{size
} = $size;
6511 # this only works if VM is running
6512 sub get_current_qemu_machine
{
6515 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6516 my $res = vm_qmp_command
($vmid, $cmd);
6518 my ($current, $default);
6519 foreach my $e (@$res) {
6520 $default = $e->{name
} if $e->{'is-default'};
6521 $current = $e->{name
} if $e->{'is-current'};
6524 # fallback to the default machine if current is not supported by qemu
6525 return $current || $default || 'pc';
6528 sub qemu_machine_feature_enabled
{
6529 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6534 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6536 $current_major = $3;
6537 $current_minor = $4;
6539 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6541 $current_major = $1;
6542 $current_minor = $2;
6545 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6550 sub qemu_machine_pxe
{
6551 my ($vmid, $conf, $machine) = @_;
6553 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6555 foreach my $opt (keys %$conf) {
6556 next if $opt !~ m/^net(\d+)$/;
6557 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6559 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6560 return $machine.".pxe" if $romfile =~ m/pxe/;
6566 sub qemu_use_old_bios_files
{
6567 my ($machine_type) = @_;
6569 return if !$machine_type;
6571 my $use_old_bios_files = undef;
6573 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6575 $use_old_bios_files = 1;
6577 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6578 # load new efi bios files on migration. So this hack is required to allow
6579 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6580 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6581 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6584 return ($use_old_bios_files, $machine_type);
6591 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6592 my (undef, $id, $function) = @_;
6593 my $res = { id
=> $id, function
=> $function};
6594 push @{$devices->{$id}}, $res;
6600 sub vm_iothreads_list
{
6603 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6606 foreach my $iothread (@$res) {
6607 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6614 my ($conf, $drive) = @_;
6618 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6620 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6626 my $controller = int($drive->{index} / $maxdev);
6627 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6629 return ($maxdev, $controller, $controller_prefix);
6632 # bash completion helper
6634 sub complete_backup_archives
{
6635 my ($cmdname, $pname, $cvalue) = @_;
6637 my $cfg = PVE
::Storage
::config
();
6641 if ($cvalue =~ m/^([^:]+):/) {
6645 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6648 foreach my $id (keys %$data) {
6649 foreach my $item (@{$data->{$id}}) {
6650 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6651 push @$res, $item->{volid
} if defined($item->{volid
});
6658 my $complete_vmid_full = sub {
6661 my $idlist = vmstatus
();
6665 foreach my $id (keys %$idlist) {
6666 my $d = $idlist->{$id};
6667 if (defined($running)) {
6668 next if $d->{template
};
6669 next if $running && $d->{status
} ne 'running';
6670 next if !$running && $d->{status
} eq 'running';
6679 return &$complete_vmid_full();
6682 sub complete_vmid_stopped
{
6683 return &$complete_vmid_full(0);
6686 sub complete_vmid_running
{
6687 return &$complete_vmid_full(1);
6690 sub complete_storage
{
6692 my $cfg = PVE
::Storage
::config
();
6693 my $ids = $cfg->{ids
};
6696 foreach my $sid (keys %$ids) {
6697 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6698 next if !$ids->{$sid}->{content
}->{images
};