1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
36 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
38 # Note about locking: we use flock on the config file protect
39 # against concurent actions.
40 # Aditionaly, we have a 'lock' setting in the config file. This
41 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
42 # allowed when such lock is set. But you can ignore this kind of
43 # lock with the --skiplock flag.
45 cfs_register_file
('/qemu-server/',
49 PVE
::JSONSchema
::register_standard_option
('skiplock', {
50 description
=> "Ignore locks - only root is allowed to use this option.",
55 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
56 description
=> "Some command save/restore state from this location.",
62 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
63 description
=> "The name of the snapshot.",
64 type
=> 'string', format
=> 'pve-configid',
68 #no warnings 'redefine';
70 unless(defined(&_VZSYSCALLS_H_
)) {
71 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
72 require 'sys/syscall.ph';
73 if(defined(&__x86_64__
)) {
74 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
75 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
76 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
77 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
78 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
79 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
80 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
81 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
83 elsif(defined( &__i386__
) ) {
84 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
85 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
86 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
87 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
88 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
89 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
90 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
91 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
93 die("no fairsched syscall for this arch");
95 require 'asm/ioctl.ph';
96 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
100 my ($parent, $weight, $desired) = @_;
102 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
105 sub fairsched_rmnod
{
108 return syscall(&__NR_fairsched_rmnod
, int($id));
112 my ($pid, $newid) = @_;
114 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
117 sub fairsched_vcpus
{
118 my ($id, $vcpus) = @_;
120 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
124 my ($id, $op, $rate) = @_;
126 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
129 use constant FAIRSCHED_SET_RATE
=> 0;
130 use constant FAIRSCHED_DROP_RATE
=> 1;
131 use constant FAIRSCHED_GET_RATE
=> 2;
133 sub fairsched_cpulimit
{
134 my ($id, $limit) = @_;
136 my $cpulim1024 = int($limit * 1024 / 100);
137 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
139 return fairsched_rate
($id, $op, $cpulim1024);
142 my $nodename = PVE
::INotify
::nodename
();
144 mkdir "/etc/pve/nodes/$nodename";
145 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
148 my $var_run_tmpdir = "/var/run/qemu-server";
149 mkdir $var_run_tmpdir;
151 my $lock_dir = "/var/lock/qemu-server";
154 my $pcisysfs = "/sys/bus/pci";
160 description
=> "Specifies whether a VM will be started during system bootup.",
166 description
=> "Automatic restart after crash (currently ignored).",
171 type
=> 'string', format
=> 'pve-hotplug-features',
172 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'.",
173 default => 'network,disk,usb',
178 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
184 description
=> "Lock/unlock the VM.",
185 enum
=> [qw(migrate backup snapshot rollback)],
190 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
197 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.",
205 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
212 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
218 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",
226 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
227 enum
=> PVE
::Tools
::kvmkeymaplist
(),
232 type
=> 'string', format
=> 'dns-name',
233 description
=> "Set a name for the VM. Only used on the configuration web interface.",
238 description
=> "scsi controller model",
239 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
245 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
250 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
251 description
=> <<EODESC,
252 Used to enable special optimization/features for specific
255 other => unspecified OS
256 wxp => Microsoft Windows XP
257 w2k => Microsoft Windows 2000
258 w2k3 => Microsoft Windows 2003
259 w2k8 => Microsoft Windows 2008
260 wvista => Microsoft Windows Vista
261 win7 => Microsoft Windows 7
262 win8 => Microsoft Windows 8/2012
263 l24 => Linux 2.4 Kernel
264 l26 => Linux 2.6/3.X Kernel
265 solaris => solaris/opensolaris/openindiania kernel
267 other|l24|l26|solaris ... no special behaviour
268 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
274 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
275 pattern
=> '[acdn]{1,4}',
280 type
=> 'string', format
=> 'pve-qm-bootdisk',
281 description
=> "Enable booting from specified disk.",
282 pattern
=> '(ide|sata|scsi|virtio)\d+',
287 description
=> "The number of CPUs. Please use option -sockets instead.",
294 description
=> "The number of CPU sockets.",
301 description
=> "The number of cores per socket.",
308 description
=> "Enable/disable Numa.",
314 description
=> "Number of hotplugged vcpus.",
321 description
=> "Enable/disable ACPI.",
327 description
=> "Enable/disable Qemu GuestAgent.",
333 description
=> "Enable/disable KVM hardware virtualization.",
339 description
=> "Enable/disable time drift fix.",
345 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
350 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
355 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.",
356 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
360 type
=> 'string', format
=> 'pve-qm-watchdog',
361 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
362 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)",
367 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
368 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'.",
369 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
372 startup
=> get_standard_option
('pve-startup-order'),
376 description
=> "Enable/disable Template.",
382 description
=> <<EODESCR,
383 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
385 args: -no-reboot -no-hpet
392 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).",
397 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
401 migrate_downtime
=> {
404 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
410 type
=> 'string', format
=> 'pve-qm-drive',
411 typetext
=> 'volume',
412 description
=> "This is an alias for option -ide2",
416 description
=> "Emulated CPU type.",
418 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
421 parent
=> get_standard_option
('pve-snapshot-name', {
423 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
427 description
=> "Timestamp for snapshots.",
433 type
=> 'string', format
=> 'pve-volume-id',
434 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
437 description
=> "Specific the Qemu machine type.",
439 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
444 description
=> "Specify SMBIOS type 1 fields.",
445 type
=> 'string', format
=> 'pve-qm-smbios1',
446 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
452 # what about other qemu settings ?
454 #machine => 'string',
467 ##soundhw => 'string',
469 while (my ($k, $v) = each %$confdesc) {
470 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
473 my $MAX_IDE_DISKS = 4;
474 my $MAX_SCSI_DISKS = 14;
475 my $MAX_VIRTIO_DISKS = 16;
476 my $MAX_SATA_DISKS = 6;
477 my $MAX_USB_DEVICES = 5;
479 my $MAX_UNUSED_DISKS = 8;
480 my $MAX_HOSTPCI_DEVICES = 4;
481 my $MAX_SERIAL_PORTS = 4;
482 my $MAX_PARALLEL_PORTS = 3;
484 my $MAX_MEM = 4194304;
485 my $STATICMEM = 1024;
489 type
=> 'string', format
=> 'pve-qm-numanode',
490 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
491 description
=> "numa topology",
493 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
495 for (my $i = 0; $i < $MAX_NUMA; $i++) {
496 $confdesc->{"numa$i"} = $numadesc;
499 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
500 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
501 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
502 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
506 type
=> 'string', format
=> 'pve-qm-net',
507 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
508 description
=> <<EODESCR,
509 Specify network devices.
511 MODEL is one of: $nic_model_list_txt
513 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
514 automatically generated if not specified.
516 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
518 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'.
520 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
526 The DHCP server assign addresses to the guest starting from 10.0.2.15.
530 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
532 for (my $i = 0; $i < $MAX_NETS; $i++) {
533 $confdesc->{"net$i"} = $netdesc;
540 type
=> 'string', format
=> 'pve-qm-drive',
541 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
542 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
544 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
548 type
=> 'string', format
=> 'pve-qm-drive',
549 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,queues=<nbqueues>]',
550 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
556 type
=> 'string', format
=> 'pve-qm-drive',
557 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
558 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
560 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
564 type
=> 'string', format
=> 'pve-qm-drive',
565 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on]',
566 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
568 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
572 type
=> 'string', format
=> 'pve-qm-usb-device',
573 typetext
=> 'host=HOSTUSBDEVICE|spice',
574 description
=> <<EODESCR,
575 Configure an USB device (n is 0 to 4). This can be used to
576 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
578 'bus-port(.port)*' (decimal numbers) or
579 'vendor_id:product_id' (hexadeciaml numbers)
581 You can use the 'lsusb -t' command to list existing usb devices.
583 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
585 The value 'spice' can be used to add a usb redirection devices for spice.
589 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
593 type
=> 'string', format
=> 'pve-qm-hostpci',
594 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
595 description
=> <<EODESCR,
596 Map host pci devices. HOSTPCIDEVICE syntax is:
598 'bus:dev.func' (hexadecimal numbers)
600 You can us the 'lspci' command to list existing pci devices.
602 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
604 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
606 Experimental: user reported problems with this option.
609 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
614 pattern
=> '(/dev/.+|socket)',
615 description
=> <<EODESCR,
616 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).
618 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
620 Experimental: user reported problems with this option.
627 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
628 description
=> <<EODESCR,
629 Map host parallel devices (n is 0 to 2).
631 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
633 Experimental: user reported problems with this option.
637 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
638 $confdesc->{"parallel$i"} = $paralleldesc;
641 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
642 $confdesc->{"serial$i"} = $serialdesc;
645 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
646 $confdesc->{"hostpci$i"} = $hostpcidesc;
649 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
650 $drivename_hash->{"ide$i"} = 1;
651 $confdesc->{"ide$i"} = $idedesc;
654 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
655 $drivename_hash->{"sata$i"} = 1;
656 $confdesc->{"sata$i"} = $satadesc;
659 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
660 $drivename_hash->{"scsi$i"} = 1;
661 $confdesc->{"scsi$i"} = $scsidesc ;
664 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
665 $drivename_hash->{"virtio$i"} = 1;
666 $confdesc->{"virtio$i"} = $virtiodesc;
669 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
670 $confdesc->{"usb$i"} = $usbdesc;
675 type
=> 'string', format
=> 'pve-volume-id',
676 description
=> "Reference to unused volumes.",
679 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
680 $confdesc->{"unused$i"} = $unuseddesc;
683 my $kvm_api_version = 0;
687 return $kvm_api_version if $kvm_api_version;
689 my $fh = IO
::File-
>new("</dev/kvm") ||
692 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
693 $kvm_api_version = $v;
698 return $kvm_api_version;
701 my $kvm_user_version;
703 sub kvm_user_version
{
705 return $kvm_user_version if $kvm_user_version;
707 $kvm_user_version = 'unknown';
709 my $tmp = `kvm -help 2>/dev/null`;
711 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
712 $kvm_user_version = $2;
715 return $kvm_user_version;
719 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
722 # order is important - used to autoselect boot disk
723 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
724 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
725 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
726 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
729 sub valid_drivename
{
732 return defined($drivename_hash->{$dev});
737 return defined($confdesc->{$key});
741 return $nic_model_list;
744 sub os_list_description
{
749 w2k
=> 'Windows 2000',
750 w2k3
=>, 'Windows 2003',
751 w2k8
=> 'Windows 2008',
752 wvista
=> 'Windows Vista',
754 win8
=> 'Windows 8/2012',
764 return $cdrom_path if $cdrom_path;
766 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
767 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
768 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
772 my ($storecfg, $vmid, $cdrom) = @_;
774 if ($cdrom eq 'cdrom') {
775 return get_cdrom_path
();
776 } elsif ($cdrom eq 'none') {
778 } elsif ($cdrom =~ m
|^/|) {
781 return PVE
::Storage
::path
($storecfg, $cdrom);
785 # try to convert old style file names to volume IDs
786 sub filename_to_volume_id
{
787 my ($vmid, $file, $media) = @_;
789 if (!($file eq 'none' || $file eq 'cdrom' ||
790 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
792 return undef if $file =~ m
|/|;
794 if ($media && $media eq 'cdrom') {
795 $file = "local:iso/$file";
797 $file = "local:$vmid/$file";
804 sub verify_media_type
{
805 my ($opt, $vtype, $media) = @_;
810 if ($media eq 'disk') {
812 } elsif ($media eq 'cdrom') {
815 die "internal error";
818 return if ($vtype eq $etype);
820 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
823 sub cleanup_drive_path
{
824 my ($opt, $storecfg, $drive) = @_;
826 # try to convert filesystem paths to volume IDs
828 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
829 ($drive->{file
} !~ m
|^/dev/.+|) &&
830 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
831 ($drive->{file
} !~ m/^\d+$/)) {
832 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
833 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
834 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
835 verify_media_type
($opt, $vtype, $drive->{media
});
836 $drive->{file
} = $volid;
839 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
842 sub create_conf_nolock
{
843 my ($vmid, $settings) = @_;
845 my $filename = config_file
($vmid);
847 die "configuration file '$filename' already exists\n" if -f
$filename;
849 my $defaults = load_defaults
();
851 $settings->{name
} = "vm$vmid" if !$settings->{name
};
852 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
855 foreach my $opt (keys %$settings) {
856 next if !$confdesc->{$opt};
858 my $value = $settings->{$opt};
861 $data .= "$opt: $value\n";
864 PVE
::Tools
::file_set_contents
($filename, $data);
867 sub parse_hotplug_features
{
872 return $res if $data eq '0';
874 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
876 foreach my $feature (PVE
::Tools
::split_list
($data)) {
877 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
880 warn "ignoring unknown hotplug feature '$feature'\n";
886 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
887 sub pve_verify_hotplug_features
{
888 my ($value, $noerr) = @_;
890 return $value if parse_hotplug_features
($value);
892 return undef if $noerr;
894 die "unable to parse hotplug option\n";
897 my $parse_size = sub {
900 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
901 my ($size, $unit) = ($1, $3);
904 $size = $size * 1024;
905 } elsif ($unit eq 'M') {
906 $size = $size * 1024 * 1024;
907 } elsif ($unit eq 'G') {
908 $size = $size * 1024 * 1024 * 1024;
914 my $format_size = sub {
919 my $kb = int($size/1024);
920 return $size if $kb*1024 != $size;
922 my $mb = int($kb/1024);
923 return "${kb}K" if $mb*1024 != $kb;
925 my $gb = int($mb/1024);
926 return "${mb}M" if $gb*1024 != $mb;
931 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
932 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
933 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
934 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
937 my ($key, $data) = @_;
941 # $key may be undefined - used to verify JSON parameters
942 if (!defined($key)) {
943 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
945 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
946 $res->{interface
} = $1;
952 foreach my $p (split (/,/, $data)) {
953 next if $p =~ m/^\s*$/;
955 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues)=(.+)$/) {
956 my ($k, $v) = ($1, $2);
958 $k = 'file' if $k eq 'volume';
960 return undef if defined $res->{$k};
962 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
963 return undef if !$v || $v !~ m/^\d+/;
965 $v = sprintf("%.3f", $v / (1024*1024));
969 if (!$res->{file
} && $p !~ m/=/) {
977 return undef if !$res->{file
};
979 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
983 return undef if $res->{cache
} &&
984 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
985 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
986 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
987 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
988 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
989 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
990 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
991 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
992 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
993 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
994 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
995 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
996 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
997 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
998 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
1000 return undef if $res->{mbps_rd
} && $res->{mbps
};
1001 return undef if $res->{mbps_wr
} && $res->{mbps
};
1003 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
1004 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
1005 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
1006 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
1007 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
1008 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
1010 return undef if $res->{iops_rd
} && $res->{iops
};
1011 return undef if $res->{iops_wr
} && $res->{iops
};
1014 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
1015 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
1016 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
1017 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
1018 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
1019 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
1023 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
1026 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1027 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1028 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1029 return undef if $res->{interface
} eq 'virtio';
1032 # rerror does not work with scsi drives
1033 if ($res->{rerror
}) {
1034 return undef if $res->{interface
} eq 'scsi';
1040 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);
1043 my ($vmid, $drive) = @_;
1046 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
1047 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1050 if ($drive->{size
}) {
1051 $opts .= ",size=" . &$format_size($drive->{size
});
1054 return "$drive->{file}$opts";
1058 my($fh, $noerr) = @_;
1061 my $SG_GET_VERSION_NUM = 0x2282;
1063 my $versionbuf = "\x00" x
8;
1064 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1066 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1069 my $version = unpack("I", $versionbuf);
1070 if ($version < 30000) {
1071 die "scsi generic interface too old\n" if !$noerr;
1075 my $buf = "\x00" x
36;
1076 my $sensebuf = "\x00" x
8;
1077 my $cmd = pack("C x3 C x1", 0x12, 36);
1079 # see /usr/include/scsi/sg.h
1080 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";
1082 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1083 length($sensebuf), 0, length($buf), $buf,
1084 $cmd, $sensebuf, 6000);
1086 $ret = ioctl($fh, $SG_IO, $packet);
1088 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1092 my @res = unpack($sg_io_hdr_t, $packet);
1093 if ($res[17] || $res[18]) {
1094 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1099 (my $byte0, my $byte1, $res->{vendor
},
1100 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1102 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1103 $res->{type
} = $byte0 & 31;
1111 my $fh = IO
::File-
>new("+<$path") || return undef;
1112 my $res = scsi_inquiry
($fh, 1);
1118 sub machine_type_is_q35
{
1121 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1124 sub print_tabletdevice_full
{
1127 my $q35 = machine_type_is_q35
($conf);
1129 # we use uhci for old VMs because tablet driver was buggy in older qemu
1130 my $usbbus = $q35 ?
"ehci" : "uhci";
1132 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1135 sub print_drivedevice_full
{
1136 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1141 if ($drive->{interface
} eq 'virtio') {
1142 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1143 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1144 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1145 } elsif ($drive->{interface
} eq 'scsi') {
1147 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1148 my $unit = $drive->{index} % $maxdev;
1149 my $devicetype = 'hd';
1151 if (drive_is_cdrom
($drive)) {
1154 if ($drive->{file
} =~ m
|^/|) {
1155 $path = $drive->{file
};
1157 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1160 if($path =~ m/^iscsi\:\/\
//){
1161 $devicetype = 'generic';
1163 if (my $info = path_is_scsi
($path)) {
1164 if ($info->{type
} == 0) {
1165 $devicetype = 'block';
1166 } elsif ($info->{type
} == 1) { # tape
1167 $devicetype = 'generic';
1173 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1174 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1176 $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}";
1179 } elsif ($drive->{interface
} eq 'ide'){
1181 my $controller = int($drive->{index} / $maxdev);
1182 my $unit = $drive->{index} % $maxdev;
1183 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1185 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1186 } elsif ($drive->{interface
} eq 'sata'){
1187 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1188 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1189 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1190 } elsif ($drive->{interface
} eq 'usb') {
1192 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1194 die "unsupported interface type";
1197 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1202 sub get_initiator_name
{
1205 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1206 while (defined(my $line = <$fh>)) {
1207 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1216 sub print_drive_full
{
1217 my ($storecfg, $vmid, $drive) = @_;
1220 foreach my $o (@qemu_drive_options) {
1221 next if $o eq 'bootindex';
1222 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1225 foreach my $o (qw(bps bps_rd bps_wr)) {
1226 my $v = $drive->{"m$o"};
1227 $opts .= ",$o=" . int($v*1024*1024) if $v;
1230 # aio native works only with O_DIRECT
1231 if (!$drive->{aio
}) {
1232 if(!$drive->{cache
} || $drive->{cache
} eq 'none' || $drive->{cache
} eq 'directsync') {
1233 $opts .= ",aio=native";
1235 $opts .= ",aio=threads";
1241 my $volid = $drive->{file
};
1242 if (drive_is_cdrom
($drive)) {
1243 $path = get_iso_path
($storecfg, $vmid, $volid);
1245 if ($volid =~ m
|^/|) {
1248 $path = PVE
::Storage
::path
($storecfg, $volid);
1252 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1254 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1255 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1257 my $pathinfo = $path ?
"file=$path," : '';
1259 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1262 sub print_netdevice_full
{
1263 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1265 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1267 my $device = $net->{model
};
1268 if ($net->{model
} eq 'virtio') {
1269 $device = 'virtio-net-pci';
1272 my $pciaddr = print_pci_addr
("$netid", $bridges);
1273 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1274 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1275 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1276 my $vectors = $net->{queues
} * 2 + 2;
1277 $tmpstr .= ",vectors=$vectors,mq=on";
1279 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1283 sub print_netdev_full
{
1284 my ($vmid, $conf, $net, $netid) = @_;
1287 if ($netid =~ m/^net(\d+)$/) {
1291 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1293 my $ifname = "tap${vmid}i$i";
1295 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1296 die "interface name '$ifname' is too long (max 15 character)\n"
1297 if length($ifname) >= 16;
1299 my $vhostparam = '';
1300 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1302 my $vmname = $conf->{name
} || "vm$vmid";
1306 if ($net->{bridge
}) {
1307 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1309 $netdev = "type=user,id=$netid,hostname=$vmname";
1312 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1317 sub drive_is_cdrom
{
1320 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1329 foreach my $kvp (split(/,/, $data)) {
1331 if ($kvp =~ m/^memory=(\S+)$/) {
1332 $res->{memory
} = $1;
1333 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1334 $res->{policy
} = $1;
1335 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1336 $res->{cpus
}->{start
} = $1;
1337 $res->{cpus
}->{end
} = $3;
1338 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1339 $res->{hostnodes
}->{start
} = $1;
1340 $res->{hostnodes
}->{end
} = $3;
1352 return undef if !$value;
1355 my @list = split(/,/, $value);
1359 foreach my $kv (@list) {
1361 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1364 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1367 my $pcidevices = lspci
($2);
1368 $res->{pciid
} = $pcidevices->{$2};
1370 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1371 $res->{driver
} = $1;
1372 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1373 $res->{rombar
} = $1;
1374 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1375 $res->{'x-vga'} = $1;
1376 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1377 $res->{pcie
} = 1 if $1 == 1;
1379 warn "unknown hostpci setting '$kv'\n";
1383 return undef if !$found;
1388 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1394 foreach my $kvp (split(/,/, $data)) {
1396 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) {
1398 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1399 $res->{model
} = $model;
1400 $res->{macaddr
} = $mac;
1401 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1402 $res->{bridge
} = $1;
1403 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1404 $res->{queues
} = $1;
1405 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1407 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1409 } elsif ($kvp =~ m/^firewall=([01])$/) {
1410 $res->{firewall
} = $1;
1411 } elsif ($kvp =~ m/^link_down=([01])$/) {
1412 $res->{link_down
} = $1;
1419 return undef if !$res->{model
};
1427 my $res = "$net->{model}";
1428 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1429 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1430 $res .= ",rate=$net->{rate}" if $net->{rate
};
1431 $res .= ",tag=$net->{tag}" if $net->{tag
};
1432 $res .= ",firewall=1" if $net->{firewall
};
1433 $res .= ",link_down=1" if $net->{link_down
};
1434 $res .= ",queues=$net->{queues}" if $net->{queues
};
1439 sub add_random_macs
{
1440 my ($settings) = @_;
1442 foreach my $opt (keys %$settings) {
1443 next if $opt !~ m/^net(\d+)$/;
1444 my $net = parse_net
($settings->{$opt});
1446 $settings->{$opt} = print_net
($net);
1450 sub add_unused_volume
{
1451 my ($config, $volid) = @_;
1454 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1455 my $test = "unused$ind";
1456 if (my $vid = $config->{$test}) {
1457 return if $vid eq $volid; # do not add duplicates
1463 die "To many unused volume - please delete them first.\n" if !$key;
1465 $config->{$key} = $volid;
1470 sub vm_is_volid_owner
{
1471 my ($storecfg, $vmid, $volid) = @_;
1473 if ($volid !~ m
|^/|) {
1475 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1476 if ($owner && ($owner == $vmid)) {
1484 sub vmconfig_delete_pending_option
{
1485 my ($conf, $key) = @_;
1487 delete $conf->{pending
}->{$key};
1488 my $pending_delete_hash = { $key => 1 };
1489 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1490 $pending_delete_hash->{$opt} = 1;
1492 $conf->{pending
}->{delete} = join(',', keys %$pending_delete_hash);
1495 sub vmconfig_undelete_pending_option
{
1496 my ($conf, $key) = @_;
1498 my $pending_delete_hash = {};
1499 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1500 $pending_delete_hash->{$opt} = 1;
1502 delete $pending_delete_hash->{$key};
1504 my @keylist = keys %$pending_delete_hash;
1505 if (scalar(@keylist)) {
1506 $conf->{pending
}->{delete} = join(',', @keylist);
1508 delete $conf->{pending
}->{delete};
1512 sub vmconfig_register_unused_drive
{
1513 my ($storecfg, $vmid, $conf, $drive) = @_;
1515 if (!drive_is_cdrom
($drive)) {
1516 my $volid = $drive->{file
};
1517 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1518 add_unused_volume
($conf, $volid, $vmid);
1523 sub vmconfig_cleanup_pending
{
1526 # remove pending changes when nothing changed
1528 foreach my $opt (keys %{$conf->{pending
}}) {
1529 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1531 delete $conf->{pending
}->{$opt};
1535 # remove delete if option is not set
1536 my $pending_delete_hash = {};
1537 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1538 if (defined($conf->{$opt})) {
1539 $pending_delete_hash->{$opt} = 1;
1545 my @keylist = keys %$pending_delete_hash;
1546 if (scalar(@keylist)) {
1547 $conf->{pending
}->{delete} = join(',', @keylist);
1549 delete $conf->{pending
}->{delete};
1555 my $valid_smbios1_options = {
1556 manufacturer
=> '\S+',
1560 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1565 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1571 foreach my $kvp (split(/,/, $data)) {
1572 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1573 my ($k, $v) = split(/=/, $kvp);
1574 return undef if !defined($k) || !defined($v);
1575 return undef if !$valid_smbios1_options->{$k};
1576 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1587 foreach my $k (keys %$smbios1) {
1588 next if !defined($smbios1->{$k});
1589 next if !$valid_smbios1_options->{$k};
1590 $data .= ',' if $data;
1591 $data .= "$k=$smbios1->{$k}";
1596 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1597 sub verify_smbios1
{
1598 my ($value, $noerr) = @_;
1600 return $value if parse_smbios1
($value);
1602 return undef if $noerr;
1604 die "unable to parse smbios (type 1) options\n";
1607 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1608 sub verify_bootdisk
{
1609 my ($value, $noerr) = @_;
1611 return $value if valid_drivename
($value);
1613 return undef if $noerr;
1615 die "invalid boot disk '$value'\n";
1618 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1620 my ($value, $noerr) = @_;
1622 return $value if parse_numa
($value);
1624 return undef if $noerr;
1626 die "unable to parse numa options\n";
1629 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1631 my ($value, $noerr) = @_;
1633 return $value if parse_net
($value);
1635 return undef if $noerr;
1637 die "unable to parse network options\n";
1640 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1642 my ($value, $noerr) = @_;
1644 return $value if parse_drive
(undef, $value);
1646 return undef if $noerr;
1648 die "unable to parse drive options\n";
1651 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1652 sub verify_hostpci
{
1653 my ($value, $noerr) = @_;
1655 return $value if parse_hostpci
($value);
1657 return undef if $noerr;
1659 die "unable to parse pci id\n";
1662 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1663 sub verify_watchdog
{
1664 my ($value, $noerr) = @_;
1666 return $value if parse_watchdog
($value);
1668 return undef if $noerr;
1670 die "unable to parse watchdog options\n";
1673 sub parse_watchdog
{
1676 return undef if !$value;
1680 foreach my $p (split(/,/, $value)) {
1681 next if $p =~ m/^\s*$/;
1683 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1685 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1686 $res->{action
} = $2;
1695 sub parse_usb_device
{
1698 return undef if !$value;
1700 my @dl = split(/,/, $value);
1704 foreach my $v (@dl) {
1705 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1707 $res->{vendorid
} = $2;
1708 $res->{productid
} = $4;
1709 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1711 $res->{hostbus
} = $1;
1712 $res->{hostport
} = $2;
1713 } elsif ($v =~ m/^spice$/) {
1720 return undef if !$found;
1725 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1726 sub verify_usb_device
{
1727 my ($value, $noerr) = @_;
1729 return $value if parse_usb_device
($value);
1731 return undef if $noerr;
1733 die "unable to parse usb device\n";
1736 # add JSON properties for create and set function
1737 sub json_config_properties
{
1740 foreach my $opt (keys %$confdesc) {
1741 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1742 $prop->{$opt} = $confdesc->{$opt};
1749 my ($key, $value) = @_;
1751 die "unknown setting '$key'\n" if !$confdesc->{$key};
1753 my $type = $confdesc->{$key}->{type
};
1755 if (!defined($value)) {
1756 die "got undefined value\n";
1759 if ($value =~ m/[\n\r]/) {
1760 die "property contains a line feed\n";
1763 if ($type eq 'boolean') {
1764 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1765 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1766 die "type check ('boolean') failed - got '$value'\n";
1767 } elsif ($type eq 'integer') {
1768 return int($1) if $value =~ m/^(\d+)$/;
1769 die "type check ('integer') failed - got '$value'\n";
1770 } elsif ($type eq 'number') {
1771 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1772 die "type check ('number') failed - got '$value'\n";
1773 } elsif ($type eq 'string') {
1774 if (my $fmt = $confdesc->{$key}->{format
}) {
1775 if ($fmt eq 'pve-qm-drive') {
1776 # special case - we need to pass $key to parse_drive()
1777 my $drive = parse_drive
($key, $value);
1778 return $value if $drive;
1779 die "unable to parse drive options\n";
1781 PVE
::JSONSchema
::check_format
($fmt, $value);
1784 $value =~ s/^\"(.*)\"$/$1/;
1787 die "internal error"
1791 sub lock_config_full
{
1792 my ($vmid, $timeout, $code, @param) = @_;
1794 my $filename = config_file_lock
($vmid);
1796 my $res = lock_file
($filename, $timeout, $code, @param);
1803 sub lock_config_mode
{
1804 my ($vmid, $timeout, $shared, $code, @param) = @_;
1806 my $filename = config_file_lock
($vmid);
1808 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1816 my ($vmid, $code, @param) = @_;
1818 return lock_config_full
($vmid, 10, $code, @param);
1821 sub cfs_config_path
{
1822 my ($vmid, $node) = @_;
1824 $node = $nodename if !$node;
1825 return "nodes/$node/qemu-server/$vmid.conf";
1828 sub check_iommu_support
{
1829 #fixme : need to check IOMMU support
1830 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1838 my ($vmid, $node) = @_;
1840 my $cfspath = cfs_config_path
($vmid, $node);
1841 return "/etc/pve/$cfspath";
1844 sub config_file_lock
{
1847 return "$lock_dir/lock-$vmid.conf";
1853 my $conf = config_file
($vmid);
1854 utime undef, undef, $conf;
1858 my ($storecfg, $vmid, $keep_empty_config) = @_;
1860 my $conffile = config_file
($vmid);
1862 my $conf = load_config
($vmid);
1866 # only remove disks owned by this VM
1867 foreach_drive
($conf, sub {
1868 my ($ds, $drive) = @_;
1870 return if drive_is_cdrom
($drive);
1872 my $volid = $drive->{file
};
1874 return if !$volid || $volid =~ m
|^/|;
1876 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1877 return if !$path || !$owner || ($owner != $vmid);
1879 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1882 if ($keep_empty_config) {
1883 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1888 # also remove unused disk
1890 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1893 PVE
::Storage
::foreach_volid
($dl, sub {
1894 my ($volid, $sid, $volname, $d) = @_;
1895 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1905 my ($vmid, $node) = @_;
1907 my $cfspath = cfs_config_path
($vmid, $node);
1909 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1911 die "no such VM ('$vmid')\n" if !defined($conf);
1916 sub parse_vm_config
{
1917 my ($filename, $raw) = @_;
1919 return undef if !defined($raw);
1922 digest
=> Digest
::SHA
::sha1_hex
($raw),
1927 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1928 || die "got strange filename '$filename'";
1936 my @lines = split(/\n/, $raw);
1937 foreach my $line (@lines) {
1938 next if $line =~ m/^\s*$/;
1940 if ($line =~ m/^\[PENDING\]\s*$/i) {
1941 $section = 'pending';
1942 $conf->{description
} = $descr if $descr;
1944 $conf = $res->{$section} = {};
1947 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1949 $conf->{description
} = $descr if $descr;
1951 $conf = $res->{snapshots
}->{$section} = {};
1955 if ($line =~ m/^\#(.*)\s*$/) {
1956 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1960 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1961 $descr .= PVE
::Tools
::decode_text
($2);
1962 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1963 $conf->{snapstate
} = $1;
1964 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1967 $conf->{$key} = $value;
1968 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1970 if ($section eq 'pending') {
1971 $conf->{delete} = $value; # we parse this later
1973 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1975 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1978 eval { $value = check_type
($key, $value); };
1980 warn "vm $vmid - unable to parse value of '$key' - $@";
1982 my $fmt = $confdesc->{$key}->{format
};
1983 if ($fmt && $fmt eq 'pve-qm-drive') {
1984 my $v = parse_drive
($key, $value);
1985 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1986 $v->{file
} = $volid;
1987 $value = print_drive
($vmid, $v);
1989 warn "vm $vmid - unable to parse value of '$key'\n";
1994 if ($key eq 'cdrom') {
1995 $conf->{ide2
} = $value;
1997 $conf->{$key} = $value;
2003 $conf->{description
} = $descr if $descr;
2005 delete $res->{snapstate
}; # just to be sure
2010 sub write_vm_config
{
2011 my ($filename, $conf) = @_;
2013 delete $conf->{snapstate
}; # just to be sure
2015 if ($conf->{cdrom
}) {
2016 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2017 $conf->{ide2
} = $conf->{cdrom
};
2018 delete $conf->{cdrom
};
2021 # we do not use 'smp' any longer
2022 if ($conf->{sockets
}) {
2023 delete $conf->{smp
};
2024 } elsif ($conf->{smp
}) {
2025 $conf->{sockets
} = $conf->{smp
};
2026 delete $conf->{cores
};
2027 delete $conf->{smp
};
2030 my $used_volids = {};
2032 my $cleanup_config = sub {
2033 my ($cref, $pending, $snapname) = @_;
2035 foreach my $key (keys %$cref) {
2036 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2037 $key eq 'snapstate' || $key eq 'pending';
2038 my $value = $cref->{$key};
2039 if ($key eq 'delete') {
2040 die "propertry 'delete' is only allowed in [PENDING]\n"
2042 # fixme: check syntax?
2045 eval { $value = check_type
($key, $value); };
2046 die "unable to parse value of '$key' - $@" if $@;
2048 $cref->{$key} = $value;
2050 if (!$snapname && valid_drivename
($key)) {
2051 my $drive = parse_drive
($key, $value);
2052 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2057 &$cleanup_config($conf);
2059 &$cleanup_config($conf->{pending
}, 1);
2061 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2062 die "internal error" if $snapname eq 'pending';
2063 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2066 # remove 'unusedX' settings if we re-add a volume
2067 foreach my $key (keys %$conf) {
2068 my $value = $conf->{$key};
2069 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2070 delete $conf->{$key};
2074 my $generate_raw_config = sub {
2079 # add description as comment to top of file
2080 my $descr = $conf->{description
} || '';
2081 foreach my $cl (split(/\n/, $descr)) {
2082 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2085 foreach my $key (sort keys %$conf) {
2086 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2087 $raw .= "$key: $conf->{$key}\n";
2092 my $raw = &$generate_raw_config($conf);
2094 if (scalar(keys %{$conf->{pending
}})){
2095 $raw .= "\n[PENDING]\n";
2096 $raw .= &$generate_raw_config($conf->{pending
});
2099 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2100 $raw .= "\n[$snapname]\n";
2101 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2107 sub update_config_nolock
{
2108 my ($vmid, $conf, $skiplock) = @_;
2110 check_lock
($conf) if !$skiplock;
2112 my $cfspath = cfs_config_path
($vmid);
2114 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2118 my ($vmid, $conf, $skiplock) = @_;
2120 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2127 # we use static defaults from our JSON schema configuration
2128 foreach my $key (keys %$confdesc) {
2129 if (defined(my $default = $confdesc->{$key}->{default})) {
2130 $res->{$key} = $default;
2134 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2135 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2141 my $vmlist = PVE
::Cluster
::get_vmlist
();
2143 return $res if !$vmlist || !$vmlist->{ids
};
2144 my $ids = $vmlist->{ids
};
2146 foreach my $vmid (keys %$ids) {
2147 my $d = $ids->{$vmid};
2148 next if !$d->{node
} || $d->{node
} ne $nodename;
2149 next if !$d->{type
} || $d->{type
} ne 'qemu';
2150 $res->{$vmid}->{exists} = 1;
2155 # test if VM uses local resources (to prevent migration)
2156 sub check_local_resources
{
2157 my ($conf, $noerr) = @_;
2161 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2162 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2164 foreach my $k (keys %$conf) {
2165 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2166 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2169 die "VM uses local resources\n" if $loc_res && !$noerr;
2174 # check if used storages are available on all nodes (use by migrate)
2175 sub check_storage_availability
{
2176 my ($storecfg, $conf, $node) = @_;
2178 foreach_drive
($conf, sub {
2179 my ($ds, $drive) = @_;
2181 my $volid = $drive->{file
};
2184 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2187 # check if storage is available on both nodes
2188 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2189 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2193 # list nodes where all VM images are available (used by has_feature API)
2195 my ($conf, $storecfg) = @_;
2197 my $nodelist = PVE
::Cluster
::get_nodelist
();
2198 my $nodehash = { map { $_ => 1 } @$nodelist };
2199 my $nodename = PVE
::INotify
::nodename
();
2201 foreach_drive
($conf, sub {
2202 my ($ds, $drive) = @_;
2204 my $volid = $drive->{file
};
2207 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2209 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2210 if ($scfg->{disable
}) {
2212 } elsif (my $avail = $scfg->{nodes
}) {
2213 foreach my $node (keys %$nodehash) {
2214 delete $nodehash->{$node} if !$avail->{$node};
2216 } elsif (!$scfg->{shared
}) {
2217 foreach my $node (keys %$nodehash) {
2218 delete $nodehash->{$node} if $node ne $nodename
2230 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2234 my ($pidfile, $pid) = @_;
2236 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2240 return undef if !$line;
2241 my @param = split(/\0/, $line);
2243 my $cmd = $param[0];
2244 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2246 for (my $i = 0; $i < scalar (@param); $i++) {
2249 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2250 my $p = $param[$i+1];
2251 return 1 if $p && ($p eq $pidfile);
2260 my ($vmid, $nocheck, $node) = @_;
2262 my $filename = config_file
($vmid, $node);
2264 die "unable to find configuration file for VM $vmid - no such machine\n"
2265 if !$nocheck && ! -f
$filename;
2267 my $pidfile = pidfile_name
($vmid);
2269 if (my $fd = IO
::File-
>new("<$pidfile")) {
2274 my $mtime = $st->mtime;
2275 if ($mtime > time()) {
2276 warn "file '$filename' modified in future\n";
2279 if ($line =~ m/^(\d+)$/) {
2281 if (check_cmdline
($pidfile, $pid)) {
2282 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2294 my $vzlist = config_list
();
2296 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2298 while (defined(my $de = $fd->read)) {
2299 next if $de !~ m/^(\d+)\.pid$/;
2301 next if !defined($vzlist->{$vmid});
2302 if (my $pid = check_running
($vmid)) {
2303 $vzlist->{$vmid}->{pid
} = $pid;
2311 my ($storecfg, $conf) = @_;
2313 my $bootdisk = $conf->{bootdisk
};
2314 return undef if !$bootdisk;
2315 return undef if !valid_drivename
($bootdisk);
2317 return undef if !$conf->{$bootdisk};
2319 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2320 return undef if !defined($drive);
2322 return undef if drive_is_cdrom
($drive);
2324 my $volid = $drive->{file
};
2325 return undef if !$volid;
2327 return $drive->{size
};
2330 my $last_proc_pid_stat;
2332 # get VM status information
2333 # This must be fast and should not block ($full == false)
2334 # We only query KVM using QMP if $full == true (this can be slow)
2336 my ($opt_vmid, $full) = @_;
2340 my $storecfg = PVE
::Storage
::config
();
2342 my $list = vzlist
();
2343 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2345 my $cpucount = $cpuinfo->{cpus
} || 1;
2347 foreach my $vmid (keys %$list) {
2348 next if $opt_vmid && ($vmid ne $opt_vmid);
2350 my $cfspath = cfs_config_path
($vmid);
2351 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2354 $d->{pid
} = $list->{$vmid}->{pid
};
2356 # fixme: better status?
2357 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2359 my $size = disksize
($storecfg, $conf);
2360 if (defined($size)) {
2361 $d->{disk
} = 0; # no info available
2362 $d->{maxdisk
} = $size;
2368 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2369 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2370 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2372 $d->{name
} = $conf->{name
} || "VM $vmid";
2373 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2375 if ($conf->{balloon
}) {
2376 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2377 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2388 $d->{diskwrite
} = 0;
2390 $d->{template
} = is_template
($conf);
2395 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2396 foreach my $dev (keys %$netdev) {
2397 next if $dev !~ m/^tap([1-9]\d*)i/;
2399 my $d = $res->{$vmid};
2402 $d->{netout
} += $netdev->{$dev}->{receive
};
2403 $d->{netin
} += $netdev->{$dev}->{transmit
};
2406 my $ctime = gettimeofday
;
2408 foreach my $vmid (keys %$list) {
2410 my $d = $res->{$vmid};
2411 my $pid = $d->{pid
};
2414 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2415 next if !$pstat; # not running
2417 my $used = $pstat->{utime} + $pstat->{stime
};
2419 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2421 if ($pstat->{vsize
}) {
2422 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2425 my $old = $last_proc_pid_stat->{$pid};
2427 $last_proc_pid_stat->{$pid} = {
2435 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2437 if ($dtime > 1000) {
2438 my $dutime = $used - $old->{used
};
2440 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2441 $last_proc_pid_stat->{$pid} = {
2447 $d->{cpu
} = $old->{cpu
};
2451 return $res if !$full;
2453 my $qmpclient = PVE
::QMPClient-
>new();
2455 my $ballooncb = sub {
2456 my ($vmid, $resp) = @_;
2458 my $info = $resp->{'return'};
2459 return if !$info->{max_mem
};
2461 my $d = $res->{$vmid};
2463 # use memory assigned to VM
2464 $d->{maxmem
} = $info->{max_mem
};
2465 $d->{balloon
} = $info->{actual
};
2467 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2468 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2469 $d->{freemem
} = $info->{free_mem
};
2474 my $blockstatscb = sub {
2475 my ($vmid, $resp) = @_;
2476 my $data = $resp->{'return'} || [];
2477 my $totalrdbytes = 0;
2478 my $totalwrbytes = 0;
2479 for my $blockstat (@$data) {
2480 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2481 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2483 $res->{$vmid}->{diskread
} = $totalrdbytes;
2484 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2487 my $statuscb = sub {
2488 my ($vmid, $resp) = @_;
2490 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2491 # this fails if ballon driver is not loaded, so this must be
2492 # the last commnand (following command are aborted if this fails).
2493 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2495 my $status = 'unknown';
2496 if (!defined($status = $resp->{'return'}->{status
})) {
2497 warn "unable to get VM status\n";
2501 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2504 foreach my $vmid (keys %$list) {
2505 next if $opt_vmid && ($vmid ne $opt_vmid);
2506 next if !$res->{$vmid}->{pid
}; # not running
2507 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2510 $qmpclient->queue_execute(undef, 1);
2512 foreach my $vmid (keys %$list) {
2513 next if $opt_vmid && ($vmid ne $opt_vmid);
2514 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2521 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2524 my $current_size = 1024;
2525 my $dimm_size = 512;
2526 return if $current_size == $memory;
2528 for (my $j = 0; $j < 8; $j++) {
2529 for (my $i = 0; $i < 32; $i++) {
2530 my $name = "dimm${dimm_id}";
2532 my $numanode = $i % $sockets;
2533 $current_size += $dimm_size;
2534 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2535 return $current_size if $current_size >= $memory;
2542 my ($conf, $func) = @_;
2544 foreach my $ds (keys %$conf) {
2545 next if !valid_drivename
($ds);
2547 my $drive = parse_drive
($ds, $conf->{$ds});
2550 &$func($ds, $drive);
2555 my ($conf, $func) = @_;
2559 my $test_volid = sub {
2560 my ($volid, $is_cdrom) = @_;
2564 $volhash->{$volid} = $is_cdrom || 0;
2567 foreach_drive
($conf, sub {
2568 my ($ds, $drive) = @_;
2569 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2572 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2573 my $snap = $conf->{snapshots
}->{$snapname};
2574 &$test_volid($snap->{vmstate
}, 0);
2575 foreach_drive
($snap, sub {
2576 my ($ds, $drive) = @_;
2577 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2581 foreach my $volid (keys %$volhash) {
2582 &$func($volid, $volhash->{$volid});
2586 sub vga_conf_has_spice
{
2589 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2594 sub config_to_command
{
2595 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2598 my $globalFlags = [];
2599 my $machineFlags = [];
2605 my $kvmver = kvm_user_version
();
2606 my $vernum = 0; # unknown
2607 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2608 $vernum = $1*1000000+$2*1000;
2609 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2610 $vernum = $1*1000000+$2*1000+$3;
2613 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2615 my $have_ovz = -f
'/proc/vz/vestat';
2617 my $q35 = machine_type_is_q35
($conf);
2618 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2619 my $machine_type = $forcemachine || $conf->{machine
};
2621 push @$cmd, '/usr/bin/kvm';
2623 push @$cmd, '-id', $vmid;
2627 my $qmpsocket = qmp_socket
($vmid);
2628 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2629 push @$cmd, '-mon', "chardev=qmp,mode=control";
2631 my $socket = vnc_socket
($vmid);
2632 push @$cmd, '-vnc', "unix:$socket,x509,password";
2634 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2636 push @$cmd, '-daemonize';
2638 if ($conf->{smbios1
}) {
2639 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2643 # the q35 chipset support native usb2, so we enable usb controller
2644 # by default for this machine type
2645 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2647 $pciaddr = print_pci_addr
("piix3", $bridges);
2648 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2651 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2652 next if !$conf->{"usb$i"};
2655 # include usb device config
2656 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2659 my $vga = $conf->{vga
};
2661 my $qxlnum = vga_conf_has_spice
($vga);
2662 $vga = 'qxl' if $qxlnum;
2665 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2666 $conf->{ostype
} eq 'win7' ||
2667 $conf->{ostype
} eq 'w2k8')) {
2674 # enable absolute mouse coordinates (needed by vnc)
2676 if (defined($conf->{tablet
})) {
2677 $tablet = $conf->{tablet
};
2679 $tablet = $defaults->{tablet
};
2680 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2681 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2684 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2687 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2688 my $d = parse_hostpci
($conf->{"hostpci$i"});
2691 my $pcie = $d->{pcie
};
2693 die "q35 machine model is not enabled" if !$q35;
2694 $pciaddr = print_pcie_addr
("hostpci$i");
2696 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2699 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2700 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2701 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2702 if ($xvga && $xvga ne '') {
2703 push @$cpuFlags, 'kvm=off';
2706 $driver = "vfio-pci" if $xvga ne '';
2707 my $pcidevices = $d->{pciid
};
2708 my $multifunction = 1 if @$pcidevices > 1;
2711 foreach my $pcidevice (@$pcidevices) {
2713 my $id = "hostpci$i";
2714 $id .= ".$j" if $multifunction;
2715 my $addr = $pciaddr;
2716 $addr .= ".$j" if $multifunction;
2717 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2720 $devicestr .= "$rombar$xvga";
2721 $devicestr .= ",multifunction=on" if $multifunction;
2724 push @$devices, '-device', $devicestr;
2730 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2731 my $d = parse_usb_device
($conf->{"usb$i"});
2733 if ($d->{vendorid
} && $d->{productid
}) {
2734 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2735 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2736 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2737 } elsif ($d->{spice
}) {
2738 # usb redir support for spice
2739 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2740 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2745 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2746 if (my $path = $conf->{"serial$i"}) {
2747 if ($path eq 'socket') {
2748 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2749 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2750 push @$devices, '-device', "isa-serial,chardev=serial$i";
2752 die "no such serial device\n" if ! -c
$path;
2753 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2754 push @$devices, '-device', "isa-serial,chardev=serial$i";
2760 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2761 if (my $path = $conf->{"parallel$i"}) {
2762 die "no such parallel device\n" if ! -c
$path;
2763 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2764 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2765 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2769 my $vmname = $conf->{name
} || "vm$vmid";
2771 push @$cmd, '-name', $vmname;
2774 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2775 $sockets = $conf->{sockets
} if $conf->{sockets
};
2777 my $cores = $conf->{cores
} || 1;
2779 my $maxcpus = $sockets * $cores;
2781 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2783 my $allowed_vcpus = $cpuinfo->{cpus
};
2785 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2786 if ($allowed_vcpus < $maxcpus);
2788 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2790 push @$cmd, '-nodefaults';
2792 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2794 my $bootindex_hash = {};
2796 foreach my $o (split(//, $bootorder)) {
2797 $bootindex_hash->{$o} = $i*100;
2801 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2803 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2805 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2807 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2810 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2812 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2813 my $useLocaltime = $conf->{localtime};
2815 if (my $ost = $conf->{ostype
}) {
2816 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2818 if ($ost =~ m/^w/) { # windows
2819 $useLocaltime = 1 if !defined($conf->{localtime});
2821 # use time drift fix when acpi is enabled
2822 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2823 $tdf = 1 if !defined($conf->{tdf
});
2827 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2829 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2830 push @$cmd, '-no-hpet';
2831 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2832 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2833 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2834 push @$cpuFlags , 'hv_time' if !$nokvm;
2837 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2841 if ($ost eq 'win7' || $ost eq 'win8') {
2842 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2846 push @$rtcFlags, 'driftfix=slew' if $tdf;
2849 push @$machineFlags, 'accel=tcg';
2851 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2854 if ($machine_type) {
2855 push @$machineFlags, "type=${machine_type}";
2858 if ($conf->{startdate
}) {
2859 push @$rtcFlags, "base=$conf->{startdate}";
2860 } elsif ($useLocaltime) {
2861 push @$rtcFlags, 'base=localtime';
2864 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2865 $cpu = $conf->{cpu
} if $conf->{cpu
};
2867 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2869 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2871 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2873 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2875 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2877 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2878 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2881 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2883 push @$cmd, '-cpu', "$cpu,enforce";
2885 my $memory = $conf->{memory
} || $defaults->{memory
};
2886 my $static_memory = 0;
2887 my $dimm_memory = 0;
2889 if ($hotplug_features->{memory
}) {
2890 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2891 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2892 $static_memory = $STATICMEM;
2893 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2894 $dimm_memory = $memory - $static_memory;
2895 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2899 $static_memory = $memory;
2900 push @$cmd, '-m', $static_memory;
2903 if ($conf->{numa
}) {
2905 my $numa_totalmemory = undef;
2906 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2907 next if !$conf->{"numa$i"};
2908 my $numa = parse_numa
($conf->{"numa$i"});
2911 die "missing numa node$i memory value\n" if !$numa->{memory
};
2912 my $numa_memory = $numa->{memory
};
2913 $numa_totalmemory += $numa_memory;
2914 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2917 my $cpus_start = $numa->{cpus
}->{start
};
2918 die "missing numa node$i cpus\n" if !defined($cpus_start);
2919 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2920 my $cpus = $cpus_start;
2921 if (defined($cpus_end)) {
2922 $cpus .= "-$cpus_end";
2923 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2927 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2928 if (defined($hostnodes_start)) {
2929 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2930 my $hostnodes = $hostnodes_start;
2931 if (defined($hostnodes_end)) {
2932 $hostnodes .= "-$hostnodes_end";
2933 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2936 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2937 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2938 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2942 my $policy = $numa->{policy
};
2943 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2944 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2947 push @$cmd, '-object', $numa_object;
2948 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2951 die "total memory for NUMA nodes must be equal to vm static memory\n"
2952 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2954 #if no custom tology, we split memory and cores across numa nodes
2955 if(!$numa_totalmemory) {
2957 my $numa_memory = ($static_memory / $sockets) . "M";
2959 for (my $i = 0; $i < $sockets; $i++) {
2961 my $cpustart = ($cores * $i);
2962 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2963 my $cpus = $cpustart;
2964 $cpus .= "-$cpuend" if $cpuend;
2966 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2967 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2972 if ($hotplug_features->{memory
}) {
2973 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2974 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2975 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2976 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2978 #if dimm_memory is not aligned to dimm map
2979 if($current_size > $memory) {
2980 $conf->{memory
} = $current_size;
2981 update_config_nolock
($vmid, $conf, 1);
2986 push @$cmd, '-S' if $conf->{freeze
};
2988 # set keyboard layout
2989 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2990 push @$cmd, '-k', $kb if $kb;
2993 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2994 #push @$cmd, '-soundhw', 'es1370';
2995 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2997 if($conf->{agent
}) {
2998 my $qgasocket = qmp_socket
($vmid, 1);
2999 my $pciaddr = print_pci_addr
("qga0", $bridges);
3000 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3001 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3002 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3009 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3010 for(my $i = 1; $i < $qxlnum; $i++){
3011 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3012 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3015 # assume other OS works like Linux
3016 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3017 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3021 my $pciaddr = print_pci_addr
("spice", $bridges);
3023 my $nodename = PVE
::INotify
::nodename
();
3024 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3025 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3027 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3029 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3030 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3031 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3034 # enable balloon by default, unless explicitly disabled
3035 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3036 $pciaddr = print_pci_addr
("balloon0", $bridges);
3037 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3040 if ($conf->{watchdog
}) {
3041 my $wdopts = parse_watchdog
($conf->{watchdog
});
3042 $pciaddr = print_pci_addr
("watchdog", $bridges);
3043 my $watchdog = $wdopts->{model
} || 'i6300esb';
3044 push @$devices, '-device', "$watchdog$pciaddr";
3045 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3049 my $scsicontroller = {};
3050 my $ahcicontroller = {};
3051 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3053 # Add iscsi initiator name if available
3054 if (my $initiator = get_initiator_name
()) {
3055 push @$devices, '-iscsi', "initiator-name=$initiator";
3058 foreach_drive
($conf, sub {
3059 my ($ds, $drive) = @_;
3061 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3062 push @$vollist, $drive->{file
};
3065 $use_virtio = 1 if $ds =~ m/^virtio/;
3067 if (drive_is_cdrom
($drive)) {
3068 if ($bootindex_hash->{d
}) {
3069 $drive->{bootindex
} = $bootindex_hash->{d
};
3070 $bootindex_hash->{d
} += 1;
3073 if ($bootindex_hash->{c
}) {
3074 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3075 $bootindex_hash->{c
} += 1;
3079 if($drive->{interface
} eq 'virtio'){
3080 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3083 if ($drive->{interface
} eq 'scsi') {
3085 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3087 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3088 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3091 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3092 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3093 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3097 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3098 $queues = ",num_queues=$drive->{queues}";
3101 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3102 $scsicontroller->{$controller}=1;
3105 if ($drive->{interface
} eq 'sata') {
3106 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3107 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3108 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3109 $ahcicontroller->{$controller}=1;
3112 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3113 push @$devices, '-drive',$drive_cmd;
3114 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3117 for (my $i = 0; $i < $MAX_NETS; $i++) {
3118 next if !$conf->{"net$i"};
3119 my $d = parse_net
($conf->{"net$i"});
3122 $use_virtio = 1 if $d->{model
} eq 'virtio';
3124 if ($bootindex_hash->{n
}) {
3125 $d->{bootindex
} = $bootindex_hash->{n
};
3126 $bootindex_hash->{n
} += 1;
3129 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3130 push @$devices, '-netdev', $netdevfull;
3132 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3133 push @$devices, '-device', $netdevicefull;
3138 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3143 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3145 while (my ($k, $v) = each %$bridges) {
3146 $pciaddr = print_pci_addr
("pci.$k");
3147 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3151 # hack: virtio with fairsched is unreliable, so we do not use fairsched
3152 # when the VM uses virtio devices.
3153 if (!$use_virtio && $have_ovz) {
3155 my $cpuunits = defined($conf->{cpuunits
}) ?
3156 $conf->{cpuunits
} : $defaults->{cpuunits
};
3158 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
3160 # fixme: cpulimit is currently ignored
3161 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
3165 if ($conf->{args
}) {
3166 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3170 push @$cmd, @$devices;
3171 push @$cmd, '-rtc', join(',', @$rtcFlags)
3172 if scalar(@$rtcFlags);
3173 push @$cmd, '-machine', join(',', @$machineFlags)
3174 if scalar(@$machineFlags);
3175 push @$cmd, '-global', join(',', @$globalFlags)
3176 if scalar(@$globalFlags);
3178 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3183 return "${var_run_tmpdir}/$vmid.vnc";
3189 my $res = vm_mon_cmd
($vmid, 'query-spice');
3191 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3195 my ($vmid, $qga) = @_;
3196 my $sockettype = $qga ?
'qga' : 'qmp';
3197 return "${var_run_tmpdir}/$vmid.$sockettype";
3202 return "${var_run_tmpdir}/$vmid.pid";
3205 sub vm_devices_list
{
3208 my $res = vm_mon_cmd
($vmid, 'query-pci');
3210 foreach my $pcibus (@$res) {
3211 foreach my $device (@{$pcibus->{devices
}}) {
3212 next if !$device->{'qdev_id'};
3213 if ($device->{'pci_bridge'}) {
3214 $devices->{$device->{'qdev_id'}} = 1;
3215 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3216 next if !$bridge_device->{'qdev_id'};
3217 $devices->{$bridge_device->{'qdev_id'}} = 1;
3218 $devices->{$device->{'qdev_id'}}++;
3221 $devices->{$device->{'qdev_id'}} = 1;
3226 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3227 foreach my $block (@$resblock) {
3228 if($block->{device
} =~ m/^drive-(\S+)/){
3233 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3234 foreach my $mice (@$resmice) {
3235 if ($mice->{name
} eq 'QEMU HID Tablet') {
3236 $devices->{tablet
} = 1;
3245 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3247 my $q35 = machine_type_is_q35
($conf);
3249 my $devices_list = vm_devices_list
($vmid);
3250 return 1 if defined($devices_list->{$deviceid});
3252 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3254 if ($deviceid eq 'tablet') {
3256 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3258 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3260 qemu_iothread_add
($vmid, $deviceid, $device);
3262 qemu_driveadd
($storecfg, $vmid, $device);
3263 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3265 qemu_deviceadd
($vmid, $devicefull);
3266 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3268 eval { qemu_drivedel
($vmid, $deviceid); };
3273 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3276 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3277 my $pciaddr = print_pci_addr
($deviceid);
3278 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3280 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3282 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3283 qemu_iothread_add
($vmid, $deviceid, $device);
3284 $devicefull .= ",iothread=iothread-$deviceid";
3287 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3288 $devicefull .= ",num_queues=$device->{queues}";
3291 qemu_deviceadd
($vmid, $devicefull);
3292 qemu_deviceaddverify
($vmid, $deviceid);
3294 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3296 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3297 qemu_driveadd
($storecfg, $vmid, $device);
3299 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3300 eval { qemu_deviceadd
($vmid, $devicefull); };
3302 eval { qemu_drivedel
($vmid, $deviceid); };
3307 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3309 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3310 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3311 qemu_deviceadd
($vmid, $netdevicefull);
3312 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3314 eval { qemu_netdevdel
($vmid, $deviceid); };
3319 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3322 my $pciaddr = print_pci_addr
($deviceid);
3323 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3325 qemu_deviceadd
($vmid, $devicefull);
3326 qemu_deviceaddverify
($vmid, $deviceid);
3329 die "can't hotplug device '$deviceid'\n";
3335 # fixme: this should raise exceptions on error!
3336 sub vm_deviceunplug
{
3337 my ($vmid, $conf, $deviceid) = @_;
3339 my $devices_list = vm_devices_list
($vmid);
3340 return 1 if !defined($devices_list->{$deviceid});
3342 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3344 if ($deviceid eq 'tablet') {
3346 qemu_devicedel
($vmid, $deviceid);
3348 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3350 qemu_devicedel
($vmid, $deviceid);
3351 qemu_devicedelverify
($vmid, $deviceid);
3352 qemu_drivedel
($vmid, $deviceid);
3353 qemu_iothread_del
($conf, $vmid, $deviceid);
3355 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3357 qemu_devicedel
($vmid, $deviceid);
3358 qemu_devicedelverify
($vmid, $deviceid);
3359 qemu_iothread_del
($conf, $vmid, $deviceid);
3361 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3363 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3364 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3365 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3367 qemu_devicedel
($vmid, $deviceid);
3368 qemu_drivedel
($vmid, $deviceid);
3369 qemu_deletescsihw
($conf, $vmid, $deviceid);
3371 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3373 qemu_devicedel
($vmid, $deviceid);
3374 qemu_devicedelverify
($vmid, $deviceid);
3375 qemu_netdevdel
($vmid, $deviceid);
3378 die "can't unplug device '$deviceid'\n";
3384 sub qemu_deviceadd
{
3385 my ($vmid, $devicefull) = @_;
3387 $devicefull = "driver=".$devicefull;
3388 my %options = split(/[=,]/, $devicefull);
3390 vm_mon_cmd
($vmid, "device_add" , %options);
3393 sub qemu_devicedel
{
3394 my ($vmid, $deviceid) = @_;
3396 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3399 sub qemu_iothread_add
{
3400 my($vmid, $deviceid, $device) = @_;
3402 if ($device->{iothread
}) {
3403 my $iothreads = vm_iothreads_list
($vmid);
3404 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3408 sub qemu_iothread_del
{
3409 my($conf, $vmid, $deviceid) = @_;
3411 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3412 if ($device->{iothread
}) {
3413 my $iothreads = vm_iothreads_list
($vmid);
3414 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3418 sub qemu_objectadd
{
3419 my($vmid, $objectid, $qomtype) = @_;
3421 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3426 sub qemu_objectdel
{
3427 my($vmid, $objectid) = @_;
3429 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3435 my ($storecfg, $vmid, $device) = @_;
3437 my $drive = print_drive_full
($storecfg, $vmid, $device);
3438 $drive =~ s/\\/\\\\/g;
3439 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3441 # If the command succeeds qemu prints: "OK
"
3442 return 1 if $ret =~ m/OK/s;
3444 die "adding drive failed
: $ret\n";
3448 my($vmid, $deviceid) = @_;
3450 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3453 return 1 if $ret eq "";
3455 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3456 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3458 die "deleting drive
$deviceid failed
: $ret\n";
3461 sub qemu_deviceaddverify {
3462 my ($vmid, $deviceid) = @_;
3464 for (my $i = 0; $i <= 5; $i++) {
3465 my $devices_list = vm_devices_list($vmid);
3466 return 1 if defined($devices_list->{$deviceid});
3470 die "error on hotplug device
'$deviceid'\n";
3474 sub qemu_devicedelverify {
3475 my ($vmid, $deviceid) = @_;
3477 # need to verify that the device is correctly removed as device_del
3478 # is async and empty return is not reliable
3480 for (my $i = 0; $i <= 5; $i++) {
3481 my $devices_list = vm_devices_list($vmid);
3482 return 1 if !defined($devices_list->{$deviceid});
3486 die "error on hot-unplugging device
'$deviceid'\n";
3489 sub qemu_findorcreatescsihw {
3490 my ($storecfg, $conf, $vmid, $device) = @_;
3492 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3494 my $scsihwid="$controller_prefix$controller";
3495 my $devices_list = vm_devices_list($vmid);
3497 if(!defined($devices_list->{$scsihwid})) {
3498 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3504 sub qemu_deletescsihw {
3505 my ($conf, $vmid, $opt) = @_;
3507 my $device = parse_drive($opt, $conf->{$opt});
3509 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3510 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3514 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3516 my $devices_list = vm_devices_list($vmid);
3517 foreach my $opt (keys %{$devices_list}) {
3518 if (PVE::QemuServer::valid_drivename($opt)) {
3519 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3520 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3526 my $scsihwid="scsihw
$controller";
3528 vm_deviceunplug($vmid, $conf, $scsihwid);
3533 sub qemu_add_pci_bridge {
3534 my ($storecfg, $conf, $vmid, $device) = @_;
3540 print_pci_addr($device, $bridges);
3542 while (my ($k, $v) = each %$bridges) {
3545 return 1 if !defined($bridgeid) || $bridgeid < 1;
3547 my $bridge = "pci
.$bridgeid";
3548 my $devices_list = vm_devices_list($vmid);
3550 if (!defined($devices_list->{$bridge})) {
3551 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3557 sub qemu_set_link_status {
3558 my ($vmid, $device, $up) = @_;
3560 vm_mon_cmd($vmid, "set_link
", name => $device,
3561 up => $up ? JSON::true : JSON::false);
3564 sub qemu_netdevadd {
3565 my ($vmid, $conf, $device, $deviceid) = @_;
3567 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3568 my %options = split(/[=,]/, $netdev);
3570 vm_mon_cmd($vmid, "netdev_add
", %options);
3574 sub qemu_netdevdel {
3575 my ($vmid, $deviceid) = @_;
3577 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3580 sub qemu_cpu_hotplug {
3581 my ($vmid, $conf, $vcpus) = @_;
3584 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3585 $sockets = $conf->{sockets} if $conf->{sockets};
3586 my $cores = $conf->{cores} || 1;
3587 my $maxcpus = $sockets * $cores;
3589 $vcpus = $maxcpus if !$vcpus;
3591 die "you can
't add more vcpus than maxcpus\n"
3592 if $vcpus > $maxcpus;
3594 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3595 die "online cpu unplug is not yet possible\n"
3596 if $vcpus < $currentvcpus;
3598 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3599 die "vcpus in running vm is different than configuration\n"
3600 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3602 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3603 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3607 sub qemu_memory_hotplug {
3608 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3610 return $value if !check_running($vmid);
3612 my $memory = $conf->{memory} || $defaults->{memory};
3613 $value = $defaults->{memory} if !$value;
3614 return $value if $value == $memory;
3616 my $static_memory = $STATICMEM;
3617 my $dimm_memory = $memory - $static_memory;
3619 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3620 die "memory unplug
is not yet available
" if $value < $memory;
3621 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3625 $sockets = $conf->{sockets} if $conf->{sockets};
3627 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3628 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3630 return if $current_size <= $conf->{memory};
3632 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3634 eval { qemu_objectdel($vmid, "mem-
$name"); };
3638 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3640 eval { qemu_objectdel($vmid, "mem-
$name"); };
3643 #update conf after each succesful module hotplug
3644 $conf->{memory} = $current_size;
3645 update_config_nolock($vmid, $conf, 1);
3649 sub qemu_block_set_io_throttle {
3650 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3652 return if !check_running($vmid) ;
3654 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid, bps => int($bps), bps_rd => int($bps_rd), bps_wr => int($bps_wr), iops => int($iops), iops_rd => int($iops_rd), iops_wr => int($iops_wr));
3658 # old code, only used to shutdown old VM after update
3660 my ($fh, $timeout) = @_;
3662 my $sel = new IO::Select;
3669 while (scalar (@ready = $sel->can_read($timeout))) {
3671 if ($count = $fh->sysread($buf, 8192)) {
3672 if ($buf =~ /^(.*)\(qemu\) $/s) {
3679 if (!defined($count)) {
3686 die "monitor
read timeout
\n" if !scalar(@ready);
3691 # old code, only used to shutdown old VM after update
3692 sub vm_monitor_command {
3693 my ($vmid, $cmdstr, $nocheck) = @_;
3698 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3700 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3702 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3703 die "unable to
connect to VM
$vmid socket - $!\n";
3707 # hack: migrate sometime blocks the monitor (when migrate_downtime
3709 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3710 $timeout = 60*60; # 1 hour
3714 my $data = __read_avail($sock, $timeout);
3716 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3717 die "got unexpected qemu monitor banner
\n";
3720 my $sel = new IO::Select;
3723 if (!scalar(my @ready = $sel->can_write($timeout))) {
3724 die "monitor
write error
- timeout
";
3727 my $fullcmd = "$cmdstr\r";
3729 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3732 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3733 die "monitor
write error
- $!";
3736 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3740 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3741 $timeout = 60*60; # 1 hour
3742 } elsif ($cmdstr =~ m/^(eject|change)/) {
3743 $timeout = 60; # note: cdrom mount command is slow
3745 if ($res = __read_avail($sock, $timeout)) {
3747 my @lines = split("\r?
\n", $res);
3749 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3751 $res = join("\n", @lines);
3759 syslog("err
", "VM
$vmid monitor command failed
- $err");
3766 sub qemu_block_resize {
3767 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3769 my $running = check_running($vmid);
3771 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3773 return if !$running;
3775 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3779 sub qemu_volume_snapshot {
3780 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3782 my $running = check_running($vmid);
3784 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3785 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3787 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3791 sub qemu_volume_snapshot_delete {
3792 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3794 my $running = check_running($vmid);
3796 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3798 return if !$running;
3800 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3803 sub set_migration_caps {
3809 "auto-converge
" => 1,
3811 "x-rdma-pin-all
" => 0,
3815 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3817 for my $supported_capability (@$supported_capabilities) {
3819 capability => $supported_capability->{capability},
3820 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3824 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3827 my $fast_plug_option = {
3835 # hotplug changes in [PENDING]
3836 # $selection hash can be used to only apply specified options, for
3837 # example: { cores => 1 } (only apply changed 'cores')
3838 # $errors ref is used to return error messages
3839 sub vmconfig_hotplug_pending {
3840 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3842 my $defaults = load_defaults();
3844 # commit values which do not have any impact on running VM first
3845 # Note: those option cannot raise errors, we we do not care about
3846 # $selection and always apply them.
3848 my $add_error = sub {
3849 my ($opt, $msg) = @_;
3850 $errors->{$opt} = "hotplug problem
- $msg";
3854 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3855 if ($fast_plug_option->{$opt}) {
3856 $conf->{$opt} = $conf->{pending}->{$opt};
3857 delete $conf->{pending}->{$opt};
3863 update_config_nolock($vmid, $conf, 1);
3864 $conf = load_config($vmid); # update/reload
3867 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3869 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3870 foreach my $opt (@delete) {
3871 next if $selection && !$selection->{$opt};
3873 if ($opt eq 'hotplug') {
3874 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3875 } elsif ($opt eq 'tablet') {
3876 die "skip
\n" if !$hotplug_features->{usb};
3877 if ($defaults->{tablet}) {
3878 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3880 vm_deviceunplug($vmid, $conf, $opt);
3882 } elsif ($opt eq 'vcpus') {
3883 die "skip
\n" if !$hotplug_features->{cpu};
3884 qemu_cpu_hotplug($vmid, $conf, undef);
3885 } elsif ($opt eq 'balloon') {
3886 # enable balloon device is not hotpluggable
3887 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3888 } elsif ($fast_plug_option->{$opt}) {
3890 } elsif ($opt =~ m/^net(\d+)$/) {
3891 die "skip
\n" if !$hotplug_features->{network};
3892 vm_deviceunplug($vmid, $conf, $opt);
3893 } elsif (valid_drivename($opt)) {
3894 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3895 vm_deviceunplug($vmid, $conf, $opt);
3896 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3897 } elsif ($opt =~ m/^memory$/) {
3898 die "skip
\n" if !$hotplug_features->{memory};
3899 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3905 &$add_error($opt, $err) if $err ne "skip
\n";
3907 # save new config if hotplug was successful
3908 delete $conf->{$opt};
3909 vmconfig_undelete_pending_option($conf, $opt);
3910 update_config_nolock($vmid, $conf, 1);
3911 $conf = load_config($vmid); # update/reload
3915 foreach my $opt (keys %{$conf->{pending}}) {
3916 next if $selection && !$selection->{$opt};
3917 my $value = $conf->{pending}->{$opt};
3919 if ($opt eq 'hotplug') {
3920 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3921 } elsif ($opt eq 'tablet') {
3922 die "skip
\n" if !$hotplug_features->{usb};
3924 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3925 } elsif ($value == 0) {
3926 vm_deviceunplug($vmid, $conf, $opt);
3928 } elsif ($opt eq 'vcpus') {
3929 die "skip
\n" if !$hotplug_features->{cpu};
3930 qemu_cpu_hotplug($vmid, $conf, $value);
3931 } elsif ($opt eq 'balloon') {
3932 # enable/disable balloning device is not hotpluggable
3933 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3934 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3935 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3937 # allow manual ballooning if shares is set to zero
3938 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3939 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3940 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3942 } elsif ($opt =~ m/^net(\d+)$/) {
3943 # some changes can be done without hotplug
3944 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3945 $vmid, $opt, $value);
3946 } elsif (valid_drivename($opt)) {
3947 # some changes can be done without hotplug
3948 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3949 $vmid, $opt, $value, 1);
3950 } elsif ($opt =~ m/^memory$/) { #dimms
3951 die "skip
\n" if !$hotplug_features->{memory};
3952 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3954 die "skip
\n"; # skip non-hot-pluggable options
3958 &$add_error($opt, $err) if $err ne "skip
\n";
3960 # save new config if hotplug was successful
3961 $conf->{$opt} = $value;
3962 delete $conf->{pending}->{$opt};
3963 update_config_nolock($vmid, $conf, 1);
3964 $conf = load_config($vmid); # update/reload
3969 sub vmconfig_apply_pending {
3970 my ($vmid, $conf, $storecfg) = @_;
3974 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3975 foreach my $opt (@delete) { # delete
3976 die "internal error
" if $opt =~ m/^unused/;
3977 $conf = load_config($vmid); # update/reload
3978 if (!defined($conf->{$opt})) {
3979 vmconfig_undelete_pending_option($conf, $opt);
3980 update_config_nolock($vmid, $conf, 1);
3981 } elsif (valid_drivename($opt)) {
3982 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3983 vmconfig_undelete_pending_option($conf, $opt);
3984 delete $conf->{$opt};
3985 update_config_nolock($vmid, $conf, 1);
3987 vmconfig_undelete_pending_option($conf, $opt);
3988 delete $conf->{$opt};
3989 update_config_nolock($vmid, $conf, 1);
3993 $conf = load_config($vmid); # update/reload
3995 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3996 $conf = load_config($vmid); # update/reload
3998 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
3999 # skip if nothing changed
4000 } elsif (valid_drivename($opt)) {
4001 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4002 if defined($conf->{$opt});
4003 $conf->{$opt} = $conf->{pending}->{$opt};
4005 $conf->{$opt} = $conf->{pending}->{$opt};
4008 delete $conf->{pending}->{$opt};
4009 update_config_nolock($vmid, $conf, 1);
4013 my $safe_num_ne = sub {
4016 return 0 if !defined($a) && !defined($b);
4017 return 1 if !defined($a);
4018 return 1 if !defined($b);
4023 my $safe_string_ne = sub {
4026 return 0 if !defined($a) && !defined($b);
4027 return 1 if !defined($a);
4028 return 1 if !defined($b);
4033 sub vmconfig_update_net {
4034 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4036 my $newnet = parse_net($value);
4038 if ($conf->{$opt}) {
4039 my $oldnet = parse_net($conf->{$opt});
4041 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4042 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4043 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4044 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4046 # for non online change, we try to hot-unplug
4047 die "skip
\n" if !$hotplug;
4048 vm_deviceunplug($vmid, $conf, $opt);
4051 die "internal error
" if $opt !~ m/net(\d+)/;
4052 my $iface = "tap
${vmid
}i
$1";
4054 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4055 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4058 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4059 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4060 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4061 PVE::Network::tap_unplug($iface);
4062 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4065 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4066 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4074 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4080 sub vmconfig_update_disk {
4081 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4083 # fixme: do we need force?
4085 my $drive = parse_drive($opt, $value);
4087 if ($conf->{$opt}) {
4089 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4091 my $media = $drive->{media} || 'disk';
4092 my $oldmedia = $old_drive->{media} || 'disk';
4093 die "unable to change media type
\n" if $media ne $oldmedia;
4095 if (!drive_is_cdrom($old_drive)) {
4097 if ($drive->{file} ne $old_drive->{file}) {
4099 die "skip
\n" if !$hotplug;
4101 # unplug and register as unused
4102 vm_deviceunplug($vmid, $conf, $opt);
4103 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4106 # update existing disk
4108 # skip non hotpluggable value
4109 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4110 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4111 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4112 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4117 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4118 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4119 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4120 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4121 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4122 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4123 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4124 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4125 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4126 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4127 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4128 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4130 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4131 ($drive->{mbps} || 0)*1024*1024,
4132 ($drive->{mbps_rd} || 0)*1024*1024,
4133 ($drive->{mbps_wr} || 0)*1024*1024,
4134 $drive->{iops} || 0,
4135 $drive->{iops_rd} || 0,
4136 $drive->{iops_wr} || 0,
4137 ($drive->{mbps_max} || 0)*1024*1024,
4138 ($drive->{mbps_rd_max} || 0)*1024*1024,
4139 ($drive->{mbps_wr_max} || 0)*1024*1024,
4140 $drive->{iops_max} || 0,
4141 $drive->{iops_rd_max} || 0,
4142 $drive->{iops_wr_max} || 0);
4151 if ($drive->{file} eq 'none') {
4152 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4154 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4155 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4156 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4164 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4166 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4170 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4172 lock_config($vmid, sub {
4173 my $conf = load_config($vmid, $migratedfrom);
4175 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4177 check_lock($conf) if !$skiplock;
4179 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4181 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4182 vmconfig_apply_pending($vmid, $conf, $storecfg);
4183 $conf = load_config($vmid); # update/reload
4186 my $defaults = load_defaults();
4188 # set environment variable useful inside network script
4189 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4191 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4193 my $migrate_port = 0;
4196 if ($statefile eq 'tcp') {
4197 my $localip = "localhost
";
4198 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4199 my $nodename = PVE::INotify::nodename();
4200 if ($datacenterconf->{migration_unsecure}) {
4201 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4203 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4204 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4205 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4206 push @$cmd, '-incoming', $migrate_uri;
4209 push @$cmd, '-loadstate', $statefile;
4216 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4217 my $d = parse_hostpci($conf->{"hostpci
$i"});
4219 my $pcidevices = $d->{pciid};
4220 foreach my $pcidevice (@$pcidevices) {
4221 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4223 my $info = pci_device_info("0000:$pciid");
4224 die "IOMMU
not present
\n" if !check_iommu_support();
4225 die "no pci device info
for device
'$pciid'\n" if !$info;
4227 if ($d->{driver} && $d->{driver} eq "vfio
") {
4228 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4230 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4233 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4237 PVE::Storage::activate_volumes($storecfg, $vollist);
4239 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4242 die "start failed: $err" if $err;
4244 print "migration listens on $migrate_uri\n" if $migrate_uri;
4246 if ($statefile && $statefile ne 'tcp
') {
4247 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4251 if ($migratedfrom) {
4254 set_migration_caps($vmid);
4259 print "spice listens on port $spice_port\n";
4260 if ($spice_ticket) {
4261 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4262 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4268 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4269 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4270 if $conf->{balloon};
4273 foreach my $opt (keys %$conf) {
4274 next if $opt !~ m/^net\d+$/;
4275 my $nicconf = parse_net($conf->{$opt});
4276 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4280 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4281 path => "machine/peripheral/balloon0",
4282 property => "guest-stats-polling-interval",
4283 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4289 my ($vmid, $execute, %params) = @_;
4291 my $cmd = { execute => $execute, arguments => \%params };
4292 vm_qmp_command($vmid, $cmd);
4295 sub vm_mon_cmd_nocheck {
4296 my ($vmid, $execute, %params) = @_;
4298 my $cmd = { execute => $execute, arguments => \%params };
4299 vm_qmp_command($vmid, $cmd, 1);
4302 sub vm_qmp_command {
4303 my ($vmid, $cmd, $nocheck) = @_;
4308 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4309 $timeout = $cmd->{arguments}->{timeout};
4310 delete $cmd->{arguments}->{timeout};
4314 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4315 my $sname = qmp_socket($vmid);
4316 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4317 my $qmpclient = PVE::QMPClient->new();
4319 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4320 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4321 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4322 if scalar(%{$cmd->{arguments}});
4323 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4325 die "unable to
open monitor
socket\n";
4329 syslog("err
", "VM
$vmid qmp command failed
- $err");
4336 sub vm_human_monitor_command {
4337 my ($vmid, $cmdline) = @_;
4342 execute => 'human-monitor-command',
4343 arguments => { 'command-line' => $cmdline},
4346 return vm_qmp_command($vmid, $cmd);
4349 sub vm_commandline {
4350 my ($storecfg, $vmid) = @_;
4352 my $conf = load_config($vmid);
4354 my $defaults = load_defaults();
4356 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4358 return join(' ', @$cmd);
4362 my ($vmid, $skiplock) = @_;
4364 lock_config($vmid, sub {
4366 my $conf = load_config($vmid);
4368 check_lock($conf) if !$skiplock;
4370 vm_mon_cmd($vmid, "system_reset
");
4374 sub get_vm_volumes {
4378 foreach_volid($conf, sub {
4379 my ($volid, $is_cdrom) = @_;
4381 return if $volid =~ m|^/|;
4383 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4386 push @$vollist, $volid;
4392 sub vm_stop_cleanup {
4393 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4396 fairsched_rmnod($vmid); # try to destroy group
4399 my $vollist = get_vm_volumes($conf);
4400 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4403 foreach my $ext (qw(mon qmp pid vnc qga)) {
4404 unlink "/var/run/qemu-server/${vmid}.$ext";
4407 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4409 warn $@ if $@; # avoid errors - just warn
4412 # Note: use $nockeck to skip tests if VM configuration file exists.
4413 # We need that when migration VMs to other nodes (files already moved)
4414 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4416 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4418 $force = 1 if !defined($force) && !$shutdown;
4421 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4422 kill 15, $pid if $pid;
4423 my $conf = load_config
($vmid, $migratedfrom);
4424 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4428 lock_config
($vmid, sub {
4430 my $pid = check_running
($vmid, $nocheck);
4435 $conf = load_config
($vmid);
4436 check_lock
($conf) if !$skiplock;
4437 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4438 my $opts = parse_startup
($conf->{startup
});
4439 $timeout = $opts->{down
} if $opts->{down
};
4443 $timeout = 60 if !defined($timeout);
4447 if (defined($conf) && $conf->{agent
}) {
4448 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4450 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4453 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4460 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4465 if ($count >= $timeout) {
4467 warn "VM still running - terminating now with SIGTERM\n";
4470 die "VM quit/powerdown failed - got timeout\n";
4473 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4478 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4481 die "VM quit/powerdown failed\n";
4489 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4494 if ($count >= $timeout) {
4495 warn "VM still running - terminating now with SIGKILL\n";
4500 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4505 my ($vmid, $skiplock) = @_;
4507 lock_config
($vmid, sub {
4509 my $conf = load_config
($vmid);
4511 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4513 vm_mon_cmd
($vmid, "stop");
4518 my ($vmid, $skiplock) = @_;
4520 lock_config
($vmid, sub {
4522 my $conf = load_config
($vmid);
4524 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4526 vm_mon_cmd
($vmid, "cont");
4531 my ($vmid, $skiplock, $key) = @_;
4533 lock_config
($vmid, sub {
4535 my $conf = load_config
($vmid);
4537 # there is no qmp command, so we use the human monitor command
4538 vm_human_monitor_command
($vmid, "sendkey $key");
4543 my ($storecfg, $vmid, $skiplock) = @_;
4545 lock_config
($vmid, sub {
4547 my $conf = load_config
($vmid);
4549 check_lock
($conf) if !$skiplock;
4551 if (!check_running
($vmid)) {
4552 fairsched_rmnod
($vmid); # try to destroy group
4553 destroy_vm
($storecfg, $vmid);
4555 die "VM $vmid is running - destroy failed\n";
4563 my ($filename, $buf) = @_;
4565 my $fh = IO
::File-
>new($filename, "w");
4566 return undef if !$fh;
4568 my $res = print $fh $buf;
4575 sub pci_device_info
{
4580 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4581 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4583 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4584 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4586 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4587 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4589 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4590 return undef if !defined($product) || $product !~ s/^0x//;
4595 product
=> $product,
4601 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4610 my $name = $dev->{name
};
4612 my $fn = "$pcisysfs/devices/$name/reset";
4614 return file_write
($fn, "1");
4617 sub pci_dev_bind_to_stub
{
4620 my $name = $dev->{name
};
4622 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4623 return 1 if -d
$testdir;
4625 my $data = "$dev->{vendor} $dev->{product}";
4626 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4628 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4629 if (!file_write
($fn, $name)) {
4630 return undef if -f
$fn;
4633 $fn = "$pcisysfs/drivers/pci-stub/bind";
4634 if (! -d
$testdir) {
4635 return undef if !file_write
($fn, $name);
4641 sub pci_dev_bind_to_vfio
{
4644 my $name = $dev->{name
};
4646 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4648 if (!-d
$vfio_basedir) {
4649 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4651 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4653 my $testdir = "$vfio_basedir/$name";
4654 return 1 if -d
$testdir;
4656 my $data = "$dev->{vendor} $dev->{product}";
4657 return undef if !file_write
("$vfio_basedir/new_id", $data);
4659 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4660 if (!file_write
($fn, $name)) {
4661 return undef if -f
$fn;
4664 $fn = "$vfio_basedir/bind";
4665 if (! -d
$testdir) {
4666 return undef if !file_write
($fn, $name);
4672 sub pci_dev_group_bind_to_vfio
{
4675 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4677 if (!-d
$vfio_basedir) {
4678 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4680 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4682 # get IOMMU group devices
4683 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4684 my @devs = grep /^0000:/, readdir($D);
4687 foreach my $pciid (@devs) {
4688 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4690 # pci bridges, switches or root ports are not supported
4691 # they have a pci_bus subdirectory so skip them
4692 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4694 my $info = pci_device_info
($1);
4695 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4701 sub print_pci_addr
{
4702 my ($id, $bridges) = @_;
4706 piix3
=> { bus
=> 0, addr
=> 1 },
4707 #addr2 : first videocard
4708 balloon0
=> { bus
=> 0, addr
=> 3 },
4709 watchdog
=> { bus
=> 0, addr
=> 4 },
4710 scsihw0
=> { bus
=> 0, addr
=> 5 },
4711 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4712 scsihw1
=> { bus
=> 0, addr
=> 6 },
4713 ahci0
=> { bus
=> 0, addr
=> 7 },
4714 qga0
=> { bus
=> 0, addr
=> 8 },
4715 spice
=> { bus
=> 0, addr
=> 9 },
4716 virtio0
=> { bus
=> 0, addr
=> 10 },
4717 virtio1
=> { bus
=> 0, addr
=> 11 },
4718 virtio2
=> { bus
=> 0, addr
=> 12 },
4719 virtio3
=> { bus
=> 0, addr
=> 13 },
4720 virtio4
=> { bus
=> 0, addr
=> 14 },
4721 virtio5
=> { bus
=> 0, addr
=> 15 },
4722 hostpci0
=> { bus
=> 0, addr
=> 16 },
4723 hostpci1
=> { bus
=> 0, addr
=> 17 },
4724 net0
=> { bus
=> 0, addr
=> 18 },
4725 net1
=> { bus
=> 0, addr
=> 19 },
4726 net2
=> { bus
=> 0, addr
=> 20 },
4727 net3
=> { bus
=> 0, addr
=> 21 },
4728 net4
=> { bus
=> 0, addr
=> 22 },
4729 net5
=> { bus
=> 0, addr
=> 23 },
4730 vga1
=> { bus
=> 0, addr
=> 24 },
4731 vga2
=> { bus
=> 0, addr
=> 25 },
4732 vga3
=> { bus
=> 0, addr
=> 26 },
4733 hostpci2
=> { bus
=> 0, addr
=> 27 },
4734 hostpci3
=> { bus
=> 0, addr
=> 28 },
4735 #addr29 : usb-host (pve-usb.cfg)
4736 'pci.1' => { bus
=> 0, addr
=> 30 },
4737 'pci.2' => { bus
=> 0, addr
=> 31 },
4738 'net6' => { bus
=> 1, addr
=> 1 },
4739 'net7' => { bus
=> 1, addr
=> 2 },
4740 'net8' => { bus
=> 1, addr
=> 3 },
4741 'net9' => { bus
=> 1, addr
=> 4 },
4742 'net10' => { bus
=> 1, addr
=> 5 },
4743 'net11' => { bus
=> 1, addr
=> 6 },
4744 'net12' => { bus
=> 1, addr
=> 7 },
4745 'net13' => { bus
=> 1, addr
=> 8 },
4746 'net14' => { bus
=> 1, addr
=> 9 },
4747 'net15' => { bus
=> 1, addr
=> 10 },
4748 'net16' => { bus
=> 1, addr
=> 11 },
4749 'net17' => { bus
=> 1, addr
=> 12 },
4750 'net18' => { bus
=> 1, addr
=> 13 },
4751 'net19' => { bus
=> 1, addr
=> 14 },
4752 'net20' => { bus
=> 1, addr
=> 15 },
4753 'net21' => { bus
=> 1, addr
=> 16 },
4754 'net22' => { bus
=> 1, addr
=> 17 },
4755 'net23' => { bus
=> 1, addr
=> 18 },
4756 'net24' => { bus
=> 1, addr
=> 19 },
4757 'net25' => { bus
=> 1, addr
=> 20 },
4758 'net26' => { bus
=> 1, addr
=> 21 },
4759 'net27' => { bus
=> 1, addr
=> 22 },
4760 'net28' => { bus
=> 1, addr
=> 23 },
4761 'net29' => { bus
=> 1, addr
=> 24 },
4762 'net30' => { bus
=> 1, addr
=> 25 },
4763 'net31' => { bus
=> 1, addr
=> 26 },
4764 'virtio6' => { bus
=> 2, addr
=> 1 },
4765 'virtio7' => { bus
=> 2, addr
=> 2 },
4766 'virtio8' => { bus
=> 2, addr
=> 3 },
4767 'virtio9' => { bus
=> 2, addr
=> 4 },
4768 'virtio10' => { bus
=> 2, addr
=> 5 },
4769 'virtio11' => { bus
=> 2, addr
=> 6 },
4770 'virtio12' => { bus
=> 2, addr
=> 7 },
4771 'virtio13' => { bus
=> 2, addr
=> 8 },
4772 'virtio14' => { bus
=> 2, addr
=> 9 },
4773 'virtio15' => { bus
=> 2, addr
=> 10 },
4774 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4775 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4776 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4777 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4778 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4779 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4780 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4781 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4782 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4783 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4784 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4785 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4786 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4787 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4788 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4789 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4790 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4791 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4792 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4793 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4794 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4795 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4796 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4797 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4798 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4799 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4800 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4801 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4802 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4803 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4804 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4808 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4809 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4810 my $bus = $devices->{$id}->{bus
};
4811 $res = ",bus=pci.$bus,addr=$addr";
4812 $bridges->{$bus} = 1 if $bridges;
4818 sub print_pcie_addr
{
4823 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4824 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4825 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4826 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4829 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4830 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4831 my $bus = $devices->{$id}->{bus
};
4832 $res = ",bus=$bus,addr=$addr";
4838 # vzdump restore implementaion
4840 sub tar_archive_read_firstfile
{
4841 my $archive = shift;
4843 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4845 # try to detect archive type first
4846 my $pid = open (TMP
, "tar tf '$archive'|") ||
4847 die "unable to open file '$archive'\n";
4848 my $firstfile = <TMP
>;
4852 die "ERROR: archive contaions no data\n" if !$firstfile;
4858 sub tar_restore_cleanup
{
4859 my ($storecfg, $statfile) = @_;
4861 print STDERR
"starting cleanup\n";
4863 if (my $fd = IO
::File-
>new($statfile, "r")) {
4864 while (defined(my $line = <$fd>)) {
4865 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4868 if ($volid =~ m
|^/|) {
4869 unlink $volid || die 'unlink failed\n';
4871 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4873 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4875 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4877 print STDERR
"unable to parse line in statfile - $line";
4884 sub restore_archive
{
4885 my ($archive, $vmid, $user, $opts) = @_;
4887 my $format = $opts->{format
};
4890 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4891 $format = 'tar' if !$format;
4893 } elsif ($archive =~ m/\.tar$/) {
4894 $format = 'tar' if !$format;
4895 } elsif ($archive =~ m/.tar.lzo$/) {
4896 $format = 'tar' if !$format;
4898 } elsif ($archive =~ m/\.vma$/) {
4899 $format = 'vma' if !$format;
4900 } elsif ($archive =~ m/\.vma\.gz$/) {
4901 $format = 'vma' if !$format;
4903 } elsif ($archive =~ m/\.vma\.lzo$/) {
4904 $format = 'vma' if !$format;
4907 $format = 'vma' if !$format; # default
4910 # try to detect archive format
4911 if ($format eq 'tar') {
4912 return restore_tar_archive
($archive, $vmid, $user, $opts);
4914 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4918 sub restore_update_config_line
{
4919 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4921 return if $line =~ m/^\#qmdump\#/;
4922 return if $line =~ m/^\#vzdump\#/;
4923 return if $line =~ m/^lock:/;
4924 return if $line =~ m/^unused\d+:/;
4925 return if $line =~ m/^parent:/;
4926 return if $line =~ m/^template:/; # restored VM is never a template
4928 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4929 # try to convert old 1.X settings
4930 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4931 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4932 my ($model, $macaddr) = split(/\=/, $devconfig);
4933 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4936 bridge
=> "vmbr$ind",
4937 macaddr
=> $macaddr,
4939 my $netstr = print_net
($net);
4941 print $outfd "net$cookie->{netcount}: $netstr\n";
4942 $cookie->{netcount
}++;
4944 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4945 my ($id, $netstr) = ($1, $2);
4946 my $net = parse_net
($netstr);
4947 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4948 $netstr = print_net
($net);
4949 print $outfd "$id: $netstr\n";
4950 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4953 if ($line =~ m/backup=no/) {
4954 print $outfd "#$line";
4955 } elsif ($virtdev && $map->{$virtdev}) {
4956 my $di = parse_drive
($virtdev, $value);
4957 delete $di->{format
}; # format can change on restore
4958 $di->{file
} = $map->{$virtdev};
4959 $value = print_drive
($vmid, $di);
4960 print $outfd "$virtdev: $value\n";
4970 my ($cfg, $vmid) = @_;
4972 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4974 my $volid_hash = {};
4975 foreach my $storeid (keys %$info) {
4976 foreach my $item (@{$info->{$storeid}}) {
4977 next if !($item->{volid
} && $item->{size
});
4978 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4979 $volid_hash->{$item->{volid
}} = $item;
4986 sub get_used_paths
{
4987 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
4991 my $scan_config = sub {
4992 my ($cref, $snapname) = @_;
4994 foreach my $key (keys %$cref) {
4995 my $value = $cref->{$key};
4996 if (valid_drivename
($key)) {
4997 next if $skip_drive && $key eq $skip_drive;
4998 my $drive = parse_drive
($key, $value);
4999 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5000 if ($drive->{file
} =~ m!^/!) {
5001 $used_path->{$drive->{file
}}++; # = 1;
5003 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5005 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5007 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5008 $used_path->{$path}++; # = 1;
5014 &$scan_config($conf);
5018 if ($scan_snapshots) {
5019 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5020 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5027 sub update_disksize
{
5028 my ($vmid, $conf, $volid_hash) = @_;
5034 # Note: it is allowed to define multiple storages with same path (alias), so
5035 # we need to check both 'volid' and real 'path' (two different volid can point
5036 # to the same path).
5041 foreach my $opt (keys %$conf) {
5042 if (valid_drivename
($opt)) {
5043 my $drive = parse_drive
($opt, $conf->{$opt});
5044 my $volid = $drive->{file
};
5047 $used->{$volid} = 1;
5048 if ($volid_hash->{$volid} &&
5049 (my $path = $volid_hash->{$volid}->{path
})) {
5050 $usedpath->{$path} = 1;
5053 next if drive_is_cdrom
($drive);
5054 next if !$volid_hash->{$volid};
5056 $drive->{size
} = $volid_hash->{$volid}->{size
};
5057 my $new = print_drive
($vmid, $drive);
5058 if ($new ne $conf->{$opt}) {
5060 $conf->{$opt} = $new;
5065 # remove 'unusedX' entry if volume is used
5066 foreach my $opt (keys %$conf) {
5067 next if $opt !~ m/^unused\d+$/;
5068 my $volid = $conf->{$opt};
5069 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5070 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5072 delete $conf->{$opt};
5076 foreach my $volid (sort keys %$volid_hash) {
5077 next if $volid =~ m/vm-$vmid-state-/;
5078 next if $used->{$volid};
5079 my $path = $volid_hash->{$volid}->{path
};
5080 next if !$path; # just to be sure
5081 next if $usedpath->{$path};
5083 add_unused_volume
($conf, $volid);
5084 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5091 my ($vmid, $nolock) = @_;
5093 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5095 my $volid_hash = scan_volids
($cfg, $vmid);
5097 my $updatefn = sub {
5100 my $conf = load_config
($vmid);
5105 foreach my $volid (keys %$volid_hash) {
5106 my $info = $volid_hash->{$volid};
5107 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5110 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5112 update_config_nolock
($vmid, $conf, 1) if $changes;
5115 if (defined($vmid)) {
5119 lock_config
($vmid, $updatefn, $vmid);
5122 my $vmlist = config_list
();
5123 foreach my $vmid (keys %$vmlist) {
5127 lock_config
($vmid, $updatefn, $vmid);
5133 sub restore_vma_archive
{
5134 my ($archive, $vmid, $user, $opts, $comp) = @_;
5136 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5137 my $readfrom = $archive;
5142 my $qarchive = PVE
::Tools
::shellquote
($archive);
5143 if ($comp eq 'gzip') {
5144 $uncomp = "zcat $qarchive|";
5145 } elsif ($comp eq 'lzop') {
5146 $uncomp = "lzop -d -c $qarchive|";
5148 die "unknown compression method '$comp'\n";
5153 my $tmpdir = "/var/tmp/vzdumptmp$$";
5156 # disable interrupts (always do cleanups)
5157 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5158 warn "got interrupt - ignored\n";
5161 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5162 POSIX
::mkfifo
($mapfifo, 0600);
5165 my $openfifo = sub {
5166 open($fifofh, '>', $mapfifo) || die $!;
5169 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5176 my $rpcenv = PVE
::RPCEnvironment
::get
();
5178 my $conffile = config_file
($vmid);
5179 my $tmpfn = "$conffile.$$.tmp";
5181 # Note: $oldconf is undef if VM does not exists
5182 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5184 my $print_devmap = sub {
5185 my $virtdev_hash = {};
5187 my $cfgfn = "$tmpdir/qemu-server.conf";
5189 # we can read the config - that is already extracted
5190 my $fh = IO
::File-
>new($cfgfn, "r") ||
5191 "unable to read qemu-server.conf - $!\n";
5193 while (defined(my $line = <$fh>)) {
5194 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5195 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5196 die "archive does not contain data for drive '$virtdev'\n"
5197 if !$devinfo->{$devname};
5198 if (defined($opts->{storage
})) {
5199 $storeid = $opts->{storage
} || 'local';
5200 } elsif (!$storeid) {
5203 $format = 'raw' if !$format;
5204 $devinfo->{$devname}->{devname
} = $devname;
5205 $devinfo->{$devname}->{virtdev
} = $virtdev;
5206 $devinfo->{$devname}->{format
} = $format;
5207 $devinfo->{$devname}->{storeid
} = $storeid;
5209 # check permission on storage
5210 my $pool = $opts->{pool
}; # todo: do we need that?
5211 if ($user ne 'root@pam') {
5212 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5215 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5219 foreach my $devname (keys %$devinfo) {
5220 die "found no device mapping information for device '$devname'\n"
5221 if !$devinfo->{$devname}->{virtdev
};
5224 my $cfg = cfs_read_file
('storage.cfg');
5226 # create empty/temp config
5228 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5229 foreach_drive
($oldconf, sub {
5230 my ($ds, $drive) = @_;
5232 return if drive_is_cdrom
($drive);
5234 my $volid = $drive->{file
};
5236 return if !$volid || $volid =~ m
|^/|;
5238 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5239 return if !$path || !$owner || ($owner != $vmid);
5241 # Note: only delete disk we want to restore
5242 # other volumes will become unused
5243 if ($virtdev_hash->{$ds}) {
5244 PVE
::Storage
::vdisk_free
($cfg, $volid);
5250 foreach my $virtdev (sort keys %$virtdev_hash) {
5251 my $d = $virtdev_hash->{$virtdev};
5252 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5253 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5255 # test if requested format is supported
5256 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5257 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5258 $d->{format
} = $defFormat if !$supported;
5260 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5261 $d->{format
}, undef, $alloc_size);
5262 print STDERR
"new volume ID is '$volid'\n";
5263 $d->{volid
} = $volid;
5264 my $path = PVE
::Storage
::path
($cfg, $volid);
5266 my $write_zeros = 1;
5267 # fixme: what other storages types initialize volumes with zero?
5268 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5269 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5273 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5275 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5276 $map->{$virtdev} = $volid;
5279 $fh->seek(0, 0) || die "seek failed - $!\n";
5281 my $outfd = new IO
::File
($tmpfn, "w") ||
5282 die "unable to write config for VM $vmid\n";
5284 my $cookie = { netcount
=> 0 };
5285 while (defined(my $line = <$fh>)) {
5286 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5295 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5296 die "interrupted by signal\n";
5298 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5300 $oldtimeout = alarm($timeout);
5307 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5308 my ($dev_id, $size, $devname) = ($1, $2, $3);
5309 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5310 } elsif ($line =~ m/^CTIME: /) {
5311 # we correctly received the vma config, so we can disable
5312 # the timeout now for disk allocation (set to 10 minutes, so
5313 # that we always timeout if something goes wrong)
5316 print $fifofh "done\n";
5317 my $tmp = $oldtimeout || 0;
5318 $oldtimeout = undef;
5324 print "restore vma archive: $cmd\n";
5325 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5329 alarm($oldtimeout) if $oldtimeout;
5337 my $cfg = cfs_read_file
('storage.cfg');
5338 foreach my $devname (keys %$devinfo) {
5339 my $volid = $devinfo->{$devname}->{volid
};
5342 if ($volid =~ m
|^/|) {
5343 unlink $volid || die 'unlink failed\n';
5345 PVE
::Storage
::vdisk_free
($cfg, $volid);
5347 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5349 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5356 rename($tmpfn, $conffile) ||
5357 die "unable to commit configuration file '$conffile'\n";
5359 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5361 eval { rescan
($vmid, 1); };
5365 sub restore_tar_archive
{
5366 my ($archive, $vmid, $user, $opts) = @_;
5368 if ($archive ne '-') {
5369 my $firstfile = tar_archive_read_firstfile
($archive);
5370 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5371 if $firstfile ne 'qemu-server.conf';
5374 my $storecfg = cfs_read_file
('storage.cfg');
5376 # destroy existing data - keep empty config
5377 my $vmcfgfn = config_file
($vmid);
5378 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5380 my $tocmd = "/usr/lib/qemu-server/qmextract";
5382 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5383 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5384 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5385 $tocmd .= ' --info' if $opts->{info
};
5387 # tar option "xf" does not autodetect compression when read from STDIN,
5388 # so we pipe to zcat
5389 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5390 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5392 my $tmpdir = "/var/tmp/vzdumptmp$$";
5395 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5396 local $ENV{VZDUMP_VMID
} = $vmid;
5397 local $ENV{VZDUMP_USER
} = $user;
5399 my $conffile = config_file
($vmid);
5400 my $tmpfn = "$conffile.$$.tmp";
5402 # disable interrupts (always do cleanups)
5403 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5404 print STDERR
"got interrupt - ignored\n";
5409 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5410 die "interrupted by signal\n";
5413 if ($archive eq '-') {
5414 print "extracting archive from STDIN\n";
5415 run_command
($cmd, input
=> "<&STDIN");
5417 print "extracting archive '$archive'\n";
5421 return if $opts->{info
};
5425 my $statfile = "$tmpdir/qmrestore.stat";
5426 if (my $fd = IO
::File-
>new($statfile, "r")) {
5427 while (defined (my $line = <$fd>)) {
5428 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5429 $map->{$1} = $2 if $1;
5431 print STDERR
"unable to parse line in statfile - $line\n";
5437 my $confsrc = "$tmpdir/qemu-server.conf";
5439 my $srcfd = new IO
::File
($confsrc, "r") ||
5440 die "unable to open file '$confsrc'\n";
5442 my $outfd = new IO
::File
($tmpfn, "w") ||
5443 die "unable to write config for VM $vmid\n";
5445 my $cookie = { netcount
=> 0 };
5446 while (defined (my $line = <$srcfd>)) {
5447 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5459 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5466 rename $tmpfn, $conffile ||
5467 die "unable to commit configuration file '$conffile'\n";
5469 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5471 eval { rescan
($vmid, 1); };
5476 # Internal snapshots
5478 # NOTE: Snapshot create/delete involves several non-atomic
5479 # action, and can take a long time.
5480 # So we try to avoid locking the file and use 'lock' variable
5481 # inside the config file instead.
5483 my $snapshot_copy_config = sub {
5484 my ($source, $dest) = @_;
5486 foreach my $k (keys %$source) {
5487 next if $k eq 'snapshots';
5488 next if $k eq 'snapstate';
5489 next if $k eq 'snaptime';
5490 next if $k eq 'vmstate';
5491 next if $k eq 'lock';
5492 next if $k eq 'digest';
5493 next if $k eq 'description';
5494 next if $k =~ m/^unused\d+$/;
5496 $dest->{$k} = $source->{$k};
5500 my $snapshot_apply_config = sub {
5501 my ($conf, $snap) = @_;
5503 # copy snapshot list
5505 snapshots
=> $conf->{snapshots
},
5508 # keep description and list of unused disks
5509 foreach my $k (keys %$conf) {
5510 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5511 $newconf->{$k} = $conf->{$k};
5514 &$snapshot_copy_config($snap, $newconf);
5519 sub foreach_writable_storage
{
5520 my ($conf, $func) = @_;
5524 foreach my $ds (keys %$conf) {
5525 next if !valid_drivename
($ds);
5527 my $drive = parse_drive
($ds, $conf->{$ds});
5529 next if drive_is_cdrom
($drive);
5531 my $volid = $drive->{file
};
5533 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5534 $sidhash->{$sid} = $sid if $sid;
5537 foreach my $sid (sort keys %$sidhash) {
5542 my $alloc_vmstate_volid = sub {
5543 my ($storecfg, $vmid, $conf, $snapname) = @_;
5545 # Note: we try to be smart when selecting a $target storage
5549 # search shared storage first
5550 foreach_writable_storage
($conf, sub {
5552 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5553 return if !$scfg->{shared
};
5555 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5559 # now search local storage
5560 foreach_writable_storage
($conf, sub {
5562 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5563 return if $scfg->{shared
};
5565 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5569 $target = 'local' if !$target;
5571 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5572 # we abort live save after $conf->{memory}, so we need at max twice that space
5573 my $size = $conf->{memory
}*2 + $driver_state_size;
5575 my $name = "vm-$vmid-state-$snapname";
5576 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5577 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5578 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5583 my $snapshot_prepare = sub {
5584 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5588 my $updatefn = sub {
5590 my $conf = load_config
($vmid);
5592 die "you can't take a snapshot if it's a template\n"
5593 if is_template
($conf);
5597 $conf->{lock} = 'snapshot';
5599 die "snapshot name '$snapname' already used\n"
5600 if defined($conf->{snapshots
}->{$snapname});
5602 my $storecfg = PVE
::Storage
::config
();
5603 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5605 $snap = $conf->{snapshots
}->{$snapname} = {};
5607 if ($save_vmstate && check_running
($vmid)) {
5608 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5611 &$snapshot_copy_config($conf, $snap);
5613 $snap->{snapstate
} = "prepare";
5614 $snap->{snaptime
} = time();
5615 $snap->{description
} = $comment if $comment;
5617 # always overwrite machine if we save vmstate. This makes sure we
5618 # can restore it later using correct machine type
5619 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5621 update_config_nolock
($vmid, $conf, 1);
5624 lock_config
($vmid, $updatefn);
5629 my $snapshot_commit = sub {
5630 my ($vmid, $snapname) = @_;
5632 my $updatefn = sub {
5634 my $conf = load_config
($vmid);
5636 die "missing snapshot lock\n"
5637 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5639 my $has_machine_config = defined($conf->{machine
});
5641 my $snap = $conf->{snapshots
}->{$snapname};
5643 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5645 die "wrong snapshot state\n"
5646 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5648 delete $snap->{snapstate
};
5649 delete $conf->{lock};
5651 my $newconf = &$snapshot_apply_config($conf, $snap);
5653 delete $newconf->{machine
} if !$has_machine_config;
5655 $newconf->{parent
} = $snapname;
5657 update_config_nolock
($vmid, $newconf, 1);
5660 lock_config
($vmid, $updatefn);
5663 sub snapshot_rollback
{
5664 my ($vmid, $snapname) = @_;
5668 my $storecfg = PVE
::Storage
::config
();
5670 my $conf = load_config
($vmid);
5672 my $get_snapshot_config = sub {
5674 die "you can't rollback if vm is a template\n" if is_template
($conf);
5676 my $res = $conf->{snapshots
}->{$snapname};
5678 die "snapshot '$snapname' does not exist\n" if !defined($res);
5683 my $snap = &$get_snapshot_config();
5685 foreach_drive
($snap, sub {
5686 my ($ds, $drive) = @_;
5688 return if drive_is_cdrom
($drive);
5690 my $volid = $drive->{file
};
5692 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5695 my $updatefn = sub {
5697 $conf = load_config
($vmid);
5699 $snap = &$get_snapshot_config();
5701 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5702 if $snap->{snapstate
};
5706 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5709 die "unable to rollback vm $vmid: vm is running\n"
5710 if check_running
($vmid);
5713 $conf->{lock} = 'rollback';
5715 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5716 delete $conf->{lock};
5722 my $has_machine_config = defined($conf->{machine
});
5724 # copy snapshot config to current config
5725 $conf = &$snapshot_apply_config($conf, $snap);
5726 $conf->{parent
} = $snapname;
5728 # Note: old code did not store 'machine', so we try to be smart
5729 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5730 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5731 # we remove the 'machine' configuration if not explicitly specified
5732 # in the original config.
5733 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5736 update_config_nolock
($vmid, $conf, 1);
5738 if (!$prepare && $snap->{vmstate
}) {
5739 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5740 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5744 lock_config
($vmid, $updatefn);
5746 foreach_drive
($snap, sub {
5747 my ($ds, $drive) = @_;
5749 return if drive_is_cdrom
($drive);
5751 my $volid = $drive->{file
};
5752 my $device = "drive-$ds";
5754 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5758 lock_config
($vmid, $updatefn);
5761 my $savevm_wait = sub {
5765 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5766 if (!$stat->{status
}) {
5767 die "savevm not active\n";
5768 } elsif ($stat->{status
} eq 'active') {
5771 } elsif ($stat->{status
} eq 'completed') {
5774 die "query-savevm returned status '$stat->{status}'\n";
5779 sub do_snapshots_with_qemu
{
5780 my ($storecfg, $volid) = @_;
5782 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5784 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5788 if ($volid =~ m/\.(qcow2|qed)$/){
5795 sub snapshot_create
{
5796 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5798 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5800 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5802 my $config = load_config
($vmid);
5804 my $running = check_running
($vmid);
5806 my $freezefs = $running && $config->{agent
};
5807 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5812 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5813 warn "guest-fsfreeze-freeze problems - $@" if $@;
5817 # create internal snapshots of all drives
5819 my $storecfg = PVE
::Storage
::config
();
5822 if ($snap->{vmstate
}) {
5823 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5824 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5825 &$savevm_wait($vmid);
5827 vm_mon_cmd
($vmid, "savevm-start");
5831 foreach_drive
($snap, sub {
5832 my ($ds, $drive) = @_;
5834 return if drive_is_cdrom
($drive);
5836 my $volid = $drive->{file
};
5837 my $device = "drive-$ds";
5839 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5840 $drivehash->{$ds} = 1;
5846 eval { vm_mon_cmd
($vmid, "savevm-end") };
5850 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5851 warn "guest-fsfreeze-thaw problems - $@" if $@;
5854 # savevm-end is async, we need to wait
5856 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5857 if (!$stat->{bytes
}) {
5860 print "savevm not yet finished\n";
5868 warn "snapshot create failed: starting cleanup\n";
5869 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5874 &$snapshot_commit($vmid, $snapname);
5877 # Note: $drivehash is only set when called from snapshot_create.
5878 sub snapshot_delete
{
5879 my ($vmid, $snapname, $force, $drivehash) = @_;
5886 my $unlink_parent = sub {
5887 my ($confref, $new_parent) = @_;
5889 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5891 $confref->{parent
} = $new_parent;
5893 delete $confref->{parent
};
5898 my $updatefn = sub {
5899 my ($remove_drive) = @_;
5901 my $conf = load_config
($vmid);
5905 die "you can't delete a snapshot if vm is a template\n"
5906 if is_template
($conf);
5909 $snap = $conf->{snapshots
}->{$snapname};
5911 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5913 # remove parent refs
5915 &$unlink_parent($conf, $snap->{parent
});
5916 foreach my $sn (keys %{$conf->{snapshots
}}) {
5917 next if $sn eq $snapname;
5918 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5922 if ($remove_drive) {
5923 if ($remove_drive eq 'vmstate') {
5924 delete $snap->{$remove_drive};
5926 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5927 my $volid = $drive->{file
};
5928 delete $snap->{$remove_drive};
5929 add_unused_volume
($conf, $volid);
5934 $snap->{snapstate
} = 'delete';
5936 delete $conf->{snapshots
}->{$snapname};
5937 delete $conf->{lock} if $drivehash;
5938 foreach my $volid (@$unused) {
5939 add_unused_volume
($conf, $volid);
5943 update_config_nolock
($vmid, $conf, 1);
5946 lock_config
($vmid, $updatefn);
5948 # now remove vmstate file
5950 my $storecfg = PVE
::Storage
::config
();
5952 if ($snap->{vmstate
}) {
5953 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5955 die $err if !$force;
5958 # save changes (remove vmstate from snapshot)
5959 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5962 # now remove all internal snapshots
5963 foreach_drive
($snap, sub {
5964 my ($ds, $drive) = @_;
5966 return if drive_is_cdrom
($drive);
5968 my $volid = $drive->{file
};
5969 my $device = "drive-$ds";
5971 if (!$drivehash || $drivehash->{$ds}) {
5972 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
5974 die $err if !$force;
5979 # save changes (remove drive fron snapshot)
5980 lock_config
($vmid, $updatefn, $ds) if !$force;
5981 push @$unused, $volid;
5984 # now cleanup config
5986 lock_config
($vmid, $updatefn);
5990 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
5993 foreach_drive
($conf, sub {
5994 my ($ds, $drive) = @_;
5996 return if drive_is_cdrom
($drive);
5997 my $volid = $drive->{file
};
5998 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6001 return $err ?
0 : 1;
6004 sub template_create
{
6005 my ($vmid, $conf, $disk) = @_;
6007 my $storecfg = PVE
::Storage
::config
();
6009 foreach_drive
($conf, sub {
6010 my ($ds, $drive) = @_;
6012 return if drive_is_cdrom
($drive);
6013 return if $disk && $ds ne $disk;
6015 my $volid = $drive->{file
};
6016 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6018 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6019 $drive->{file
} = $voliddst;
6020 $conf->{$ds} = print_drive
($vmid, $drive);
6021 update_config_nolock
($vmid, $conf, 1);
6028 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6031 sub qemu_img_convert
{
6032 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6034 my $storecfg = PVE
::Storage
::config
();
6035 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6036 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6038 if ($src_storeid && $dst_storeid) {
6039 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6040 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6042 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6043 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6045 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6046 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6049 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6050 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6051 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6055 if($line =~ m/\((\S+)\/100\
%\)/){
6057 my $transferred = int($size * $percent / 100);
6058 my $remaining = $size - $transferred;
6060 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6065 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6067 die "copy failed: $err" if $err;
6071 sub qemu_img_format
{
6072 my ($scfg, $volname) = @_;
6074 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
6076 } elsif ($scfg->{type
} eq 'iscsi') {
6077 return "host_device";
6083 sub qemu_drive_mirror
{
6084 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6086 my $storecfg = PVE
::Storage
::config
();
6087 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6089 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6092 if ($dst_volname =~ m/\.(raw|qcow2)$/){
6096 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6098 #drive-mirror is doing lseek on source image before starting, and this can take a lot of time for big nfs volume
6099 #during this time, qmp socket is hanging
6100 #http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg01838.html
6101 #so we need to setup a big timeout
6102 my $opts = { timeout
=> 14400, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6103 $opts->{format
} = $format if $format;
6105 print "drive mirror is starting : this step can take some minutes/hours, depend of disk size and storage speed\n";
6107 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6110 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6111 my $stat = @$stats[0];
6112 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6113 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6115 my $busy = $stat->{busy
};
6116 my $ready = $stat->{ready
};
6118 if (my $total = $stat->{len
}) {
6119 my $transferred = $stat->{offset
} || 0;
6120 my $remaining = $total - $transferred;
6121 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6123 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6127 if ($stat->{ready
} eq 'true') {
6129 last if $vmiddst != $vmid;
6131 # try to switch the disk if source and destination are on the same guest
6132 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6134 die $@ if $@ !~ m/cannot be completed/;
6143 my $cancel_job = sub {
6144 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6146 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6147 my $stat = @$stats[0];
6154 eval { &$cancel_job(); };
6155 die "mirroring error: $err";
6158 if ($vmiddst != $vmid) {
6159 # if we clone a disk for a new target vm, we don't switch the disk
6160 &$cancel_job(); # so we call block-job-cancel
6165 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6166 $newvmid, $storage, $format, $full, $newvollist) = @_;
6171 print "create linked clone of drive $drivename ($drive->{file})\n";
6172 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6173 push @$newvollist, $newvolid;
6175 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6176 $storeid = $storage if $storage;
6178 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6180 $format = $drive->{format
} || $defFormat;
6183 # test if requested format is supported - else use default
6184 my $supported = grep { $_ eq $format } @$validFormats;
6185 $format = $defFormat if !$supported;
6187 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6189 print "create full clone of drive $drivename ($drive->{file})\n";
6190 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6191 push @$newvollist, $newvolid;
6193 if (!$running || $snapname) {
6194 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6196 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6200 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6203 $disk->{format
} = undef;
6204 $disk->{file
} = $newvolid;
6205 $disk->{size
} = $size;
6210 # this only works if VM is running
6211 sub get_current_qemu_machine
{
6214 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6215 my $res = vm_qmp_command
($vmid, $cmd);
6217 my ($current, $default);
6218 foreach my $e (@$res) {
6219 $default = $e->{name
} if $e->{'is-default'};
6220 $current = $e->{name
} if $e->{'is-current'};
6223 # fallback to the default machine if current is not supported by qemu
6224 return $current || $default || 'pc';
6227 sub qemu_machine_feature_enabled
{
6228 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6233 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6235 $current_major = $3;
6236 $current_minor = $4;
6238 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6240 $current_major = $1;
6241 $current_minor = $2;
6244 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6253 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6254 my (undef, $id, $function) = @_;
6255 my $res = { id
=> $id, function
=> $function};
6256 push @{$devices->{$id}}, $res;
6262 sub vm_iothreads_list
{
6265 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6268 foreach my $iothread (@$res) {
6269 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6276 my ($conf, $drive) = @_;
6280 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6282 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6288 my $controller = int($drive->{index} / $maxdev);
6289 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6291 return ($maxdev, $controller, $controller_prefix);