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 $spice_port = PVE
::Tools
::next_spice_port
();
3025 push @$devices, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3027 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3028 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3029 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3032 # enable balloon by default, unless explicitly disabled
3033 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3034 $pciaddr = print_pci_addr
("balloon0", $bridges);
3035 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3038 if ($conf->{watchdog
}) {
3039 my $wdopts = parse_watchdog
($conf->{watchdog
});
3040 $pciaddr = print_pci_addr
("watchdog", $bridges);
3041 my $watchdog = $wdopts->{model
} || 'i6300esb';
3042 push @$devices, '-device', "$watchdog$pciaddr";
3043 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3047 my $scsicontroller = {};
3048 my $ahcicontroller = {};
3049 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3051 # Add iscsi initiator name if available
3052 if (my $initiator = get_initiator_name
()) {
3053 push @$devices, '-iscsi', "initiator-name=$initiator";
3056 foreach_drive
($conf, sub {
3057 my ($ds, $drive) = @_;
3059 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3060 push @$vollist, $drive->{file
};
3063 $use_virtio = 1 if $ds =~ m/^virtio/;
3065 if (drive_is_cdrom
($drive)) {
3066 if ($bootindex_hash->{d
}) {
3067 $drive->{bootindex
} = $bootindex_hash->{d
};
3068 $bootindex_hash->{d
} += 1;
3071 if ($bootindex_hash->{c
}) {
3072 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3073 $bootindex_hash->{c
} += 1;
3077 if($drive->{interface
} eq 'virtio'){
3078 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3081 if ($drive->{interface
} eq 'scsi') {
3083 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3085 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3086 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3089 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3090 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3091 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3095 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3096 $queues = ",num_queues=$drive->{queues}";
3099 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3100 $scsicontroller->{$controller}=1;
3103 if ($drive->{interface
} eq 'sata') {
3104 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3105 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3106 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3107 $ahcicontroller->{$controller}=1;
3110 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3111 push @$devices, '-drive',$drive_cmd;
3112 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3115 for (my $i = 0; $i < $MAX_NETS; $i++) {
3116 next if !$conf->{"net$i"};
3117 my $d = parse_net
($conf->{"net$i"});
3120 $use_virtio = 1 if $d->{model
} eq 'virtio';
3122 if ($bootindex_hash->{n
}) {
3123 $d->{bootindex
} = $bootindex_hash->{n
};
3124 $bootindex_hash->{n
} += 1;
3127 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3128 push @$devices, '-netdev', $netdevfull;
3130 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3131 push @$devices, '-device', $netdevicefull;
3136 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3141 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3143 while (my ($k, $v) = each %$bridges) {
3144 $pciaddr = print_pci_addr
("pci.$k");
3145 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3149 # hack: virtio with fairsched is unreliable, so we do not use fairsched
3150 # when the VM uses virtio devices.
3151 if (!$use_virtio && $have_ovz) {
3153 my $cpuunits = defined($conf->{cpuunits
}) ?
3154 $conf->{cpuunits
} : $defaults->{cpuunits
};
3156 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
3158 # fixme: cpulimit is currently ignored
3159 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
3163 if ($conf->{args
}) {
3164 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3168 push @$cmd, @$devices;
3169 push @$cmd, '-rtc', join(',', @$rtcFlags)
3170 if scalar(@$rtcFlags);
3171 push @$cmd, '-machine', join(',', @$machineFlags)
3172 if scalar(@$machineFlags);
3173 push @$cmd, '-global', join(',', @$globalFlags)
3174 if scalar(@$globalFlags);
3176 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3181 return "${var_run_tmpdir}/$vmid.vnc";
3187 my $res = vm_mon_cmd
($vmid, 'query-spice');
3189 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3193 my ($vmid, $qga) = @_;
3194 my $sockettype = $qga ?
'qga' : 'qmp';
3195 return "${var_run_tmpdir}/$vmid.$sockettype";
3200 return "${var_run_tmpdir}/$vmid.pid";
3203 sub vm_devices_list
{
3206 my $res = vm_mon_cmd
($vmid, 'query-pci');
3208 foreach my $pcibus (@$res) {
3209 foreach my $device (@{$pcibus->{devices
}}) {
3210 next if !$device->{'qdev_id'};
3211 if ($device->{'pci_bridge'}) {
3212 $devices->{$device->{'qdev_id'}} = 1;
3213 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3214 next if !$bridge_device->{'qdev_id'};
3215 $devices->{$bridge_device->{'qdev_id'}} = 1;
3216 $devices->{$device->{'qdev_id'}}++;
3219 $devices->{$device->{'qdev_id'}} = 1;
3224 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3225 foreach my $block (@$resblock) {
3226 if($block->{device
} =~ m/^drive-(\S+)/){
3231 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3232 foreach my $mice (@$resmice) {
3233 if ($mice->{name
} eq 'QEMU HID Tablet') {
3234 $devices->{tablet
} = 1;
3243 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3245 my $q35 = machine_type_is_q35
($conf);
3247 my $devices_list = vm_devices_list
($vmid);
3248 return 1 if defined($devices_list->{$deviceid});
3250 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3252 if ($deviceid eq 'tablet') {
3254 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3256 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3258 qemu_iothread_add
($vmid, $deviceid, $device);
3260 qemu_driveadd
($storecfg, $vmid, $device);
3261 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3263 qemu_deviceadd
($vmid, $devicefull);
3264 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3266 eval { qemu_drivedel
($vmid, $deviceid); };
3271 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3274 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3275 my $pciaddr = print_pci_addr
($deviceid);
3276 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3278 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3280 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3281 qemu_iothread_add
($vmid, $deviceid, $device);
3282 $devicefull .= ",iothread=iothread-$deviceid";
3285 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3286 $devicefull .= ",num_queues=$device->{queues}";
3289 qemu_deviceadd
($vmid, $devicefull);
3290 qemu_deviceaddverify
($vmid, $deviceid);
3292 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3294 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3295 qemu_driveadd
($storecfg, $vmid, $device);
3297 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3298 eval { qemu_deviceadd
($vmid, $devicefull); };
3300 eval { qemu_drivedel
($vmid, $deviceid); };
3305 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3307 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3308 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3309 qemu_deviceadd
($vmid, $netdevicefull);
3310 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3312 eval { qemu_netdevdel
($vmid, $deviceid); };
3317 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3320 my $pciaddr = print_pci_addr
($deviceid);
3321 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3323 qemu_deviceadd
($vmid, $devicefull);
3324 qemu_deviceaddverify
($vmid, $deviceid);
3327 die "can't hotplug device '$deviceid'\n";
3333 # fixme: this should raise exceptions on error!
3334 sub vm_deviceunplug
{
3335 my ($vmid, $conf, $deviceid) = @_;
3337 my $devices_list = vm_devices_list
($vmid);
3338 return 1 if !defined($devices_list->{$deviceid});
3340 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3342 if ($deviceid eq 'tablet') {
3344 qemu_devicedel
($vmid, $deviceid);
3346 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3348 qemu_devicedel
($vmid, $deviceid);
3349 qemu_devicedelverify
($vmid, $deviceid);
3350 qemu_drivedel
($vmid, $deviceid);
3351 qemu_iothread_del
($conf, $vmid, $deviceid);
3353 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3355 qemu_devicedel
($vmid, $deviceid);
3356 qemu_devicedelverify
($vmid, $deviceid);
3357 qemu_iothread_del
($conf, $vmid, $deviceid);
3359 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3361 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3362 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3363 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3365 qemu_devicedel
($vmid, $deviceid);
3366 qemu_drivedel
($vmid, $deviceid);
3367 qemu_deletescsihw
($conf, $vmid, $deviceid);
3369 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3371 qemu_devicedel
($vmid, $deviceid);
3372 qemu_devicedelverify
($vmid, $deviceid);
3373 qemu_netdevdel
($vmid, $deviceid);
3376 die "can't unplug device '$deviceid'\n";
3382 sub qemu_deviceadd
{
3383 my ($vmid, $devicefull) = @_;
3385 $devicefull = "driver=".$devicefull;
3386 my %options = split(/[=,]/, $devicefull);
3388 vm_mon_cmd
($vmid, "device_add" , %options);
3391 sub qemu_devicedel
{
3392 my ($vmid, $deviceid) = @_;
3394 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3397 sub qemu_iothread_add
{
3398 my($vmid, $deviceid, $device) = @_;
3400 if ($device->{iothread
}) {
3401 my $iothreads = vm_iothreads_list
($vmid);
3402 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3406 sub qemu_iothread_del
{
3407 my($conf, $vmid, $deviceid) = @_;
3409 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3410 if ($device->{iothread
}) {
3411 my $iothreads = vm_iothreads_list
($vmid);
3412 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3416 sub qemu_objectadd
{
3417 my($vmid, $objectid, $qomtype) = @_;
3419 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3424 sub qemu_objectdel
{
3425 my($vmid, $objectid) = @_;
3427 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3433 my ($storecfg, $vmid, $device) = @_;
3435 my $drive = print_drive_full
($storecfg, $vmid, $device);
3436 $drive =~ s/\\/\\\\/g;
3437 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3439 # If the command succeeds qemu prints: "OK
"
3440 return 1 if $ret =~ m/OK/s;
3442 die "adding drive failed
: $ret\n";
3446 my($vmid, $deviceid) = @_;
3448 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3451 return 1 if $ret eq "";
3453 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3454 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3456 die "deleting drive
$deviceid failed
: $ret\n";
3459 sub qemu_deviceaddverify {
3460 my ($vmid, $deviceid) = @_;
3462 for (my $i = 0; $i <= 5; $i++) {
3463 my $devices_list = vm_devices_list($vmid);
3464 return 1 if defined($devices_list->{$deviceid});
3468 die "error on hotplug device
'$deviceid'\n";
3472 sub qemu_devicedelverify {
3473 my ($vmid, $deviceid) = @_;
3475 # need to verify that the device is correctly removed as device_del
3476 # is async and empty return is not reliable
3478 for (my $i = 0; $i <= 5; $i++) {
3479 my $devices_list = vm_devices_list($vmid);
3480 return 1 if !defined($devices_list->{$deviceid});
3484 die "error on hot-unplugging device
'$deviceid'\n";
3487 sub qemu_findorcreatescsihw {
3488 my ($storecfg, $conf, $vmid, $device) = @_;
3490 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3492 my $scsihwid="$controller_prefix$controller";
3493 my $devices_list = vm_devices_list($vmid);
3495 if(!defined($devices_list->{$scsihwid})) {
3496 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3502 sub qemu_deletescsihw {
3503 my ($conf, $vmid, $opt) = @_;
3505 my $device = parse_drive($opt, $conf->{$opt});
3507 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3508 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3512 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3514 my $devices_list = vm_devices_list($vmid);
3515 foreach my $opt (keys %{$devices_list}) {
3516 if (PVE::QemuServer::valid_drivename($opt)) {
3517 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3518 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3524 my $scsihwid="scsihw
$controller";
3526 vm_deviceunplug($vmid, $conf, $scsihwid);
3531 sub qemu_add_pci_bridge {
3532 my ($storecfg, $conf, $vmid, $device) = @_;
3538 print_pci_addr($device, $bridges);
3540 while (my ($k, $v) = each %$bridges) {
3543 return 1 if !defined($bridgeid) || $bridgeid < 1;
3545 my $bridge = "pci
.$bridgeid";
3546 my $devices_list = vm_devices_list($vmid);
3548 if (!defined($devices_list->{$bridge})) {
3549 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3555 sub qemu_set_link_status {
3556 my ($vmid, $device, $up) = @_;
3558 vm_mon_cmd($vmid, "set_link
", name => $device,
3559 up => $up ? JSON::true : JSON::false);
3562 sub qemu_netdevadd {
3563 my ($vmid, $conf, $device, $deviceid) = @_;
3565 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3566 my %options = split(/[=,]/, $netdev);
3568 vm_mon_cmd($vmid, "netdev_add
", %options);
3572 sub qemu_netdevdel {
3573 my ($vmid, $deviceid) = @_;
3575 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3578 sub qemu_cpu_hotplug {
3579 my ($vmid, $conf, $vcpus) = @_;
3582 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3583 $sockets = $conf->{sockets} if $conf->{sockets};
3584 my $cores = $conf->{cores} || 1;
3585 my $maxcpus = $sockets * $cores;
3587 $vcpus = $maxcpus if !$vcpus;
3589 die "you can
't add more vcpus than maxcpus\n"
3590 if $vcpus > $maxcpus;
3592 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3593 die "online cpu unplug is not yet possible\n"
3594 if $vcpus < $currentvcpus;
3596 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3597 die "vcpus in running vm is different than configuration\n"
3598 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3600 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3601 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3605 sub qemu_memory_hotplug {
3606 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3608 return $value if !check_running($vmid);
3610 my $memory = $conf->{memory} || $defaults->{memory};
3611 $value = $defaults->{memory} if !$value;
3612 return $value if $value == $memory;
3614 my $static_memory = $STATICMEM;
3615 my $dimm_memory = $memory - $static_memory;
3617 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3618 die "memory unplug
is not yet available
" if $value < $memory;
3619 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3623 $sockets = $conf->{sockets} if $conf->{sockets};
3625 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3626 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3628 return if $current_size <= $conf->{memory};
3630 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3632 eval { qemu_objectdel($vmid, "mem-
$name"); };
3636 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3638 eval { qemu_objectdel($vmid, "mem-
$name"); };
3641 #update conf after each succesful module hotplug
3642 $conf->{memory} = $current_size;
3643 update_config_nolock($vmid, $conf, 1);
3647 sub qemu_block_set_io_throttle {
3648 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3650 return if !check_running($vmid) ;
3652 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));
3656 # old code, only used to shutdown old VM after update
3658 my ($fh, $timeout) = @_;
3660 my $sel = new IO::Select;
3667 while (scalar (@ready = $sel->can_read($timeout))) {
3669 if ($count = $fh->sysread($buf, 8192)) {
3670 if ($buf =~ /^(.*)\(qemu\) $/s) {
3677 if (!defined($count)) {
3684 die "monitor
read timeout
\n" if !scalar(@ready);
3689 # old code, only used to shutdown old VM after update
3690 sub vm_monitor_command {
3691 my ($vmid, $cmdstr, $nocheck) = @_;
3696 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3698 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3700 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3701 die "unable to
connect to VM
$vmid socket - $!\n";
3705 # hack: migrate sometime blocks the monitor (when migrate_downtime
3707 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3708 $timeout = 60*60; # 1 hour
3712 my $data = __read_avail($sock, $timeout);
3714 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3715 die "got unexpected qemu monitor banner
\n";
3718 my $sel = new IO::Select;
3721 if (!scalar(my @ready = $sel->can_write($timeout))) {
3722 die "monitor
write error
- timeout
";
3725 my $fullcmd = "$cmdstr\r";
3727 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3730 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3731 die "monitor
write error
- $!";
3734 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3738 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3739 $timeout = 60*60; # 1 hour
3740 } elsif ($cmdstr =~ m/^(eject|change)/) {
3741 $timeout = 60; # note: cdrom mount command is slow
3743 if ($res = __read_avail($sock, $timeout)) {
3745 my @lines = split("\r?
\n", $res);
3747 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3749 $res = join("\n", @lines);
3757 syslog("err
", "VM
$vmid monitor command failed
- $err");
3764 sub qemu_block_resize {
3765 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3767 my $running = check_running($vmid);
3769 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3771 return if !$running;
3773 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3777 sub qemu_volume_snapshot {
3778 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3780 my $running = check_running($vmid);
3782 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3783 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3785 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3789 sub qemu_volume_snapshot_delete {
3790 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3792 my $running = check_running($vmid);
3794 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3796 return if !$running;
3798 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3801 sub set_migration_caps {
3807 "auto-converge
" => 1,
3809 "x-rdma-pin-all
" => 0,
3813 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3815 for my $supported_capability (@$supported_capabilities) {
3817 capability => $supported_capability->{capability},
3818 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3822 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3825 my $fast_plug_option = {
3833 # hotplug changes in [PENDING]
3834 # $selection hash can be used to only apply specified options, for
3835 # example: { cores => 1 } (only apply changed 'cores')
3836 # $errors ref is used to return error messages
3837 sub vmconfig_hotplug_pending {
3838 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3840 my $defaults = load_defaults();
3842 # commit values which do not have any impact on running VM first
3843 # Note: those option cannot raise errors, we we do not care about
3844 # $selection and always apply them.
3846 my $add_error = sub {
3847 my ($opt, $msg) = @_;
3848 $errors->{$opt} = "hotplug problem
- $msg";
3852 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3853 if ($fast_plug_option->{$opt}) {
3854 $conf->{$opt} = $conf->{pending}->{$opt};
3855 delete $conf->{pending}->{$opt};
3861 update_config_nolock($vmid, $conf, 1);
3862 $conf = load_config($vmid); # update/reload
3865 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3867 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3868 foreach my $opt (@delete) {
3869 next if $selection && !$selection->{$opt};
3871 if ($opt eq 'hotplug') {
3872 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3873 } elsif ($opt eq 'tablet') {
3874 die "skip
\n" if !$hotplug_features->{usb};
3875 if ($defaults->{tablet}) {
3876 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3878 vm_deviceunplug($vmid, $conf, $opt);
3880 } elsif ($opt eq 'vcpus') {
3881 die "skip
\n" if !$hotplug_features->{cpu};
3882 qemu_cpu_hotplug($vmid, $conf, undef);
3883 } elsif ($opt eq 'balloon') {
3884 # enable balloon device is not hotpluggable
3885 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3886 } elsif ($fast_plug_option->{$opt}) {
3888 } elsif ($opt =~ m/^net(\d+)$/) {
3889 die "skip
\n" if !$hotplug_features->{network};
3890 vm_deviceunplug($vmid, $conf, $opt);
3891 } elsif (valid_drivename($opt)) {
3892 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3893 vm_deviceunplug($vmid, $conf, $opt);
3894 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3895 } elsif ($opt =~ m/^memory$/) {
3896 die "skip
\n" if !$hotplug_features->{memory};
3897 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3903 &$add_error($opt, $err) if $err ne "skip
\n";
3905 # save new config if hotplug was successful
3906 delete $conf->{$opt};
3907 vmconfig_undelete_pending_option($conf, $opt);
3908 update_config_nolock($vmid, $conf, 1);
3909 $conf = load_config($vmid); # update/reload
3913 foreach my $opt (keys %{$conf->{pending}}) {
3914 next if $selection && !$selection->{$opt};
3915 my $value = $conf->{pending}->{$opt};
3917 if ($opt eq 'hotplug') {
3918 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3919 } elsif ($opt eq 'tablet') {
3920 die "skip
\n" if !$hotplug_features->{usb};
3922 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3923 } elsif ($value == 0) {
3924 vm_deviceunplug($vmid, $conf, $opt);
3926 } elsif ($opt eq 'vcpus') {
3927 die "skip
\n" if !$hotplug_features->{cpu};
3928 qemu_cpu_hotplug($vmid, $conf, $value);
3929 } elsif ($opt eq 'balloon') {
3930 # enable/disable balloning device is not hotpluggable
3931 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3932 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3933 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3935 # allow manual ballooning if shares is set to zero
3936 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3937 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3938 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3940 } elsif ($opt =~ m/^net(\d+)$/) {
3941 # some changes can be done without hotplug
3942 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3943 $vmid, $opt, $value);
3944 } elsif (valid_drivename($opt)) {
3945 # some changes can be done without hotplug
3946 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3947 $vmid, $opt, $value, 1);
3948 } elsif ($opt =~ m/^memory$/) { #dimms
3949 die "skip
\n" if !$hotplug_features->{memory};
3950 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3952 die "skip
\n"; # skip non-hot-pluggable options
3956 &$add_error($opt, $err) if $err ne "skip
\n";
3958 # save new config if hotplug was successful
3959 $conf->{$opt} = $value;
3960 delete $conf->{pending}->{$opt};
3961 update_config_nolock($vmid, $conf, 1);
3962 $conf = load_config($vmid); # update/reload
3967 sub vmconfig_apply_pending {
3968 my ($vmid, $conf, $storecfg) = @_;
3972 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3973 foreach my $opt (@delete) { # delete
3974 die "internal error
" if $opt =~ m/^unused/;
3975 $conf = load_config($vmid); # update/reload
3976 if (!defined($conf->{$opt})) {
3977 vmconfig_undelete_pending_option($conf, $opt);
3978 update_config_nolock($vmid, $conf, 1);
3979 } elsif (valid_drivename($opt)) {
3980 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3981 vmconfig_undelete_pending_option($conf, $opt);
3982 delete $conf->{$opt};
3983 update_config_nolock($vmid, $conf, 1);
3985 vmconfig_undelete_pending_option($conf, $opt);
3986 delete $conf->{$opt};
3987 update_config_nolock($vmid, $conf, 1);
3991 $conf = load_config($vmid); # update/reload
3993 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3994 $conf = load_config($vmid); # update/reload
3996 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
3997 # skip if nothing changed
3998 } elsif (valid_drivename($opt)) {
3999 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4000 if defined($conf->{$opt});
4001 $conf->{$opt} = $conf->{pending}->{$opt};
4003 $conf->{$opt} = $conf->{pending}->{$opt};
4006 delete $conf->{pending}->{$opt};
4007 update_config_nolock($vmid, $conf, 1);
4011 my $safe_num_ne = sub {
4014 return 0 if !defined($a) && !defined($b);
4015 return 1 if !defined($a);
4016 return 1 if !defined($b);
4021 my $safe_string_ne = sub {
4024 return 0 if !defined($a) && !defined($b);
4025 return 1 if !defined($a);
4026 return 1 if !defined($b);
4031 sub vmconfig_update_net {
4032 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4034 my $newnet = parse_net($value);
4036 if ($conf->{$opt}) {
4037 my $oldnet = parse_net($conf->{$opt});
4039 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4040 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4041 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4042 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4044 # for non online change, we try to hot-unplug
4045 die "skip
\n" if !$hotplug;
4046 vm_deviceunplug($vmid, $conf, $opt);
4049 die "internal error
" if $opt !~ m/net(\d+)/;
4050 my $iface = "tap
${vmid
}i
$1";
4052 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4053 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4056 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4057 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4058 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4059 PVE::Network::tap_unplug($iface);
4060 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4063 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4064 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4072 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4078 sub vmconfig_update_disk {
4079 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4081 # fixme: do we need force?
4083 my $drive = parse_drive($opt, $value);
4085 if ($conf->{$opt}) {
4087 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4089 my $media = $drive->{media} || 'disk';
4090 my $oldmedia = $old_drive->{media} || 'disk';
4091 die "unable to change media type
\n" if $media ne $oldmedia;
4093 if (!drive_is_cdrom($old_drive)) {
4095 if ($drive->{file} ne $old_drive->{file}) {
4097 die "skip
\n" if !$hotplug;
4099 # unplug and register as unused
4100 vm_deviceunplug($vmid, $conf, $opt);
4101 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4104 # update existing disk
4106 # skip non hotpluggable value
4107 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4108 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4109 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4110 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4115 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4116 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4117 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4118 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4119 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4120 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4121 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4122 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4123 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4124 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4125 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4126 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4128 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4129 ($drive->{mbps} || 0)*1024*1024,
4130 ($drive->{mbps_rd} || 0)*1024*1024,
4131 ($drive->{mbps_wr} || 0)*1024*1024,
4132 $drive->{iops} || 0,
4133 $drive->{iops_rd} || 0,
4134 $drive->{iops_wr} || 0,
4135 ($drive->{mbps_max} || 0)*1024*1024,
4136 ($drive->{mbps_rd_max} || 0)*1024*1024,
4137 ($drive->{mbps_wr_max} || 0)*1024*1024,
4138 $drive->{iops_max} || 0,
4139 $drive->{iops_rd_max} || 0,
4140 $drive->{iops_wr_max} || 0);
4149 if ($drive->{file} eq 'none') {
4150 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4152 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4153 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4154 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4162 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4164 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4168 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4170 lock_config($vmid, sub {
4171 my $conf = load_config($vmid, $migratedfrom);
4173 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4175 check_lock($conf) if !$skiplock;
4177 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4179 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4180 vmconfig_apply_pending($vmid, $conf, $storecfg);
4181 $conf = load_config($vmid); # update/reload
4184 my $defaults = load_defaults();
4186 # set environment variable useful inside network script
4187 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4189 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4191 my $migrate_port = 0;
4194 if ($statefile eq 'tcp') {
4195 my $localip = "localhost
";
4196 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4197 if ($datacenterconf->{migration_unsecure}) {
4198 my $nodename = PVE::INotify::nodename();
4199 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4201 $migrate_port = PVE::Tools::next_migrate_port();
4202 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4203 push @$cmd, '-incoming', $migrate_uri;
4206 push @$cmd, '-loadstate', $statefile;
4213 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4214 my $d = parse_hostpci($conf->{"hostpci
$i"});
4216 my $pcidevices = $d->{pciid};
4217 foreach my $pcidevice (@$pcidevices) {
4218 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4220 my $info = pci_device_info("0000:$pciid");
4221 die "IOMMU
not present
\n" if !check_iommu_support();
4222 die "no pci device info
for device
'$pciid'\n" if !$info;
4224 if ($d->{driver} && $d->{driver} eq "vfio
") {
4225 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4227 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4230 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4234 PVE::Storage::activate_volumes($storecfg, $vollist);
4236 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4239 die "start failed: $err" if $err;
4241 print "migration listens on $migrate_uri\n" if $migrate_uri;
4243 if ($statefile && $statefile ne 'tcp
') {
4244 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4248 if ($migratedfrom) {
4251 set_migration_caps($vmid);
4256 print "spice listens on port $spice_port\n";
4257 if ($spice_ticket) {
4258 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4259 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4265 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4266 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4267 if $conf->{balloon};
4270 foreach my $opt (keys %$conf) {
4271 next if $opt !~ m/^net\d+$/;
4272 my $nicconf = parse_net($conf->{$opt});
4273 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4277 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4278 path => "machine/peripheral/balloon0",
4279 property => "guest-stats-polling-interval",
4280 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4286 my ($vmid, $execute, %params) = @_;
4288 my $cmd = { execute => $execute, arguments => \%params };
4289 vm_qmp_command($vmid, $cmd);
4292 sub vm_mon_cmd_nocheck {
4293 my ($vmid, $execute, %params) = @_;
4295 my $cmd = { execute => $execute, arguments => \%params };
4296 vm_qmp_command($vmid, $cmd, 1);
4299 sub vm_qmp_command {
4300 my ($vmid, $cmd, $nocheck) = @_;
4305 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4306 $timeout = $cmd->{arguments}->{timeout};
4307 delete $cmd->{arguments}->{timeout};
4311 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4312 my $sname = qmp_socket($vmid);
4313 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4314 my $qmpclient = PVE::QMPClient->new();
4316 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4317 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4318 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4319 if scalar(%{$cmd->{arguments}});
4320 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4322 die "unable to
open monitor
socket\n";
4326 syslog("err
", "VM
$vmid qmp command failed
- $err");
4333 sub vm_human_monitor_command {
4334 my ($vmid, $cmdline) = @_;
4339 execute => 'human-monitor-command',
4340 arguments => { 'command-line' => $cmdline},
4343 return vm_qmp_command($vmid, $cmd);
4346 sub vm_commandline {
4347 my ($storecfg, $vmid) = @_;
4349 my $conf = load_config($vmid);
4351 my $defaults = load_defaults();
4353 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4355 return join(' ', @$cmd);
4359 my ($vmid, $skiplock) = @_;
4361 lock_config($vmid, sub {
4363 my $conf = load_config($vmid);
4365 check_lock($conf) if !$skiplock;
4367 vm_mon_cmd($vmid, "system_reset
");
4371 sub get_vm_volumes {
4375 foreach_volid($conf, sub {
4376 my ($volid, $is_cdrom) = @_;
4378 return if $volid =~ m|^/|;
4380 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4383 push @$vollist, $volid;
4389 sub vm_stop_cleanup {
4390 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4393 fairsched_rmnod($vmid); # try to destroy group
4396 my $vollist = get_vm_volumes($conf);
4397 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4400 foreach my $ext (qw(mon qmp pid vnc qga)) {
4401 unlink "/var/run/qemu-server/${vmid}.$ext";
4404 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4406 warn $@ if $@; # avoid errors - just warn
4409 # Note: use $nockeck to skip tests if VM configuration file exists.
4410 # We need that when migration VMs to other nodes (files already moved)
4411 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4413 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4415 $force = 1 if !defined($force) && !$shutdown;
4418 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4419 kill 15, $pid if $pid;
4420 my $conf = load_config
($vmid, $migratedfrom);
4421 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4425 lock_config
($vmid, sub {
4427 my $pid = check_running
($vmid, $nocheck);
4432 $conf = load_config
($vmid);
4433 check_lock
($conf) if !$skiplock;
4434 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4435 my $opts = parse_startup
($conf->{startup
});
4436 $timeout = $opts->{down
} if $opts->{down
};
4440 $timeout = 60 if !defined($timeout);
4444 if (defined($conf) && $conf->{agent
}) {
4445 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4447 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4450 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4457 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4462 if ($count >= $timeout) {
4464 warn "VM still running - terminating now with SIGTERM\n";
4467 die "VM quit/powerdown failed - got timeout\n";
4470 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4475 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4478 die "VM quit/powerdown failed\n";
4486 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4491 if ($count >= $timeout) {
4492 warn "VM still running - terminating now with SIGKILL\n";
4497 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4502 my ($vmid, $skiplock) = @_;
4504 lock_config
($vmid, sub {
4506 my $conf = load_config
($vmid);
4508 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4510 vm_mon_cmd
($vmid, "stop");
4515 my ($vmid, $skiplock) = @_;
4517 lock_config
($vmid, sub {
4519 my $conf = load_config
($vmid);
4521 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4523 vm_mon_cmd
($vmid, "cont");
4528 my ($vmid, $skiplock, $key) = @_;
4530 lock_config
($vmid, sub {
4532 my $conf = load_config
($vmid);
4534 # there is no qmp command, so we use the human monitor command
4535 vm_human_monitor_command
($vmid, "sendkey $key");
4540 my ($storecfg, $vmid, $skiplock) = @_;
4542 lock_config
($vmid, sub {
4544 my $conf = load_config
($vmid);
4546 check_lock
($conf) if !$skiplock;
4548 if (!check_running
($vmid)) {
4549 fairsched_rmnod
($vmid); # try to destroy group
4550 destroy_vm
($storecfg, $vmid);
4552 die "VM $vmid is running - destroy failed\n";
4560 my ($filename, $buf) = @_;
4562 my $fh = IO
::File-
>new($filename, "w");
4563 return undef if !$fh;
4565 my $res = print $fh $buf;
4572 sub pci_device_info
{
4577 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4578 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4580 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4581 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4583 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4584 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4586 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4587 return undef if !defined($product) || $product !~ s/^0x//;
4592 product
=> $product,
4598 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4607 my $name = $dev->{name
};
4609 my $fn = "$pcisysfs/devices/$name/reset";
4611 return file_write
($fn, "1");
4614 sub pci_dev_bind_to_stub
{
4617 my $name = $dev->{name
};
4619 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4620 return 1 if -d
$testdir;
4622 my $data = "$dev->{vendor} $dev->{product}";
4623 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4625 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4626 if (!file_write
($fn, $name)) {
4627 return undef if -f
$fn;
4630 $fn = "$pcisysfs/drivers/pci-stub/bind";
4631 if (! -d
$testdir) {
4632 return undef if !file_write
($fn, $name);
4638 sub pci_dev_bind_to_vfio
{
4641 my $name = $dev->{name
};
4643 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4645 if (!-d
$vfio_basedir) {
4646 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4648 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4650 my $testdir = "$vfio_basedir/$name";
4651 return 1 if -d
$testdir;
4653 my $data = "$dev->{vendor} $dev->{product}";
4654 return undef if !file_write
("$vfio_basedir/new_id", $data);
4656 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4657 if (!file_write
($fn, $name)) {
4658 return undef if -f
$fn;
4661 $fn = "$vfio_basedir/bind";
4662 if (! -d
$testdir) {
4663 return undef if !file_write
($fn, $name);
4669 sub pci_dev_group_bind_to_vfio
{
4672 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4674 if (!-d
$vfio_basedir) {
4675 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4677 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4679 # get IOMMU group devices
4680 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4681 my @devs = grep /^0000:/, readdir($D);
4684 foreach my $pciid (@devs) {
4685 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4687 # pci bridges, switches or root ports are not supported
4688 # they have a pci_bus subdirectory so skip them
4689 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4691 my $info = pci_device_info
($1);
4692 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4698 sub print_pci_addr
{
4699 my ($id, $bridges) = @_;
4703 piix3
=> { bus
=> 0, addr
=> 1 },
4704 #addr2 : first videocard
4705 balloon0
=> { bus
=> 0, addr
=> 3 },
4706 watchdog
=> { bus
=> 0, addr
=> 4 },
4707 scsihw0
=> { bus
=> 0, addr
=> 5 },
4708 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4709 scsihw1
=> { bus
=> 0, addr
=> 6 },
4710 ahci0
=> { bus
=> 0, addr
=> 7 },
4711 qga0
=> { bus
=> 0, addr
=> 8 },
4712 spice
=> { bus
=> 0, addr
=> 9 },
4713 virtio0
=> { bus
=> 0, addr
=> 10 },
4714 virtio1
=> { bus
=> 0, addr
=> 11 },
4715 virtio2
=> { bus
=> 0, addr
=> 12 },
4716 virtio3
=> { bus
=> 0, addr
=> 13 },
4717 virtio4
=> { bus
=> 0, addr
=> 14 },
4718 virtio5
=> { bus
=> 0, addr
=> 15 },
4719 hostpci0
=> { bus
=> 0, addr
=> 16 },
4720 hostpci1
=> { bus
=> 0, addr
=> 17 },
4721 net0
=> { bus
=> 0, addr
=> 18 },
4722 net1
=> { bus
=> 0, addr
=> 19 },
4723 net2
=> { bus
=> 0, addr
=> 20 },
4724 net3
=> { bus
=> 0, addr
=> 21 },
4725 net4
=> { bus
=> 0, addr
=> 22 },
4726 net5
=> { bus
=> 0, addr
=> 23 },
4727 vga1
=> { bus
=> 0, addr
=> 24 },
4728 vga2
=> { bus
=> 0, addr
=> 25 },
4729 vga3
=> { bus
=> 0, addr
=> 26 },
4730 hostpci2
=> { bus
=> 0, addr
=> 27 },
4731 hostpci3
=> { bus
=> 0, addr
=> 28 },
4732 #addr29 : usb-host (pve-usb.cfg)
4733 'pci.1' => { bus
=> 0, addr
=> 30 },
4734 'pci.2' => { bus
=> 0, addr
=> 31 },
4735 'net6' => { bus
=> 1, addr
=> 1 },
4736 'net7' => { bus
=> 1, addr
=> 2 },
4737 'net8' => { bus
=> 1, addr
=> 3 },
4738 'net9' => { bus
=> 1, addr
=> 4 },
4739 'net10' => { bus
=> 1, addr
=> 5 },
4740 'net11' => { bus
=> 1, addr
=> 6 },
4741 'net12' => { bus
=> 1, addr
=> 7 },
4742 'net13' => { bus
=> 1, addr
=> 8 },
4743 'net14' => { bus
=> 1, addr
=> 9 },
4744 'net15' => { bus
=> 1, addr
=> 10 },
4745 'net16' => { bus
=> 1, addr
=> 11 },
4746 'net17' => { bus
=> 1, addr
=> 12 },
4747 'net18' => { bus
=> 1, addr
=> 13 },
4748 'net19' => { bus
=> 1, addr
=> 14 },
4749 'net20' => { bus
=> 1, addr
=> 15 },
4750 'net21' => { bus
=> 1, addr
=> 16 },
4751 'net22' => { bus
=> 1, addr
=> 17 },
4752 'net23' => { bus
=> 1, addr
=> 18 },
4753 'net24' => { bus
=> 1, addr
=> 19 },
4754 'net25' => { bus
=> 1, addr
=> 20 },
4755 'net26' => { bus
=> 1, addr
=> 21 },
4756 'net27' => { bus
=> 1, addr
=> 22 },
4757 'net28' => { bus
=> 1, addr
=> 23 },
4758 'net29' => { bus
=> 1, addr
=> 24 },
4759 'net30' => { bus
=> 1, addr
=> 25 },
4760 'net31' => { bus
=> 1, addr
=> 26 },
4761 'virtio6' => { bus
=> 2, addr
=> 1 },
4762 'virtio7' => { bus
=> 2, addr
=> 2 },
4763 'virtio8' => { bus
=> 2, addr
=> 3 },
4764 'virtio9' => { bus
=> 2, addr
=> 4 },
4765 'virtio10' => { bus
=> 2, addr
=> 5 },
4766 'virtio11' => { bus
=> 2, addr
=> 6 },
4767 'virtio12' => { bus
=> 2, addr
=> 7 },
4768 'virtio13' => { bus
=> 2, addr
=> 8 },
4769 'virtio14' => { bus
=> 2, addr
=> 9 },
4770 'virtio15' => { bus
=> 2, addr
=> 10 },
4771 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4772 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4773 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4774 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4775 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4776 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4777 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4778 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4779 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4780 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4781 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4782 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4783 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4784 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4785 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4786 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4787 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4788 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4789 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4790 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4791 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4792 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4793 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4794 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4795 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4796 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4797 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4798 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4799 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4800 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4801 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4805 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4806 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4807 my $bus = $devices->{$id}->{bus
};
4808 $res = ",bus=pci.$bus,addr=$addr";
4809 $bridges->{$bus} = 1 if $bridges;
4815 sub print_pcie_addr
{
4820 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4821 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4822 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4823 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4826 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4827 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4828 my $bus = $devices->{$id}->{bus
};
4829 $res = ",bus=$bus,addr=$addr";
4835 # vzdump restore implementaion
4837 sub tar_archive_read_firstfile
{
4838 my $archive = shift;
4840 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4842 # try to detect archive type first
4843 my $pid = open (TMP
, "tar tf '$archive'|") ||
4844 die "unable to open file '$archive'\n";
4845 my $firstfile = <TMP
>;
4849 die "ERROR: archive contaions no data\n" if !$firstfile;
4855 sub tar_restore_cleanup
{
4856 my ($storecfg, $statfile) = @_;
4858 print STDERR
"starting cleanup\n";
4860 if (my $fd = IO
::File-
>new($statfile, "r")) {
4861 while (defined(my $line = <$fd>)) {
4862 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4865 if ($volid =~ m
|^/|) {
4866 unlink $volid || die 'unlink failed\n';
4868 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4870 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4872 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4874 print STDERR
"unable to parse line in statfile - $line";
4881 sub restore_archive
{
4882 my ($archive, $vmid, $user, $opts) = @_;
4884 my $format = $opts->{format
};
4887 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4888 $format = 'tar' if !$format;
4890 } elsif ($archive =~ m/\.tar$/) {
4891 $format = 'tar' if !$format;
4892 } elsif ($archive =~ m/.tar.lzo$/) {
4893 $format = 'tar' if !$format;
4895 } elsif ($archive =~ m/\.vma$/) {
4896 $format = 'vma' if !$format;
4897 } elsif ($archive =~ m/\.vma\.gz$/) {
4898 $format = 'vma' if !$format;
4900 } elsif ($archive =~ m/\.vma\.lzo$/) {
4901 $format = 'vma' if !$format;
4904 $format = 'vma' if !$format; # default
4907 # try to detect archive format
4908 if ($format eq 'tar') {
4909 return restore_tar_archive
($archive, $vmid, $user, $opts);
4911 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4915 sub restore_update_config_line
{
4916 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4918 return if $line =~ m/^\#qmdump\#/;
4919 return if $line =~ m/^\#vzdump\#/;
4920 return if $line =~ m/^lock:/;
4921 return if $line =~ m/^unused\d+:/;
4922 return if $line =~ m/^parent:/;
4923 return if $line =~ m/^template:/; # restored VM is never a template
4925 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4926 # try to convert old 1.X settings
4927 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4928 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4929 my ($model, $macaddr) = split(/\=/, $devconfig);
4930 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4933 bridge
=> "vmbr$ind",
4934 macaddr
=> $macaddr,
4936 my $netstr = print_net
($net);
4938 print $outfd "net$cookie->{netcount}: $netstr\n";
4939 $cookie->{netcount
}++;
4941 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4942 my ($id, $netstr) = ($1, $2);
4943 my $net = parse_net
($netstr);
4944 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4945 $netstr = print_net
($net);
4946 print $outfd "$id: $netstr\n";
4947 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4950 if ($line =~ m/backup=no/) {
4951 print $outfd "#$line";
4952 } elsif ($virtdev && $map->{$virtdev}) {
4953 my $di = parse_drive
($virtdev, $value);
4954 delete $di->{format
}; # format can change on restore
4955 $di->{file
} = $map->{$virtdev};
4956 $value = print_drive
($vmid, $di);
4957 print $outfd "$virtdev: $value\n";
4967 my ($cfg, $vmid) = @_;
4969 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4971 my $volid_hash = {};
4972 foreach my $storeid (keys %$info) {
4973 foreach my $item (@{$info->{$storeid}}) {
4974 next if !($item->{volid
} && $item->{size
});
4975 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4976 $volid_hash->{$item->{volid
}} = $item;
4983 sub get_used_paths
{
4984 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
4988 my $scan_config = sub {
4989 my ($cref, $snapname) = @_;
4991 foreach my $key (keys %$cref) {
4992 my $value = $cref->{$key};
4993 if (valid_drivename
($key)) {
4994 next if $skip_drive && $key eq $skip_drive;
4995 my $drive = parse_drive
($key, $value);
4996 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
4997 if ($drive->{file
} =~ m!^/!) {
4998 $used_path->{$drive->{file
}}++; # = 1;
5000 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5002 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5004 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5005 $used_path->{$path}++; # = 1;
5011 &$scan_config($conf);
5015 if ($scan_snapshots) {
5016 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5017 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5024 sub update_disksize
{
5025 my ($vmid, $conf, $volid_hash) = @_;
5031 # Note: it is allowed to define multiple storages with same path (alias), so
5032 # we need to check both 'volid' and real 'path' (two different volid can point
5033 # to the same path).
5038 foreach my $opt (keys %$conf) {
5039 if (valid_drivename
($opt)) {
5040 my $drive = parse_drive
($opt, $conf->{$opt});
5041 my $volid = $drive->{file
};
5044 $used->{$volid} = 1;
5045 if ($volid_hash->{$volid} &&
5046 (my $path = $volid_hash->{$volid}->{path
})) {
5047 $usedpath->{$path} = 1;
5050 next if drive_is_cdrom
($drive);
5051 next if !$volid_hash->{$volid};
5053 $drive->{size
} = $volid_hash->{$volid}->{size
};
5054 my $new = print_drive
($vmid, $drive);
5055 if ($new ne $conf->{$opt}) {
5057 $conf->{$opt} = $new;
5062 # remove 'unusedX' entry if volume is used
5063 foreach my $opt (keys %$conf) {
5064 next if $opt !~ m/^unused\d+$/;
5065 my $volid = $conf->{$opt};
5066 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5067 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5069 delete $conf->{$opt};
5073 foreach my $volid (sort keys %$volid_hash) {
5074 next if $volid =~ m/vm-$vmid-state-/;
5075 next if $used->{$volid};
5076 my $path = $volid_hash->{$volid}->{path
};
5077 next if !$path; # just to be sure
5078 next if $usedpath->{$path};
5080 add_unused_volume
($conf, $volid);
5081 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5088 my ($vmid, $nolock) = @_;
5090 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5092 my $volid_hash = scan_volids
($cfg, $vmid);
5094 my $updatefn = sub {
5097 my $conf = load_config
($vmid);
5102 foreach my $volid (keys %$volid_hash) {
5103 my $info = $volid_hash->{$volid};
5104 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5107 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5109 update_config_nolock
($vmid, $conf, 1) if $changes;
5112 if (defined($vmid)) {
5116 lock_config
($vmid, $updatefn, $vmid);
5119 my $vmlist = config_list
();
5120 foreach my $vmid (keys %$vmlist) {
5124 lock_config
($vmid, $updatefn, $vmid);
5130 sub restore_vma_archive
{
5131 my ($archive, $vmid, $user, $opts, $comp) = @_;
5133 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5134 my $readfrom = $archive;
5139 my $qarchive = PVE
::Tools
::shellquote
($archive);
5140 if ($comp eq 'gzip') {
5141 $uncomp = "zcat $qarchive|";
5142 } elsif ($comp eq 'lzop') {
5143 $uncomp = "lzop -d -c $qarchive|";
5145 die "unknown compression method '$comp'\n";
5150 my $tmpdir = "/var/tmp/vzdumptmp$$";
5153 # disable interrupts (always do cleanups)
5154 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5155 warn "got interrupt - ignored\n";
5158 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5159 POSIX
::mkfifo
($mapfifo, 0600);
5162 my $openfifo = sub {
5163 open($fifofh, '>', $mapfifo) || die $!;
5166 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5173 my $rpcenv = PVE
::RPCEnvironment
::get
();
5175 my $conffile = config_file
($vmid);
5176 my $tmpfn = "$conffile.$$.tmp";
5178 # Note: $oldconf is undef if VM does not exists
5179 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5181 my $print_devmap = sub {
5182 my $virtdev_hash = {};
5184 my $cfgfn = "$tmpdir/qemu-server.conf";
5186 # we can read the config - that is already extracted
5187 my $fh = IO
::File-
>new($cfgfn, "r") ||
5188 "unable to read qemu-server.conf - $!\n";
5190 while (defined(my $line = <$fh>)) {
5191 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5192 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5193 die "archive does not contain data for drive '$virtdev'\n"
5194 if !$devinfo->{$devname};
5195 if (defined($opts->{storage
})) {
5196 $storeid = $opts->{storage
} || 'local';
5197 } elsif (!$storeid) {
5200 $format = 'raw' if !$format;
5201 $devinfo->{$devname}->{devname
} = $devname;
5202 $devinfo->{$devname}->{virtdev
} = $virtdev;
5203 $devinfo->{$devname}->{format
} = $format;
5204 $devinfo->{$devname}->{storeid
} = $storeid;
5206 # check permission on storage
5207 my $pool = $opts->{pool
}; # todo: do we need that?
5208 if ($user ne 'root@pam') {
5209 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5212 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5216 foreach my $devname (keys %$devinfo) {
5217 die "found no device mapping information for device '$devname'\n"
5218 if !$devinfo->{$devname}->{virtdev
};
5221 my $cfg = cfs_read_file
('storage.cfg');
5223 # create empty/temp config
5225 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5226 foreach_drive
($oldconf, sub {
5227 my ($ds, $drive) = @_;
5229 return if drive_is_cdrom
($drive);
5231 my $volid = $drive->{file
};
5233 return if !$volid || $volid =~ m
|^/|;
5235 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5236 return if !$path || !$owner || ($owner != $vmid);
5238 # Note: only delete disk we want to restore
5239 # other volumes will become unused
5240 if ($virtdev_hash->{$ds}) {
5241 PVE
::Storage
::vdisk_free
($cfg, $volid);
5247 foreach my $virtdev (sort keys %$virtdev_hash) {
5248 my $d = $virtdev_hash->{$virtdev};
5249 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5250 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5252 # test if requested format is supported
5253 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5254 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5255 $d->{format
} = $defFormat if !$supported;
5257 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5258 $d->{format
}, undef, $alloc_size);
5259 print STDERR
"new volume ID is '$volid'\n";
5260 $d->{volid
} = $volid;
5261 my $path = PVE
::Storage
::path
($cfg, $volid);
5263 my $write_zeros = 1;
5264 # fixme: what other storages types initialize volumes with zero?
5265 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5266 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5270 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5272 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5273 $map->{$virtdev} = $volid;
5276 $fh->seek(0, 0) || die "seek failed - $!\n";
5278 my $outfd = new IO
::File
($tmpfn, "w") ||
5279 die "unable to write config for VM $vmid\n";
5281 my $cookie = { netcount
=> 0 };
5282 while (defined(my $line = <$fh>)) {
5283 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5292 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5293 die "interrupted by signal\n";
5295 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5297 $oldtimeout = alarm($timeout);
5304 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5305 my ($dev_id, $size, $devname) = ($1, $2, $3);
5306 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5307 } elsif ($line =~ m/^CTIME: /) {
5308 # we correctly received the vma config, so we can disable
5309 # the timeout now for disk allocation (set to 10 minutes, so
5310 # that we always timeout if something goes wrong)
5313 print $fifofh "done\n";
5314 my $tmp = $oldtimeout || 0;
5315 $oldtimeout = undef;
5321 print "restore vma archive: $cmd\n";
5322 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5326 alarm($oldtimeout) if $oldtimeout;
5334 my $cfg = cfs_read_file
('storage.cfg');
5335 foreach my $devname (keys %$devinfo) {
5336 my $volid = $devinfo->{$devname}->{volid
};
5339 if ($volid =~ m
|^/|) {
5340 unlink $volid || die 'unlink failed\n';
5342 PVE
::Storage
::vdisk_free
($cfg, $volid);
5344 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5346 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5353 rename($tmpfn, $conffile) ||
5354 die "unable to commit configuration file '$conffile'\n";
5356 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5358 eval { rescan
($vmid, 1); };
5362 sub restore_tar_archive
{
5363 my ($archive, $vmid, $user, $opts) = @_;
5365 if ($archive ne '-') {
5366 my $firstfile = tar_archive_read_firstfile
($archive);
5367 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5368 if $firstfile ne 'qemu-server.conf';
5371 my $storecfg = cfs_read_file
('storage.cfg');
5373 # destroy existing data - keep empty config
5374 my $vmcfgfn = config_file
($vmid);
5375 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5377 my $tocmd = "/usr/lib/qemu-server/qmextract";
5379 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5380 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5381 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5382 $tocmd .= ' --info' if $opts->{info
};
5384 # tar option "xf" does not autodetect compression when read from STDIN,
5385 # so we pipe to zcat
5386 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5387 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5389 my $tmpdir = "/var/tmp/vzdumptmp$$";
5392 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5393 local $ENV{VZDUMP_VMID
} = $vmid;
5394 local $ENV{VZDUMP_USER
} = $user;
5396 my $conffile = config_file
($vmid);
5397 my $tmpfn = "$conffile.$$.tmp";
5399 # disable interrupts (always do cleanups)
5400 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5401 print STDERR
"got interrupt - ignored\n";
5406 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5407 die "interrupted by signal\n";
5410 if ($archive eq '-') {
5411 print "extracting archive from STDIN\n";
5412 run_command
($cmd, input
=> "<&STDIN");
5414 print "extracting archive '$archive'\n";
5418 return if $opts->{info
};
5422 my $statfile = "$tmpdir/qmrestore.stat";
5423 if (my $fd = IO
::File-
>new($statfile, "r")) {
5424 while (defined (my $line = <$fd>)) {
5425 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5426 $map->{$1} = $2 if $1;
5428 print STDERR
"unable to parse line in statfile - $line\n";
5434 my $confsrc = "$tmpdir/qemu-server.conf";
5436 my $srcfd = new IO
::File
($confsrc, "r") ||
5437 die "unable to open file '$confsrc'\n";
5439 my $outfd = new IO
::File
($tmpfn, "w") ||
5440 die "unable to write config for VM $vmid\n";
5442 my $cookie = { netcount
=> 0 };
5443 while (defined (my $line = <$srcfd>)) {
5444 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5456 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5463 rename $tmpfn, $conffile ||
5464 die "unable to commit configuration file '$conffile'\n";
5466 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5468 eval { rescan
($vmid, 1); };
5473 # Internal snapshots
5475 # NOTE: Snapshot create/delete involves several non-atomic
5476 # action, and can take a long time.
5477 # So we try to avoid locking the file and use 'lock' variable
5478 # inside the config file instead.
5480 my $snapshot_copy_config = sub {
5481 my ($source, $dest) = @_;
5483 foreach my $k (keys %$source) {
5484 next if $k eq 'snapshots';
5485 next if $k eq 'snapstate';
5486 next if $k eq 'snaptime';
5487 next if $k eq 'vmstate';
5488 next if $k eq 'lock';
5489 next if $k eq 'digest';
5490 next if $k eq 'description';
5491 next if $k =~ m/^unused\d+$/;
5493 $dest->{$k} = $source->{$k};
5497 my $snapshot_apply_config = sub {
5498 my ($conf, $snap) = @_;
5500 # copy snapshot list
5502 snapshots
=> $conf->{snapshots
},
5505 # keep description and list of unused disks
5506 foreach my $k (keys %$conf) {
5507 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5508 $newconf->{$k} = $conf->{$k};
5511 &$snapshot_copy_config($snap, $newconf);
5516 sub foreach_writable_storage
{
5517 my ($conf, $func) = @_;
5521 foreach my $ds (keys %$conf) {
5522 next if !valid_drivename
($ds);
5524 my $drive = parse_drive
($ds, $conf->{$ds});
5526 next if drive_is_cdrom
($drive);
5528 my $volid = $drive->{file
};
5530 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5531 $sidhash->{$sid} = $sid if $sid;
5534 foreach my $sid (sort keys %$sidhash) {
5539 my $alloc_vmstate_volid = sub {
5540 my ($storecfg, $vmid, $conf, $snapname) = @_;
5542 # Note: we try to be smart when selecting a $target storage
5546 # search shared storage first
5547 foreach_writable_storage
($conf, sub {
5549 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5550 return if !$scfg->{shared
};
5552 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5556 # now search local storage
5557 foreach_writable_storage
($conf, sub {
5559 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5560 return if $scfg->{shared
};
5562 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5566 $target = 'local' if !$target;
5568 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5569 # we abort live save after $conf->{memory}, so we need at max twice that space
5570 my $size = $conf->{memory
}*2 + $driver_state_size;
5572 my $name = "vm-$vmid-state-$snapname";
5573 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5574 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5575 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5580 my $snapshot_prepare = sub {
5581 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5585 my $updatefn = sub {
5587 my $conf = load_config
($vmid);
5589 die "you can't take a snapshot if it's a template\n"
5590 if is_template
($conf);
5594 $conf->{lock} = 'snapshot';
5596 die "snapshot name '$snapname' already used\n"
5597 if defined($conf->{snapshots
}->{$snapname});
5599 my $storecfg = PVE
::Storage
::config
();
5600 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5602 $snap = $conf->{snapshots
}->{$snapname} = {};
5604 if ($save_vmstate && check_running
($vmid)) {
5605 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5608 &$snapshot_copy_config($conf, $snap);
5610 $snap->{snapstate
} = "prepare";
5611 $snap->{snaptime
} = time();
5612 $snap->{description
} = $comment if $comment;
5614 # always overwrite machine if we save vmstate. This makes sure we
5615 # can restore it later using correct machine type
5616 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5618 update_config_nolock
($vmid, $conf, 1);
5621 lock_config
($vmid, $updatefn);
5626 my $snapshot_commit = sub {
5627 my ($vmid, $snapname) = @_;
5629 my $updatefn = sub {
5631 my $conf = load_config
($vmid);
5633 die "missing snapshot lock\n"
5634 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5636 my $has_machine_config = defined($conf->{machine
});
5638 my $snap = $conf->{snapshots
}->{$snapname};
5640 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5642 die "wrong snapshot state\n"
5643 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5645 delete $snap->{snapstate
};
5646 delete $conf->{lock};
5648 my $newconf = &$snapshot_apply_config($conf, $snap);
5650 delete $newconf->{machine
} if !$has_machine_config;
5652 $newconf->{parent
} = $snapname;
5654 update_config_nolock
($vmid, $newconf, 1);
5657 lock_config
($vmid, $updatefn);
5660 sub snapshot_rollback
{
5661 my ($vmid, $snapname) = @_;
5665 my $storecfg = PVE
::Storage
::config
();
5667 my $conf = load_config
($vmid);
5669 my $get_snapshot_config = sub {
5671 die "you can't rollback if vm is a template\n" if is_template
($conf);
5673 my $res = $conf->{snapshots
}->{$snapname};
5675 die "snapshot '$snapname' does not exist\n" if !defined($res);
5680 my $snap = &$get_snapshot_config();
5682 foreach_drive
($snap, sub {
5683 my ($ds, $drive) = @_;
5685 return if drive_is_cdrom
($drive);
5687 my $volid = $drive->{file
};
5689 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5692 my $updatefn = sub {
5694 $conf = load_config
($vmid);
5696 $snap = &$get_snapshot_config();
5698 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5699 if $snap->{snapstate
};
5703 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5706 die "unable to rollback vm $vmid: vm is running\n"
5707 if check_running
($vmid);
5710 $conf->{lock} = 'rollback';
5712 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5713 delete $conf->{lock};
5719 my $has_machine_config = defined($conf->{machine
});
5721 # copy snapshot config to current config
5722 $conf = &$snapshot_apply_config($conf, $snap);
5723 $conf->{parent
} = $snapname;
5725 # Note: old code did not store 'machine', so we try to be smart
5726 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5727 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5728 # we remove the 'machine' configuration if not explicitly specified
5729 # in the original config.
5730 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5733 update_config_nolock
($vmid, $conf, 1);
5735 if (!$prepare && $snap->{vmstate
}) {
5736 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5737 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5741 lock_config
($vmid, $updatefn);
5743 foreach_drive
($snap, sub {
5744 my ($ds, $drive) = @_;
5746 return if drive_is_cdrom
($drive);
5748 my $volid = $drive->{file
};
5749 my $device = "drive-$ds";
5751 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5755 lock_config
($vmid, $updatefn);
5758 my $savevm_wait = sub {
5762 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5763 if (!$stat->{status
}) {
5764 die "savevm not active\n";
5765 } elsif ($stat->{status
} eq 'active') {
5768 } elsif ($stat->{status
} eq 'completed') {
5771 die "query-savevm returned status '$stat->{status}'\n";
5776 sub do_snapshots_with_qemu
{
5777 my ($storecfg, $volid) = @_;
5779 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5781 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5785 if ($volid =~ m/\.(qcow2|qed)$/){
5792 sub snapshot_create
{
5793 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5795 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5797 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5799 my $config = load_config
($vmid);
5801 my $running = check_running
($vmid);
5803 my $freezefs = $running && $config->{agent
};
5804 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5809 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5810 warn "guest-fsfreeze-freeze problems - $@" if $@;
5814 # create internal snapshots of all drives
5816 my $storecfg = PVE
::Storage
::config
();
5819 if ($snap->{vmstate
}) {
5820 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5821 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5822 &$savevm_wait($vmid);
5824 vm_mon_cmd
($vmid, "savevm-start");
5828 foreach_drive
($snap, sub {
5829 my ($ds, $drive) = @_;
5831 return if drive_is_cdrom
($drive);
5833 my $volid = $drive->{file
};
5834 my $device = "drive-$ds";
5836 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5837 $drivehash->{$ds} = 1;
5843 eval { vm_mon_cmd
($vmid, "savevm-end") };
5847 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5848 warn "guest-fsfreeze-thaw problems - $@" if $@;
5851 # savevm-end is async, we need to wait
5853 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5854 if (!$stat->{bytes
}) {
5857 print "savevm not yet finished\n";
5865 warn "snapshot create failed: starting cleanup\n";
5866 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5871 &$snapshot_commit($vmid, $snapname);
5874 # Note: $drivehash is only set when called from snapshot_create.
5875 sub snapshot_delete
{
5876 my ($vmid, $snapname, $force, $drivehash) = @_;
5883 my $unlink_parent = sub {
5884 my ($confref, $new_parent) = @_;
5886 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5888 $confref->{parent
} = $new_parent;
5890 delete $confref->{parent
};
5895 my $updatefn = sub {
5896 my ($remove_drive) = @_;
5898 my $conf = load_config
($vmid);
5902 die "you can't delete a snapshot if vm is a template\n"
5903 if is_template
($conf);
5906 $snap = $conf->{snapshots
}->{$snapname};
5908 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5910 # remove parent refs
5912 &$unlink_parent($conf, $snap->{parent
});
5913 foreach my $sn (keys %{$conf->{snapshots
}}) {
5914 next if $sn eq $snapname;
5915 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5919 if ($remove_drive) {
5920 if ($remove_drive eq 'vmstate') {
5921 delete $snap->{$remove_drive};
5923 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5924 my $volid = $drive->{file
};
5925 delete $snap->{$remove_drive};
5926 add_unused_volume
($conf, $volid);
5931 $snap->{snapstate
} = 'delete';
5933 delete $conf->{snapshots
}->{$snapname};
5934 delete $conf->{lock} if $drivehash;
5935 foreach my $volid (@$unused) {
5936 add_unused_volume
($conf, $volid);
5940 update_config_nolock
($vmid, $conf, 1);
5943 lock_config
($vmid, $updatefn);
5945 # now remove vmstate file
5947 my $storecfg = PVE
::Storage
::config
();
5949 if ($snap->{vmstate
}) {
5950 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5952 die $err if !$force;
5955 # save changes (remove vmstate from snapshot)
5956 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5959 # now remove all internal snapshots
5960 foreach_drive
($snap, sub {
5961 my ($ds, $drive) = @_;
5963 return if drive_is_cdrom
($drive);
5965 my $volid = $drive->{file
};
5966 my $device = "drive-$ds";
5968 if (!$drivehash || $drivehash->{$ds}) {
5969 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
5971 die $err if !$force;
5976 # save changes (remove drive fron snapshot)
5977 lock_config
($vmid, $updatefn, $ds) if !$force;
5978 push @$unused, $volid;
5981 # now cleanup config
5983 lock_config
($vmid, $updatefn);
5987 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
5990 foreach_drive
($conf, sub {
5991 my ($ds, $drive) = @_;
5993 return if drive_is_cdrom
($drive);
5994 my $volid = $drive->{file
};
5995 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
5998 return $err ?
0 : 1;
6001 sub template_create
{
6002 my ($vmid, $conf, $disk) = @_;
6004 my $storecfg = PVE
::Storage
::config
();
6006 foreach_drive
($conf, sub {
6007 my ($ds, $drive) = @_;
6009 return if drive_is_cdrom
($drive);
6010 return if $disk && $ds ne $disk;
6012 my $volid = $drive->{file
};
6013 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6015 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6016 $drive->{file
} = $voliddst;
6017 $conf->{$ds} = print_drive
($vmid, $drive);
6018 update_config_nolock
($vmid, $conf, 1);
6025 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6028 sub qemu_img_convert
{
6029 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6031 my $storecfg = PVE
::Storage
::config
();
6032 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6033 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6035 if ($src_storeid && $dst_storeid) {
6036 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6037 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6039 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6040 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6042 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6043 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6046 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6047 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6048 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6052 if($line =~ m/\((\S+)\/100\
%\)/){
6054 my $transferred = int($size * $percent / 100);
6055 my $remaining = $size - $transferred;
6057 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6062 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6064 die "copy failed: $err" if $err;
6068 sub qemu_img_format
{
6069 my ($scfg, $volname) = @_;
6071 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
6073 } elsif ($scfg->{type
} eq 'iscsi') {
6074 return "host_device";
6080 sub qemu_drive_mirror
{
6081 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6083 my $storecfg = PVE
::Storage
::config
();
6084 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6086 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6089 if ($dst_volname =~ m/\.(raw|qcow2)$/){
6093 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6095 #drive-mirror is doing lseek on source image before starting, and this can take a lot of time for big nfs volume
6096 #during this time, qmp socket is hanging
6097 #http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg01838.html
6098 #so we need to setup a big timeout
6099 my $opts = { timeout
=> 14400, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6100 $opts->{format
} = $format if $format;
6102 print "drive mirror is starting : this step can take some minutes/hours, depend of disk size and storage speed\n";
6104 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6107 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6108 my $stat = @$stats[0];
6109 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6110 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6112 my $busy = $stat->{busy
};
6113 my $ready = $stat->{ready
};
6115 if (my $total = $stat->{len
}) {
6116 my $transferred = $stat->{offset
} || 0;
6117 my $remaining = $total - $transferred;
6118 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6120 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6124 if ($stat->{ready
} eq 'true') {
6126 last if $vmiddst != $vmid;
6128 # try to switch the disk if source and destination are on the same guest
6129 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6131 die $@ if $@ !~ m/cannot be completed/;
6140 my $cancel_job = sub {
6141 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6143 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6144 my $stat = @$stats[0];
6151 eval { &$cancel_job(); };
6152 die "mirroring error: $err";
6155 if ($vmiddst != $vmid) {
6156 # if we clone a disk for a new target vm, we don't switch the disk
6157 &$cancel_job(); # so we call block-job-cancel
6162 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6163 $newvmid, $storage, $format, $full, $newvollist) = @_;
6168 print "create linked clone of drive $drivename ($drive->{file})\n";
6169 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6170 push @$newvollist, $newvolid;
6172 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6173 $storeid = $storage if $storage;
6175 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6177 $format = $drive->{format
} || $defFormat;
6180 # test if requested format is supported - else use default
6181 my $supported = grep { $_ eq $format } @$validFormats;
6182 $format = $defFormat if !$supported;
6184 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6186 print "create full clone of drive $drivename ($drive->{file})\n";
6187 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6188 push @$newvollist, $newvolid;
6190 if (!$running || $snapname) {
6191 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6193 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6197 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6200 $disk->{format
} = undef;
6201 $disk->{file
} = $newvolid;
6202 $disk->{size
} = $size;
6207 # this only works if VM is running
6208 sub get_current_qemu_machine
{
6211 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6212 my $res = vm_qmp_command
($vmid, $cmd);
6214 my ($current, $default);
6215 foreach my $e (@$res) {
6216 $default = $e->{name
} if $e->{'is-default'};
6217 $current = $e->{name
} if $e->{'is-current'};
6220 # fallback to the default machine if current is not supported by qemu
6221 return $current || $default || 'pc';
6224 sub qemu_machine_feature_enabled
{
6225 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6230 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6232 $current_major = $3;
6233 $current_minor = $4;
6235 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6237 $current_major = $1;
6238 $current_minor = $2;
6241 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6250 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6251 my (undef, $id, $function) = @_;
6252 my $res = { id
=> $id, function
=> $function};
6253 push @{$devices->{$id}}, $res;
6259 sub vm_iothreads_list
{
6262 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6265 foreach my $iothread (@$res) {
6266 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6273 my ($conf, $drive) = @_;
6277 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6279 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6285 my $controller = int($drive->{index} / $maxdev);
6286 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6288 return ($maxdev, $controller, $controller_prefix);