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';
71 my ($controller, $vmid, $option, $value) = @_;
73 my $root_path = "/sys/fs/cgroup/";
74 my $vm_path = $root_path.$controller."/qemu.slice/$vmid.scope";
77 PVE
::ProcFSTools
::write_proc_entry
("$vm_path/$option", $value);
81 unless(defined(&_VZSYSCALLS_H_
)) {
82 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
83 require 'sys/syscall.ph';
84 if(defined(&__x86_64__
)) {
85 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
86 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
87 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
88 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
89 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
90 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
91 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
92 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
94 elsif(defined( &__i386__
) ) {
95 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
96 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
97 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
98 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
99 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
100 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
101 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
102 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
104 die("no fairsched syscall for this arch");
106 require 'asm/ioctl.ph';
107 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
110 sub fairsched_mknod
{
111 my ($parent, $weight, $desired) = @_;
113 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
116 sub fairsched_rmnod
{
119 return syscall(&__NR_fairsched_rmnod
, int($id));
123 my ($pid, $newid) = @_;
125 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
128 sub fairsched_vcpus
{
129 my ($id, $vcpus) = @_;
131 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
135 my ($id, $op, $rate) = @_;
137 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
140 use constant FAIRSCHED_SET_RATE
=> 0;
141 use constant FAIRSCHED_DROP_RATE
=> 1;
142 use constant FAIRSCHED_GET_RATE
=> 2;
144 sub fairsched_cpulimit
{
145 my ($id, $limit) = @_;
147 my $cpulim1024 = int($limit * 1024 / 100);
148 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
150 return fairsched_rate
($id, $op, $cpulim1024);
153 my $nodename = PVE
::INotify
::nodename
();
155 mkdir "/etc/pve/nodes/$nodename";
156 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
159 my $var_run_tmpdir = "/var/run/qemu-server";
160 mkdir $var_run_tmpdir;
162 my $lock_dir = "/var/lock/qemu-server";
165 my $pcisysfs = "/sys/bus/pci";
171 description
=> "Specifies whether a VM will be started during system bootup.",
177 description
=> "Automatic restart after crash (currently ignored).",
182 type
=> 'string', format
=> 'pve-hotplug-features',
183 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'.",
184 default => 'network,disk,usb',
189 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
195 description
=> "Lock/unlock the VM.",
196 enum
=> [qw(migrate backup snapshot rollback)],
201 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.",
208 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
216 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
223 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
229 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
237 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
238 enum
=> PVE
::Tools
::kvmkeymaplist
(),
243 type
=> 'string', format
=> 'dns-name',
244 description
=> "Set a name for the VM. Only used on the configuration web interface.",
249 description
=> "scsi controller model",
250 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
256 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
261 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
262 description
=> <<EODESC,
263 Used to enable special optimization/features for specific
266 other => unspecified OS
267 wxp => Microsoft Windows XP
268 w2k => Microsoft Windows 2000
269 w2k3 => Microsoft Windows 2003
270 w2k8 => Microsoft Windows 2008
271 wvista => Microsoft Windows Vista
272 win7 => Microsoft Windows 7
273 win8 => Microsoft Windows 8/2012
274 l24 => Linux 2.4 Kernel
275 l26 => Linux 2.6/3.X Kernel
276 solaris => solaris/opensolaris/openindiania kernel
278 other|l24|l26|solaris ... no special behaviour
279 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
285 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
286 pattern
=> '[acdn]{1,4}',
291 type
=> 'string', format
=> 'pve-qm-bootdisk',
292 description
=> "Enable booting from specified disk.",
293 pattern
=> '(ide|sata|scsi|virtio)\d+',
298 description
=> "The number of CPUs. Please use option -sockets instead.",
305 description
=> "The number of CPU sockets.",
312 description
=> "The number of cores per socket.",
319 description
=> "Enable/disable Numa.",
325 description
=> "Number of hotplugged vcpus.",
332 description
=> "Enable/disable ACPI.",
338 description
=> "Enable/disable Qemu GuestAgent.",
344 description
=> "Enable/disable KVM hardware virtualization.",
350 description
=> "Enable/disable time drift fix.",
356 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
361 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
366 description
=> "Select 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.",
367 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
371 type
=> 'string', format
=> 'pve-qm-watchdog',
372 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
373 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)",
378 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
379 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'.",
380 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
383 startup
=> get_standard_option
('pve-startup-order'),
387 description
=> "Enable/disable Template.",
393 description
=> <<EODESCR,
394 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
396 args: -no-reboot -no-hpet
403 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).",
408 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
412 migrate_downtime
=> {
415 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
421 type
=> 'string', format
=> 'pve-qm-drive',
422 typetext
=> 'volume',
423 description
=> "This is an alias for option -ide2",
427 description
=> "Emulated CPU type.",
429 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) ],
432 parent
=> get_standard_option
('pve-snapshot-name', {
434 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
438 description
=> "Timestamp for snapshots.",
444 type
=> 'string', format
=> 'pve-volume-id',
445 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
448 description
=> "Specific the Qemu machine type.",
450 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
455 description
=> "Specify SMBIOS type 1 fields.",
456 type
=> 'string', format
=> 'pve-qm-smbios1',
457 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
463 # what about other qemu settings ?
465 #machine => 'string',
478 ##soundhw => 'string',
480 while (my ($k, $v) = each %$confdesc) {
481 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
484 my $MAX_IDE_DISKS = 4;
485 my $MAX_SCSI_DISKS = 14;
486 my $MAX_VIRTIO_DISKS = 16;
487 my $MAX_SATA_DISKS = 6;
488 my $MAX_USB_DEVICES = 5;
490 my $MAX_UNUSED_DISKS = 8;
491 my $MAX_HOSTPCI_DEVICES = 4;
492 my $MAX_SERIAL_PORTS = 4;
493 my $MAX_PARALLEL_PORTS = 3;
495 my $MAX_MEM = 4194304;
496 my $STATICMEM = 1024;
500 type
=> 'string', format
=> 'pve-qm-numanode',
501 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
502 description
=> "numa topology",
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
506 for (my $i = 0; $i < $MAX_NUMA; $i++) {
507 $confdesc->{"numa$i"} = $numadesc;
510 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
511 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
512 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
513 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
517 type
=> 'string', format
=> 'pve-qm-net',
518 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
519 description
=> <<EODESCR,
520 Specify network devices.
522 MODEL is one of: $nic_model_list_txt
524 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
525 automatically generated if not specified.
527 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
529 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'.
531 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
537 The DHCP server assign addresses to the guest starting from 10.0.2.15.
541 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
543 for (my $i = 0; $i < $MAX_NETS; $i++) {
544 $confdesc->{"net$i"} = $netdesc;
551 type
=> 'string', format
=> 'pve-qm-drive',
552 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]',
553 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
555 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
559 type
=> 'string', format
=> 'pve-qm-drive',
560 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>]',
561 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
567 type
=> 'string', format
=> 'pve-qm-drive',
568 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]',
569 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
571 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
575 type
=> 'string', format
=> 'pve-qm-drive',
576 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]',
577 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
579 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
583 type
=> 'string', format
=> 'pve-qm-usb-device',
584 typetext
=> 'host=HOSTUSBDEVICE|spice',
585 description
=> <<EODESCR,
586 Configure an USB device (n is 0 to 4). This can be used to
587 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
589 'bus-port(.port)*' (decimal numbers) or
590 'vendor_id:product_id' (hexadeciaml numbers)
592 You can use the 'lsusb -t' command to list existing usb devices.
594 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
596 The value 'spice' can be used to add a usb redirection devices for spice.
600 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
604 type
=> 'string', format
=> 'pve-qm-hostpci',
605 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
606 description
=> <<EODESCR,
607 Map host pci devices. HOSTPCIDEVICE syntax is:
609 'bus:dev.func' (hexadecimal numbers)
611 You can us the 'lspci' command to list existing pci devices.
613 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
615 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
617 Experimental: user reported problems with this option.
620 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
625 pattern
=> '(/dev/.+|socket)',
626 description
=> <<EODESCR,
627 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).
629 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
631 Experimental: user reported problems with this option.
638 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
639 description
=> <<EODESCR,
640 Map host parallel devices (n is 0 to 2).
642 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
644 Experimental: user reported problems with this option.
648 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
649 $confdesc->{"parallel$i"} = $paralleldesc;
652 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
653 $confdesc->{"serial$i"} = $serialdesc;
656 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
657 $confdesc->{"hostpci$i"} = $hostpcidesc;
660 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
661 $drivename_hash->{"ide$i"} = 1;
662 $confdesc->{"ide$i"} = $idedesc;
665 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
666 $drivename_hash->{"sata$i"} = 1;
667 $confdesc->{"sata$i"} = $satadesc;
670 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
671 $drivename_hash->{"scsi$i"} = 1;
672 $confdesc->{"scsi$i"} = $scsidesc ;
675 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
676 $drivename_hash->{"virtio$i"} = 1;
677 $confdesc->{"virtio$i"} = $virtiodesc;
680 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
681 $confdesc->{"usb$i"} = $usbdesc;
686 type
=> 'string', format
=> 'pve-volume-id',
687 description
=> "Reference to unused volumes.",
690 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
691 $confdesc->{"unused$i"} = $unuseddesc;
694 my $kvm_api_version = 0;
698 return $kvm_api_version if $kvm_api_version;
700 my $fh = IO
::File-
>new("</dev/kvm") ||
703 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
704 $kvm_api_version = $v;
709 return $kvm_api_version;
712 my $kvm_user_version;
714 sub kvm_user_version
{
716 return $kvm_user_version if $kvm_user_version;
718 $kvm_user_version = 'unknown';
720 my $tmp = `kvm -help 2>/dev/null`;
722 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
723 $kvm_user_version = $2;
726 return $kvm_user_version;
730 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
733 # order is important - used to autoselect boot disk
734 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
735 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
736 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
737 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
740 sub valid_drivename
{
743 return defined($drivename_hash->{$dev});
748 return defined($confdesc->{$key});
752 return $nic_model_list;
755 sub os_list_description
{
760 w2k
=> 'Windows 2000',
761 w2k3
=>, 'Windows 2003',
762 w2k8
=> 'Windows 2008',
763 wvista
=> 'Windows Vista',
765 win8
=> 'Windows 8/2012',
775 return $cdrom_path if $cdrom_path;
777 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
778 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
779 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
783 my ($storecfg, $vmid, $cdrom) = @_;
785 if ($cdrom eq 'cdrom') {
786 return get_cdrom_path
();
787 } elsif ($cdrom eq 'none') {
789 } elsif ($cdrom =~ m
|^/|) {
792 return PVE
::Storage
::path
($storecfg, $cdrom);
796 # try to convert old style file names to volume IDs
797 sub filename_to_volume_id
{
798 my ($vmid, $file, $media) = @_;
800 if (!($file eq 'none' || $file eq 'cdrom' ||
801 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
803 return undef if $file =~ m
|/|;
805 if ($media && $media eq 'cdrom') {
806 $file = "local:iso/$file";
808 $file = "local:$vmid/$file";
815 sub verify_media_type
{
816 my ($opt, $vtype, $media) = @_;
821 if ($media eq 'disk') {
823 } elsif ($media eq 'cdrom') {
826 die "internal error";
829 return if ($vtype eq $etype);
831 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
834 sub cleanup_drive_path
{
835 my ($opt, $storecfg, $drive) = @_;
837 # try to convert filesystem paths to volume IDs
839 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
840 ($drive->{file
} !~ m
|^/dev/.+|) &&
841 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
842 ($drive->{file
} !~ m/^\d+$/)) {
843 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
844 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
845 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
846 verify_media_type
($opt, $vtype, $drive->{media
});
847 $drive->{file
} = $volid;
850 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
853 sub create_conf_nolock
{
854 my ($vmid, $settings) = @_;
856 my $filename = config_file
($vmid);
858 die "configuration file '$filename' already exists\n" if -f
$filename;
860 my $defaults = load_defaults
();
862 $settings->{name
} = "vm$vmid" if !$settings->{name
};
863 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
866 foreach my $opt (keys %$settings) {
867 next if !$confdesc->{$opt};
869 my $value = $settings->{$opt};
872 $data .= "$opt: $value\n";
875 PVE
::Tools
::file_set_contents
($filename, $data);
878 sub parse_hotplug_features
{
883 return $res if $data eq '0';
885 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
887 foreach my $feature (PVE
::Tools
::split_list
($data)) {
888 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
891 warn "ignoring unknown hotplug feature '$feature'\n";
897 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
898 sub pve_verify_hotplug_features
{
899 my ($value, $noerr) = @_;
901 return $value if parse_hotplug_features
($value);
903 return undef if $noerr;
905 die "unable to parse hotplug option\n";
908 my $parse_size = sub {
911 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
912 my ($size, $unit) = ($1, $3);
915 $size = $size * 1024;
916 } elsif ($unit eq 'M') {
917 $size = $size * 1024 * 1024;
918 } elsif ($unit eq 'G') {
919 $size = $size * 1024 * 1024 * 1024;
925 my $format_size = sub {
930 my $kb = int($size/1024);
931 return $size if $kb*1024 != $size;
933 my $mb = int($kb/1024);
934 return "${kb}K" if $mb*1024 != $kb;
936 my $gb = int($mb/1024);
937 return "${mb}M" if $gb*1024 != $mb;
942 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
943 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
944 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
945 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
948 my ($key, $data) = @_;
952 # $key may be undefined - used to verify JSON parameters
953 if (!defined($key)) {
954 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
956 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
957 $res->{interface
} = $1;
963 foreach my $p (split (/,/, $data)) {
964 next if $p =~ m/^\s*$/;
966 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)=(.+)$/) {
967 my ($k, $v) = ($1, $2);
969 $k = 'file' if $k eq 'volume';
971 return undef if defined $res->{$k};
973 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
974 return undef if !$v || $v !~ m/^\d+/;
976 $v = sprintf("%.3f", $v / (1024*1024));
980 if (!$res->{file
} && $p !~ m/=/) {
988 return undef if !$res->{file
};
990 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
994 return undef if $res->{cache
} &&
995 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
996 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
997 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
998 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
999 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
1000 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
1001 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
1002 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
1003 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
1004 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
1005 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
1006 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
1007 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
1008 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
1009 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
1011 return undef if $res->{mbps_rd
} && $res->{mbps
};
1012 return undef if $res->{mbps_wr
} && $res->{mbps
};
1014 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
1015 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
1016 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
1017 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
1018 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
1019 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
1021 return undef if $res->{iops_rd
} && $res->{iops
};
1022 return undef if $res->{iops_wr
} && $res->{iops
};
1025 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
1026 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
1027 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
1028 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
1029 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
1030 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
1034 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
1037 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1038 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1039 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1040 return undef if $res->{interface
} eq 'virtio';
1043 # rerror does not work with scsi drives
1044 if ($res->{rerror
}) {
1045 return undef if $res->{interface
} eq 'scsi';
1051 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);
1054 my ($vmid, $drive) = @_;
1057 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
1058 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1061 if ($drive->{size
}) {
1062 $opts .= ",size=" . &$format_size($drive->{size
});
1065 return "$drive->{file}$opts";
1069 my($fh, $noerr) = @_;
1072 my $SG_GET_VERSION_NUM = 0x2282;
1074 my $versionbuf = "\x00" x
8;
1075 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1077 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1080 my $version = unpack("I", $versionbuf);
1081 if ($version < 30000) {
1082 die "scsi generic interface too old\n" if !$noerr;
1086 my $buf = "\x00" x
36;
1087 my $sensebuf = "\x00" x
8;
1088 my $cmd = pack("C x3 C x1", 0x12, 36);
1090 # see /usr/include/scsi/sg.h
1091 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";
1093 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1094 length($sensebuf), 0, length($buf), $buf,
1095 $cmd, $sensebuf, 6000);
1097 $ret = ioctl($fh, $SG_IO, $packet);
1099 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1103 my @res = unpack($sg_io_hdr_t, $packet);
1104 if ($res[17] || $res[18]) {
1105 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1110 (my $byte0, my $byte1, $res->{vendor
},
1111 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1113 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1114 $res->{type
} = $byte0 & 31;
1122 my $fh = IO
::File-
>new("+<$path") || return undef;
1123 my $res = scsi_inquiry
($fh, 1);
1129 sub machine_type_is_q35
{
1132 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1135 sub print_tabletdevice_full
{
1138 my $q35 = machine_type_is_q35
($conf);
1140 # we use uhci for old VMs because tablet driver was buggy in older qemu
1141 my $usbbus = $q35 ?
"ehci" : "uhci";
1143 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1146 sub print_drivedevice_full
{
1147 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1152 if ($drive->{interface
} eq 'virtio') {
1153 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1154 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1155 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1156 } elsif ($drive->{interface
} eq 'scsi') {
1158 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1159 my $unit = $drive->{index} % $maxdev;
1160 my $devicetype = 'hd';
1162 if (drive_is_cdrom
($drive)) {
1165 if ($drive->{file
} =~ m
|^/|) {
1166 $path = $drive->{file
};
1168 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1171 if($path =~ m/^iscsi\:\/\
//){
1172 $devicetype = 'generic';
1174 if (my $info = path_is_scsi
($path)) {
1175 if ($info->{type
} == 0) {
1176 $devicetype = 'block';
1177 } elsif ($info->{type
} == 1) { # tape
1178 $devicetype = 'generic';
1184 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1185 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1187 $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}";
1190 } elsif ($drive->{interface
} eq 'ide'){
1192 my $controller = int($drive->{index} / $maxdev);
1193 my $unit = $drive->{index} % $maxdev;
1194 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1196 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1197 } elsif ($drive->{interface
} eq 'sata'){
1198 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1199 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1200 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1201 } elsif ($drive->{interface
} eq 'usb') {
1203 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1205 die "unsupported interface type";
1208 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1213 sub get_initiator_name
{
1216 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1217 while (defined(my $line = <$fh>)) {
1218 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1227 sub print_drive_full
{
1228 my ($storecfg, $vmid, $drive) = @_;
1231 foreach my $o (@qemu_drive_options) {
1232 next if $o eq 'bootindex';
1233 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1236 foreach my $o (qw(bps bps_rd bps_wr)) {
1237 my $v = $drive->{"m$o"};
1238 $opts .= ",$o=" . int($v*1024*1024) if $v;
1241 # aio native works only with O_DIRECT
1242 if (!$drive->{aio
}) {
1243 if(!$drive->{cache
} || $drive->{cache
} eq 'none' || $drive->{cache
} eq 'directsync') {
1244 $opts .= ",aio=native";
1246 $opts .= ",aio=threads";
1252 my $volid = $drive->{file
};
1253 if (drive_is_cdrom
($drive)) {
1254 $path = get_iso_path
($storecfg, $vmid, $volid);
1256 if ($volid =~ m
|^/|) {
1259 $path = PVE
::Storage
::path
($storecfg, $volid);
1263 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1265 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1266 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1268 my $pathinfo = $path ?
"file=$path," : '';
1270 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1273 sub print_netdevice_full
{
1274 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1276 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1278 my $device = $net->{model
};
1279 if ($net->{model
} eq 'virtio') {
1280 $device = 'virtio-net-pci';
1283 my $pciaddr = print_pci_addr
("$netid", $bridges);
1284 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1285 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1286 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1287 my $vectors = $net->{queues
} * 2 + 2;
1288 $tmpstr .= ",vectors=$vectors,mq=on";
1290 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1294 sub print_netdev_full
{
1295 my ($vmid, $conf, $net, $netid) = @_;
1298 if ($netid =~ m/^net(\d+)$/) {
1302 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1304 my $ifname = "tap${vmid}i$i";
1306 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1307 die "interface name '$ifname' is too long (max 15 character)\n"
1308 if length($ifname) >= 16;
1310 my $vhostparam = '';
1311 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1313 my $vmname = $conf->{name
} || "vm$vmid";
1317 if ($net->{bridge
}) {
1318 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1320 $netdev = "type=user,id=$netid,hostname=$vmname";
1323 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1328 sub drive_is_cdrom
{
1331 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1340 foreach my $kvp (split(/,/, $data)) {
1342 if ($kvp =~ m/^memory=(\S+)$/) {
1343 $res->{memory
} = $1;
1344 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1345 $res->{policy
} = $1;
1346 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1347 $res->{cpus
}->{start
} = $1;
1348 $res->{cpus
}->{end
} = $3;
1349 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1350 $res->{hostnodes
}->{start
} = $1;
1351 $res->{hostnodes
}->{end
} = $3;
1363 return undef if !$value;
1366 my @list = split(/,/, $value);
1370 foreach my $kv (@list) {
1372 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1375 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1378 my $pcidevices = lspci
($2);
1379 $res->{pciid
} = $pcidevices->{$2};
1381 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1382 $res->{driver
} = $1;
1383 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1384 $res->{rombar
} = $1;
1385 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1386 $res->{'x-vga'} = $1;
1387 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1388 $res->{pcie
} = 1 if $1 == 1;
1390 warn "unknown hostpci setting '$kv'\n";
1394 return undef if !$found;
1399 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1405 foreach my $kvp (split(/,/, $data)) {
1407 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) {
1409 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1410 $res->{model
} = $model;
1411 $res->{macaddr
} = $mac;
1412 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1413 $res->{bridge
} = $1;
1414 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1415 $res->{queues
} = $1;
1416 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1418 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1420 } elsif ($kvp =~ m/^firewall=([01])$/) {
1421 $res->{firewall
} = $1;
1422 } elsif ($kvp =~ m/^link_down=([01])$/) {
1423 $res->{link_down
} = $1;
1430 return undef if !$res->{model
};
1438 my $res = "$net->{model}";
1439 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1440 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1441 $res .= ",rate=$net->{rate}" if $net->{rate
};
1442 $res .= ",tag=$net->{tag}" if $net->{tag
};
1443 $res .= ",firewall=1" if $net->{firewall
};
1444 $res .= ",link_down=1" if $net->{link_down
};
1445 $res .= ",queues=$net->{queues}" if $net->{queues
};
1450 sub add_random_macs
{
1451 my ($settings) = @_;
1453 foreach my $opt (keys %$settings) {
1454 next if $opt !~ m/^net(\d+)$/;
1455 my $net = parse_net
($settings->{$opt});
1457 $settings->{$opt} = print_net
($net);
1461 sub add_unused_volume
{
1462 my ($config, $volid) = @_;
1465 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1466 my $test = "unused$ind";
1467 if (my $vid = $config->{$test}) {
1468 return if $vid eq $volid; # do not add duplicates
1474 die "To many unused volume - please delete them first.\n" if !$key;
1476 $config->{$key} = $volid;
1481 sub vm_is_volid_owner
{
1482 my ($storecfg, $vmid, $volid) = @_;
1484 if ($volid !~ m
|^/|) {
1486 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1487 if ($owner && ($owner == $vmid)) {
1495 sub vmconfig_delete_pending_option
{
1496 my ($conf, $key) = @_;
1498 delete $conf->{pending
}->{$key};
1499 my $pending_delete_hash = { $key => 1 };
1500 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1501 $pending_delete_hash->{$opt} = 1;
1503 $conf->{pending
}->{delete} = join(',', keys %$pending_delete_hash);
1506 sub vmconfig_undelete_pending_option
{
1507 my ($conf, $key) = @_;
1509 my $pending_delete_hash = {};
1510 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1511 $pending_delete_hash->{$opt} = 1;
1513 delete $pending_delete_hash->{$key};
1515 my @keylist = keys %$pending_delete_hash;
1516 if (scalar(@keylist)) {
1517 $conf->{pending
}->{delete} = join(',', @keylist);
1519 delete $conf->{pending
}->{delete};
1523 sub vmconfig_register_unused_drive
{
1524 my ($storecfg, $vmid, $conf, $drive) = @_;
1526 if (!drive_is_cdrom
($drive)) {
1527 my $volid = $drive->{file
};
1528 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1529 add_unused_volume
($conf, $volid, $vmid);
1534 sub vmconfig_cleanup_pending
{
1537 # remove pending changes when nothing changed
1539 foreach my $opt (keys %{$conf->{pending
}}) {
1540 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1542 delete $conf->{pending
}->{$opt};
1546 # remove delete if option is not set
1547 my $pending_delete_hash = {};
1548 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1549 if (defined($conf->{$opt})) {
1550 $pending_delete_hash->{$opt} = 1;
1556 my @keylist = keys %$pending_delete_hash;
1557 if (scalar(@keylist)) {
1558 $conf->{pending
}->{delete} = join(',', @keylist);
1560 delete $conf->{pending
}->{delete};
1566 my $valid_smbios1_options = {
1567 manufacturer
=> '\S+',
1571 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1576 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1582 foreach my $kvp (split(/,/, $data)) {
1583 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1584 my ($k, $v) = split(/=/, $kvp);
1585 return undef if !defined($k) || !defined($v);
1586 return undef if !$valid_smbios1_options->{$k};
1587 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1598 foreach my $k (keys %$smbios1) {
1599 next if !defined($smbios1->{$k});
1600 next if !$valid_smbios1_options->{$k};
1601 $data .= ',' if $data;
1602 $data .= "$k=$smbios1->{$k}";
1607 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1608 sub verify_smbios1
{
1609 my ($value, $noerr) = @_;
1611 return $value if parse_smbios1
($value);
1613 return undef if $noerr;
1615 die "unable to parse smbios (type 1) options\n";
1618 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1619 sub verify_bootdisk
{
1620 my ($value, $noerr) = @_;
1622 return $value if valid_drivename
($value);
1624 return undef if $noerr;
1626 die "invalid boot disk '$value'\n";
1629 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1631 my ($value, $noerr) = @_;
1633 return $value if parse_numa
($value);
1635 return undef if $noerr;
1637 die "unable to parse numa options\n";
1640 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1642 my ($value, $noerr) = @_;
1644 return $value if parse_net
($value);
1646 return undef if $noerr;
1648 die "unable to parse network options\n";
1651 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1653 my ($value, $noerr) = @_;
1655 return $value if parse_drive
(undef, $value);
1657 return undef if $noerr;
1659 die "unable to parse drive options\n";
1662 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1663 sub verify_hostpci
{
1664 my ($value, $noerr) = @_;
1666 return $value if parse_hostpci
($value);
1668 return undef if $noerr;
1670 die "unable to parse pci id\n";
1673 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1674 sub verify_watchdog
{
1675 my ($value, $noerr) = @_;
1677 return $value if parse_watchdog
($value);
1679 return undef if $noerr;
1681 die "unable to parse watchdog options\n";
1684 sub parse_watchdog
{
1687 return undef if !$value;
1691 foreach my $p (split(/,/, $value)) {
1692 next if $p =~ m/^\s*$/;
1694 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1696 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1697 $res->{action
} = $2;
1706 sub parse_usb_device
{
1709 return undef if !$value;
1711 my @dl = split(/,/, $value);
1715 foreach my $v (@dl) {
1716 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1718 $res->{vendorid
} = $2;
1719 $res->{productid
} = $4;
1720 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1722 $res->{hostbus
} = $1;
1723 $res->{hostport
} = $2;
1724 } elsif ($v =~ m/^spice$/) {
1731 return undef if !$found;
1736 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1737 sub verify_usb_device
{
1738 my ($value, $noerr) = @_;
1740 return $value if parse_usb_device
($value);
1742 return undef if $noerr;
1744 die "unable to parse usb device\n";
1747 # add JSON properties for create and set function
1748 sub json_config_properties
{
1751 foreach my $opt (keys %$confdesc) {
1752 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1753 $prop->{$opt} = $confdesc->{$opt};
1760 my ($key, $value) = @_;
1762 die "unknown setting '$key'\n" if !$confdesc->{$key};
1764 my $type = $confdesc->{$key}->{type
};
1766 if (!defined($value)) {
1767 die "got undefined value\n";
1770 if ($value =~ m/[\n\r]/) {
1771 die "property contains a line feed\n";
1774 if ($type eq 'boolean') {
1775 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1776 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1777 die "type check ('boolean') failed - got '$value'\n";
1778 } elsif ($type eq 'integer') {
1779 return int($1) if $value =~ m/^(\d+)$/;
1780 die "type check ('integer') failed - got '$value'\n";
1781 } elsif ($type eq 'number') {
1782 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1783 die "type check ('number') failed - got '$value'\n";
1784 } elsif ($type eq 'string') {
1785 if (my $fmt = $confdesc->{$key}->{format
}) {
1786 if ($fmt eq 'pve-qm-drive') {
1787 # special case - we need to pass $key to parse_drive()
1788 my $drive = parse_drive
($key, $value);
1789 return $value if $drive;
1790 die "unable to parse drive options\n";
1792 PVE
::JSONSchema
::check_format
($fmt, $value);
1795 $value =~ s/^\"(.*)\"$/$1/;
1798 die "internal error"
1802 sub lock_config_full
{
1803 my ($vmid, $timeout, $code, @param) = @_;
1805 my $filename = config_file_lock
($vmid);
1807 my $res = lock_file
($filename, $timeout, $code, @param);
1814 sub lock_config_mode
{
1815 my ($vmid, $timeout, $shared, $code, @param) = @_;
1817 my $filename = config_file_lock
($vmid);
1819 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1827 my ($vmid, $code, @param) = @_;
1829 return lock_config_full
($vmid, 10, $code, @param);
1832 sub cfs_config_path
{
1833 my ($vmid, $node) = @_;
1835 $node = $nodename if !$node;
1836 return "nodes/$node/qemu-server/$vmid.conf";
1839 sub check_iommu_support
{
1840 #fixme : need to check IOMMU support
1841 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1849 my ($vmid, $node) = @_;
1851 my $cfspath = cfs_config_path
($vmid, $node);
1852 return "/etc/pve/$cfspath";
1855 sub config_file_lock
{
1858 return "$lock_dir/lock-$vmid.conf";
1864 my $conf = config_file
($vmid);
1865 utime undef, undef, $conf;
1869 my ($storecfg, $vmid, $keep_empty_config) = @_;
1871 my $conffile = config_file
($vmid);
1873 my $conf = load_config
($vmid);
1877 # only remove disks owned by this VM
1878 foreach_drive
($conf, sub {
1879 my ($ds, $drive) = @_;
1881 return if drive_is_cdrom
($drive);
1883 my $volid = $drive->{file
};
1885 return if !$volid || $volid =~ m
|^/|;
1887 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1888 return if !$path || !$owner || ($owner != $vmid);
1890 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1893 if ($keep_empty_config) {
1894 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1899 # also remove unused disk
1901 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1904 PVE
::Storage
::foreach_volid
($dl, sub {
1905 my ($volid, $sid, $volname, $d) = @_;
1906 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1916 my ($vmid, $node) = @_;
1918 my $cfspath = cfs_config_path
($vmid, $node);
1920 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1922 die "no such VM ('$vmid')\n" if !defined($conf);
1927 sub parse_vm_config
{
1928 my ($filename, $raw) = @_;
1930 return undef if !defined($raw);
1933 digest
=> Digest
::SHA
::sha1_hex
($raw),
1938 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1939 || die "got strange filename '$filename'";
1947 my @lines = split(/\n/, $raw);
1948 foreach my $line (@lines) {
1949 next if $line =~ m/^\s*$/;
1951 if ($line =~ m/^\[PENDING\]\s*$/i) {
1952 $section = 'pending';
1953 $conf->{description
} = $descr if $descr;
1955 $conf = $res->{$section} = {};
1958 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1960 $conf->{description
} = $descr if $descr;
1962 $conf = $res->{snapshots
}->{$section} = {};
1966 if ($line =~ m/^\#(.*)\s*$/) {
1967 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1971 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1972 $descr .= PVE
::Tools
::decode_text
($2);
1973 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1974 $conf->{snapstate
} = $1;
1975 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1978 $conf->{$key} = $value;
1979 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1981 if ($section eq 'pending') {
1982 $conf->{delete} = $value; # we parse this later
1984 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1986 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1989 eval { $value = check_type
($key, $value); };
1991 warn "vm $vmid - unable to parse value of '$key' - $@";
1993 my $fmt = $confdesc->{$key}->{format
};
1994 if ($fmt && $fmt eq 'pve-qm-drive') {
1995 my $v = parse_drive
($key, $value);
1996 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1997 $v->{file
} = $volid;
1998 $value = print_drive
($vmid, $v);
2000 warn "vm $vmid - unable to parse value of '$key'\n";
2005 if ($key eq 'cdrom') {
2006 $conf->{ide2
} = $value;
2008 $conf->{$key} = $value;
2014 $conf->{description
} = $descr if $descr;
2016 delete $res->{snapstate
}; # just to be sure
2021 sub write_vm_config
{
2022 my ($filename, $conf) = @_;
2024 delete $conf->{snapstate
}; # just to be sure
2026 if ($conf->{cdrom
}) {
2027 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2028 $conf->{ide2
} = $conf->{cdrom
};
2029 delete $conf->{cdrom
};
2032 # we do not use 'smp' any longer
2033 if ($conf->{sockets
}) {
2034 delete $conf->{smp
};
2035 } elsif ($conf->{smp
}) {
2036 $conf->{sockets
} = $conf->{smp
};
2037 delete $conf->{cores
};
2038 delete $conf->{smp
};
2041 my $used_volids = {};
2043 my $cleanup_config = sub {
2044 my ($cref, $pending, $snapname) = @_;
2046 foreach my $key (keys %$cref) {
2047 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2048 $key eq 'snapstate' || $key eq 'pending';
2049 my $value = $cref->{$key};
2050 if ($key eq 'delete') {
2051 die "propertry 'delete' is only allowed in [PENDING]\n"
2053 # fixme: check syntax?
2056 eval { $value = check_type
($key, $value); };
2057 die "unable to parse value of '$key' - $@" if $@;
2059 $cref->{$key} = $value;
2061 if (!$snapname && valid_drivename
($key)) {
2062 my $drive = parse_drive
($key, $value);
2063 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2068 &$cleanup_config($conf);
2070 &$cleanup_config($conf->{pending
}, 1);
2072 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2073 die "internal error" if $snapname eq 'pending';
2074 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2077 # remove 'unusedX' settings if we re-add a volume
2078 foreach my $key (keys %$conf) {
2079 my $value = $conf->{$key};
2080 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2081 delete $conf->{$key};
2085 my $generate_raw_config = sub {
2090 # add description as comment to top of file
2091 my $descr = $conf->{description
} || '';
2092 foreach my $cl (split(/\n/, $descr)) {
2093 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2096 foreach my $key (sort keys %$conf) {
2097 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2098 $raw .= "$key: $conf->{$key}\n";
2103 my $raw = &$generate_raw_config($conf);
2105 if (scalar(keys %{$conf->{pending
}})){
2106 $raw .= "\n[PENDING]\n";
2107 $raw .= &$generate_raw_config($conf->{pending
});
2110 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2111 $raw .= "\n[$snapname]\n";
2112 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2118 sub update_config_nolock
{
2119 my ($vmid, $conf, $skiplock) = @_;
2121 check_lock
($conf) if !$skiplock;
2123 my $cfspath = cfs_config_path
($vmid);
2125 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2129 my ($vmid, $conf, $skiplock) = @_;
2131 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2138 # we use static defaults from our JSON schema configuration
2139 foreach my $key (keys %$confdesc) {
2140 if (defined(my $default = $confdesc->{$key}->{default})) {
2141 $res->{$key} = $default;
2145 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2146 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2152 my $vmlist = PVE
::Cluster
::get_vmlist
();
2154 return $res if !$vmlist || !$vmlist->{ids
};
2155 my $ids = $vmlist->{ids
};
2157 foreach my $vmid (keys %$ids) {
2158 my $d = $ids->{$vmid};
2159 next if !$d->{node
} || $d->{node
} ne $nodename;
2160 next if !$d->{type
} || $d->{type
} ne 'qemu';
2161 $res->{$vmid}->{exists} = 1;
2166 # test if VM uses local resources (to prevent migration)
2167 sub check_local_resources
{
2168 my ($conf, $noerr) = @_;
2172 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2173 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2175 foreach my $k (keys %$conf) {
2176 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2177 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2180 die "VM uses local resources\n" if $loc_res && !$noerr;
2185 # check if used storages are available on all nodes (use by migrate)
2186 sub check_storage_availability
{
2187 my ($storecfg, $conf, $node) = @_;
2189 foreach_drive
($conf, sub {
2190 my ($ds, $drive) = @_;
2192 my $volid = $drive->{file
};
2195 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2198 # check if storage is available on both nodes
2199 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2200 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2204 # list nodes where all VM images are available (used by has_feature API)
2206 my ($conf, $storecfg) = @_;
2208 my $nodelist = PVE
::Cluster
::get_nodelist
();
2209 my $nodehash = { map { $_ => 1 } @$nodelist };
2210 my $nodename = PVE
::INotify
::nodename
();
2212 foreach_drive
($conf, sub {
2213 my ($ds, $drive) = @_;
2215 my $volid = $drive->{file
};
2218 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2220 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2221 if ($scfg->{disable
}) {
2223 } elsif (my $avail = $scfg->{nodes
}) {
2224 foreach my $node (keys %$nodehash) {
2225 delete $nodehash->{$node} if !$avail->{$node};
2227 } elsif (!$scfg->{shared
}) {
2228 foreach my $node (keys %$nodehash) {
2229 delete $nodehash->{$node} if $node ne $nodename
2241 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2245 my ($pidfile, $pid) = @_;
2247 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2251 return undef if !$line;
2252 my @param = split(/\0/, $line);
2254 my $cmd = $param[0];
2255 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2257 for (my $i = 0; $i < scalar (@param); $i++) {
2260 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2261 my $p = $param[$i+1];
2262 return 1 if $p && ($p eq $pidfile);
2271 my ($vmid, $nocheck, $node) = @_;
2273 my $filename = config_file
($vmid, $node);
2275 die "unable to find configuration file for VM $vmid - no such machine\n"
2276 if !$nocheck && ! -f
$filename;
2278 my $pidfile = pidfile_name
($vmid);
2280 if (my $fd = IO
::File-
>new("<$pidfile")) {
2285 my $mtime = $st->mtime;
2286 if ($mtime > time()) {
2287 warn "file '$filename' modified in future\n";
2290 if ($line =~ m/^(\d+)$/) {
2292 if (check_cmdline
($pidfile, $pid)) {
2293 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2305 my $vzlist = config_list
();
2307 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2309 while (defined(my $de = $fd->read)) {
2310 next if $de !~ m/^(\d+)\.pid$/;
2312 next if !defined($vzlist->{$vmid});
2313 if (my $pid = check_running
($vmid)) {
2314 $vzlist->{$vmid}->{pid
} = $pid;
2322 my ($storecfg, $conf) = @_;
2324 my $bootdisk = $conf->{bootdisk
};
2325 return undef if !$bootdisk;
2326 return undef if !valid_drivename
($bootdisk);
2328 return undef if !$conf->{$bootdisk};
2330 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2331 return undef if !defined($drive);
2333 return undef if drive_is_cdrom
($drive);
2335 my $volid = $drive->{file
};
2336 return undef if !$volid;
2338 return $drive->{size
};
2341 my $last_proc_pid_stat;
2343 # get VM status information
2344 # This must be fast and should not block ($full == false)
2345 # We only query KVM using QMP if $full == true (this can be slow)
2347 my ($opt_vmid, $full) = @_;
2351 my $storecfg = PVE
::Storage
::config
();
2353 my $list = vzlist
();
2354 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2356 my $cpucount = $cpuinfo->{cpus
} || 1;
2358 foreach my $vmid (keys %$list) {
2359 next if $opt_vmid && ($vmid ne $opt_vmid);
2361 my $cfspath = cfs_config_path
($vmid);
2362 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2365 $d->{pid
} = $list->{$vmid}->{pid
};
2367 # fixme: better status?
2368 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2370 my $size = disksize
($storecfg, $conf);
2371 if (defined($size)) {
2372 $d->{disk
} = 0; # no info available
2373 $d->{maxdisk
} = $size;
2379 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2380 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2381 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2383 $d->{name
} = $conf->{name
} || "VM $vmid";
2384 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2386 if ($conf->{balloon
}) {
2387 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2388 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2399 $d->{diskwrite
} = 0;
2401 $d->{template
} = is_template
($conf);
2406 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2407 foreach my $dev (keys %$netdev) {
2408 next if $dev !~ m/^tap([1-9]\d*)i/;
2410 my $d = $res->{$vmid};
2413 $d->{netout
} += $netdev->{$dev}->{receive
};
2414 $d->{netin
} += $netdev->{$dev}->{transmit
};
2417 my $ctime = gettimeofday
;
2419 foreach my $vmid (keys %$list) {
2421 my $d = $res->{$vmid};
2422 my $pid = $d->{pid
};
2425 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2426 next if !$pstat; # not running
2428 my $used = $pstat->{utime} + $pstat->{stime
};
2430 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2432 if ($pstat->{vsize
}) {
2433 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2436 my $old = $last_proc_pid_stat->{$pid};
2438 $last_proc_pid_stat->{$pid} = {
2446 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2448 if ($dtime > 1000) {
2449 my $dutime = $used - $old->{used
};
2451 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2452 $last_proc_pid_stat->{$pid} = {
2458 $d->{cpu
} = $old->{cpu
};
2462 return $res if !$full;
2464 my $qmpclient = PVE
::QMPClient-
>new();
2466 my $ballooncb = sub {
2467 my ($vmid, $resp) = @_;
2469 my $info = $resp->{'return'};
2470 return if !$info->{max_mem
};
2472 my $d = $res->{$vmid};
2474 # use memory assigned to VM
2475 $d->{maxmem
} = $info->{max_mem
};
2476 $d->{balloon
} = $info->{actual
};
2478 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2479 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2480 $d->{freemem
} = $info->{free_mem
};
2485 my $blockstatscb = sub {
2486 my ($vmid, $resp) = @_;
2487 my $data = $resp->{'return'} || [];
2488 my $totalrdbytes = 0;
2489 my $totalwrbytes = 0;
2490 for my $blockstat (@$data) {
2491 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2492 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2494 $res->{$vmid}->{diskread
} = $totalrdbytes;
2495 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2498 my $statuscb = sub {
2499 my ($vmid, $resp) = @_;
2501 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2502 # this fails if ballon driver is not loaded, so this must be
2503 # the last commnand (following command are aborted if this fails).
2504 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2506 my $status = 'unknown';
2507 if (!defined($status = $resp->{'return'}->{status
})) {
2508 warn "unable to get VM status\n";
2512 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2515 foreach my $vmid (keys %$list) {
2516 next if $opt_vmid && ($vmid ne $opt_vmid);
2517 next if !$res->{$vmid}->{pid
}; # not running
2518 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2521 $qmpclient->queue_execute(undef, 1);
2523 foreach my $vmid (keys %$list) {
2524 next if $opt_vmid && ($vmid ne $opt_vmid);
2525 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2532 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2535 my $current_size = 1024;
2536 my $dimm_size = 512;
2537 return if $current_size == $memory;
2539 for (my $j = 0; $j < 8; $j++) {
2540 for (my $i = 0; $i < 32; $i++) {
2541 my $name = "dimm${dimm_id}";
2543 my $numanode = $i % $sockets;
2544 $current_size += $dimm_size;
2545 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2546 return $current_size if $current_size >= $memory;
2553 my ($conf, $func) = @_;
2555 foreach my $ds (keys %$conf) {
2556 next if !valid_drivename
($ds);
2558 my $drive = parse_drive
($ds, $conf->{$ds});
2561 &$func($ds, $drive);
2566 my ($conf, $func) = @_;
2570 my $test_volid = sub {
2571 my ($volid, $is_cdrom) = @_;
2575 $volhash->{$volid} = $is_cdrom || 0;
2578 foreach_drive
($conf, sub {
2579 my ($ds, $drive) = @_;
2580 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2583 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2584 my $snap = $conf->{snapshots
}->{$snapname};
2585 &$test_volid($snap->{vmstate
}, 0);
2586 foreach_drive
($snap, sub {
2587 my ($ds, $drive) = @_;
2588 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2592 foreach my $volid (keys %$volhash) {
2593 &$func($volid, $volhash->{$volid});
2597 sub vga_conf_has_spice
{
2600 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2605 sub config_to_command
{
2606 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2609 my $globalFlags = [];
2610 my $machineFlags = [];
2616 my $kvmver = kvm_user_version
();
2617 my $vernum = 0; # unknown
2618 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2619 $vernum = $1*1000000+$2*1000;
2620 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2621 $vernum = $1*1000000+$2*1000+$3;
2624 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2626 my $have_ovz = -f
'/proc/vz/vestat';
2628 my $q35 = machine_type_is_q35
($conf);
2629 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2630 my $machine_type = $forcemachine || $conf->{machine
};
2632 my $cpuunits = defined($conf->{cpuunits
}) ?
2633 $conf->{cpuunits
} : $defaults->{cpuunits
};
2635 push @$cmd, '/usr/bin/systemd-run';
2636 push @$cmd, '--scope';
2637 push @$cmd, '--slice', "qemu";
2638 push @$cmd, '--unit', $vmid;
2639 push @$cmd, '-p', "CPUShares=$cpuunits";
2641 push @$cmd, '/usr/bin/kvm';
2643 push @$cmd, '-id', $vmid;
2647 my $qmpsocket = qmp_socket
($vmid);
2648 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2649 push @$cmd, '-mon', "chardev=qmp,mode=control";
2651 my $socket = vnc_socket
($vmid);
2652 push @$cmd, '-vnc', "unix:$socket,x509,password";
2654 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2656 push @$cmd, '-daemonize';
2658 if ($conf->{smbios1
}) {
2659 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2663 # the q35 chipset support native usb2, so we enable usb controller
2664 # by default for this machine type
2665 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2667 $pciaddr = print_pci_addr
("piix3", $bridges);
2668 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2671 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2672 next if !$conf->{"usb$i"};
2675 # include usb device config
2676 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2679 my $vga = $conf->{vga
};
2681 my $qxlnum = vga_conf_has_spice
($vga);
2682 $vga = 'qxl' if $qxlnum;
2685 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2686 $conf->{ostype
} eq 'win7' ||
2687 $conf->{ostype
} eq 'w2k8')) {
2694 # enable absolute mouse coordinates (needed by vnc)
2696 if (defined($conf->{tablet
})) {
2697 $tablet = $conf->{tablet
};
2699 $tablet = $defaults->{tablet
};
2700 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2701 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2704 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2707 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2708 my $d = parse_hostpci
($conf->{"hostpci$i"});
2711 my $pcie = $d->{pcie
};
2713 die "q35 machine model is not enabled" if !$q35;
2714 $pciaddr = print_pcie_addr
("hostpci$i");
2716 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2719 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2720 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2721 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2722 if ($xvga && $xvga ne '') {
2723 push @$cpuFlags, 'kvm=off';
2726 $driver = "vfio-pci" if $xvga ne '';
2727 my $pcidevices = $d->{pciid
};
2728 my $multifunction = 1 if @$pcidevices > 1;
2731 foreach my $pcidevice (@$pcidevices) {
2733 my $id = "hostpci$i";
2734 $id .= ".$j" if $multifunction;
2735 my $addr = $pciaddr;
2736 $addr .= ".$j" if $multifunction;
2737 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2740 $devicestr .= "$rombar$xvga";
2741 $devicestr .= ",multifunction=on" if $multifunction;
2744 push @$devices, '-device', $devicestr;
2750 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2751 my $d = parse_usb_device
($conf->{"usb$i"});
2753 if ($d->{vendorid
} && $d->{productid
}) {
2754 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2755 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2756 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2757 } elsif ($d->{spice
}) {
2758 # usb redir support for spice
2759 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2760 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2765 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2766 if (my $path = $conf->{"serial$i"}) {
2767 if ($path eq 'socket') {
2768 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2769 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2770 push @$devices, '-device', "isa-serial,chardev=serial$i";
2772 die "no such serial device\n" if ! -c
$path;
2773 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2774 push @$devices, '-device', "isa-serial,chardev=serial$i";
2780 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2781 if (my $path = $conf->{"parallel$i"}) {
2782 die "no such parallel device\n" if ! -c
$path;
2783 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2784 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2785 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2789 my $vmname = $conf->{name
} || "vm$vmid";
2791 push @$cmd, '-name', $vmname;
2794 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2795 $sockets = $conf->{sockets
} if $conf->{sockets
};
2797 my $cores = $conf->{cores
} || 1;
2799 my $maxcpus = $sockets * $cores;
2801 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2803 my $allowed_vcpus = $cpuinfo->{cpus
};
2805 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2806 if ($allowed_vcpus < $maxcpus);
2808 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2810 push @$cmd, '-nodefaults';
2812 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2814 my $bootindex_hash = {};
2816 foreach my $o (split(//, $bootorder)) {
2817 $bootindex_hash->{$o} = $i*100;
2821 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2823 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2825 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2827 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2830 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2832 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2833 my $useLocaltime = $conf->{localtime};
2835 if (my $ost = $conf->{ostype
}) {
2836 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2838 if ($ost =~ m/^w/) { # windows
2839 $useLocaltime = 1 if !defined($conf->{localtime});
2841 # use time drift fix when acpi is enabled
2842 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2843 $tdf = 1 if !defined($conf->{tdf
});
2847 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2849 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2850 push @$cmd, '-no-hpet';
2851 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2852 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2853 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2854 push @$cpuFlags , 'hv_time' if !$nokvm;
2857 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2861 if ($ost eq 'win7' || $ost eq 'win8') {
2862 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2866 push @$rtcFlags, 'driftfix=slew' if $tdf;
2869 push @$machineFlags, 'accel=tcg';
2871 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2874 if ($machine_type) {
2875 push @$machineFlags, "type=${machine_type}";
2878 if ($conf->{startdate
}) {
2879 push @$rtcFlags, "base=$conf->{startdate}";
2880 } elsif ($useLocaltime) {
2881 push @$rtcFlags, 'base=localtime';
2884 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2885 $cpu = $conf->{cpu
} if $conf->{cpu
};
2887 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2889 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2891 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2893 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2895 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2897 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2898 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2901 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2903 push @$cmd, '-cpu', "$cpu,enforce";
2905 my $memory = $conf->{memory
} || $defaults->{memory
};
2906 my $static_memory = 0;
2907 my $dimm_memory = 0;
2909 if ($hotplug_features->{memory
}) {
2910 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2911 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2912 $static_memory = $STATICMEM;
2913 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2914 $dimm_memory = $memory - $static_memory;
2915 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2919 $static_memory = $memory;
2920 push @$cmd, '-m', $static_memory;
2923 if ($conf->{numa
}) {
2925 my $numa_totalmemory = undef;
2926 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2927 next if !$conf->{"numa$i"};
2928 my $numa = parse_numa
($conf->{"numa$i"});
2931 die "missing numa node$i memory value\n" if !$numa->{memory
};
2932 my $numa_memory = $numa->{memory
};
2933 $numa_totalmemory += $numa_memory;
2934 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2937 my $cpus_start = $numa->{cpus
}->{start
};
2938 die "missing numa node$i cpus\n" if !defined($cpus_start);
2939 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2940 my $cpus = $cpus_start;
2941 if (defined($cpus_end)) {
2942 $cpus .= "-$cpus_end";
2943 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2947 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2948 if (defined($hostnodes_start)) {
2949 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2950 my $hostnodes = $hostnodes_start;
2951 if (defined($hostnodes_end)) {
2952 $hostnodes .= "-$hostnodes_end";
2953 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2956 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2957 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2958 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2962 my $policy = $numa->{policy
};
2963 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2964 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2967 push @$cmd, '-object', $numa_object;
2968 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2971 die "total memory for NUMA nodes must be equal to vm static memory\n"
2972 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2974 #if no custom tology, we split memory and cores across numa nodes
2975 if(!$numa_totalmemory) {
2977 my $numa_memory = ($static_memory / $sockets) . "M";
2979 for (my $i = 0; $i < $sockets; $i++) {
2981 my $cpustart = ($cores * $i);
2982 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2983 my $cpus = $cpustart;
2984 $cpus .= "-$cpuend" if $cpuend;
2986 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2987 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2992 if ($hotplug_features->{memory
}) {
2993 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2994 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2995 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2996 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2998 #if dimm_memory is not aligned to dimm map
2999 if($current_size > $memory) {
3000 $conf->{memory
} = $current_size;
3001 update_config_nolock
($vmid, $conf, 1);
3006 push @$cmd, '-S' if $conf->{freeze
};
3008 # set keyboard layout
3009 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3010 push @$cmd, '-k', $kb if $kb;
3013 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3014 #push @$cmd, '-soundhw', 'es1370';
3015 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3017 if($conf->{agent
}) {
3018 my $qgasocket = qmp_socket
($vmid, 1);
3019 my $pciaddr = print_pci_addr
("qga0", $bridges);
3020 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3021 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3022 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3029 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3030 for(my $i = 1; $i < $qxlnum; $i++){
3031 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3032 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3035 # assume other OS works like Linux
3036 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3037 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3041 my $pciaddr = print_pci_addr
("spice", $bridges);
3043 my $nodename = PVE
::INotify
::nodename
();
3044 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3045 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3047 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3049 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3050 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3051 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3054 # enable balloon by default, unless explicitly disabled
3055 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3056 $pciaddr = print_pci_addr
("balloon0", $bridges);
3057 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3060 if ($conf->{watchdog
}) {
3061 my $wdopts = parse_watchdog
($conf->{watchdog
});
3062 $pciaddr = print_pci_addr
("watchdog", $bridges);
3063 my $watchdog = $wdopts->{model
} || 'i6300esb';
3064 push @$devices, '-device', "$watchdog$pciaddr";
3065 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3069 my $scsicontroller = {};
3070 my $ahcicontroller = {};
3071 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3073 # Add iscsi initiator name if available
3074 if (my $initiator = get_initiator_name
()) {
3075 push @$devices, '-iscsi', "initiator-name=$initiator";
3078 foreach_drive
($conf, sub {
3079 my ($ds, $drive) = @_;
3081 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3082 push @$vollist, $drive->{file
};
3085 $use_virtio = 1 if $ds =~ m/^virtio/;
3087 if (drive_is_cdrom
($drive)) {
3088 if ($bootindex_hash->{d
}) {
3089 $drive->{bootindex
} = $bootindex_hash->{d
};
3090 $bootindex_hash->{d
} += 1;
3093 if ($bootindex_hash->{c
}) {
3094 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3095 $bootindex_hash->{c
} += 1;
3099 if($drive->{interface
} eq 'virtio'){
3100 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3103 if ($drive->{interface
} eq 'scsi') {
3105 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3107 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3108 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3111 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3112 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3113 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3117 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3118 $queues = ",num_queues=$drive->{queues}";
3121 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3122 $scsicontroller->{$controller}=1;
3125 if ($drive->{interface
} eq 'sata') {
3126 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3127 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3128 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3129 $ahcicontroller->{$controller}=1;
3132 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3133 push @$devices, '-drive',$drive_cmd;
3134 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3137 for (my $i = 0; $i < $MAX_NETS; $i++) {
3138 next if !$conf->{"net$i"};
3139 my $d = parse_net
($conf->{"net$i"});
3142 $use_virtio = 1 if $d->{model
} eq 'virtio';
3144 if ($bootindex_hash->{n
}) {
3145 $d->{bootindex
} = $bootindex_hash->{n
};
3146 $bootindex_hash->{n
} += 1;
3149 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3150 push @$devices, '-netdev', $netdevfull;
3152 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3153 push @$devices, '-device', $netdevicefull;
3158 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3163 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3165 while (my ($k, $v) = each %$bridges) {
3166 $pciaddr = print_pci_addr
("pci.$k");
3167 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3171 # hack: virtio with fairsched is unreliable, so we do not use fairsched
3172 # when the VM uses virtio devices.
3173 if (!$use_virtio && $have_ovz) {
3175 my $cpuunits = defined($conf->{cpuunits
}) ?
3176 $conf->{cpuunits
} : $defaults->{cpuunits
};
3178 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
3180 # fixme: cpulimit is currently ignored
3181 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
3185 if ($conf->{args
}) {
3186 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3190 push @$cmd, @$devices;
3191 push @$cmd, '-rtc', join(',', @$rtcFlags)
3192 if scalar(@$rtcFlags);
3193 push @$cmd, '-machine', join(',', @$machineFlags)
3194 if scalar(@$machineFlags);
3195 push @$cmd, '-global', join(',', @$globalFlags)
3196 if scalar(@$globalFlags);
3198 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3203 return "${var_run_tmpdir}/$vmid.vnc";
3209 my $res = vm_mon_cmd
($vmid, 'query-spice');
3211 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3215 my ($vmid, $qga) = @_;
3216 my $sockettype = $qga ?
'qga' : 'qmp';
3217 return "${var_run_tmpdir}/$vmid.$sockettype";
3222 return "${var_run_tmpdir}/$vmid.pid";
3225 sub vm_devices_list
{
3228 my $res = vm_mon_cmd
($vmid, 'query-pci');
3230 foreach my $pcibus (@$res) {
3231 foreach my $device (@{$pcibus->{devices
}}) {
3232 next if !$device->{'qdev_id'};
3233 if ($device->{'pci_bridge'}) {
3234 $devices->{$device->{'qdev_id'}} = 1;
3235 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3236 next if !$bridge_device->{'qdev_id'};
3237 $devices->{$bridge_device->{'qdev_id'}} = 1;
3238 $devices->{$device->{'qdev_id'}}++;
3241 $devices->{$device->{'qdev_id'}} = 1;
3246 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3247 foreach my $block (@$resblock) {
3248 if($block->{device
} =~ m/^drive-(\S+)/){
3253 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3254 foreach my $mice (@$resmice) {
3255 if ($mice->{name
} eq 'QEMU HID Tablet') {
3256 $devices->{tablet
} = 1;
3265 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3267 my $q35 = machine_type_is_q35
($conf);
3269 my $devices_list = vm_devices_list
($vmid);
3270 return 1 if defined($devices_list->{$deviceid});
3272 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3274 if ($deviceid eq 'tablet') {
3276 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3278 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3280 qemu_iothread_add
($vmid, $deviceid, $device);
3282 qemu_driveadd
($storecfg, $vmid, $device);
3283 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3285 qemu_deviceadd
($vmid, $devicefull);
3286 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3288 eval { qemu_drivedel
($vmid, $deviceid); };
3293 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3296 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3297 my $pciaddr = print_pci_addr
($deviceid);
3298 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3300 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3302 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3303 qemu_iothread_add
($vmid, $deviceid, $device);
3304 $devicefull .= ",iothread=iothread-$deviceid";
3307 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3308 $devicefull .= ",num_queues=$device->{queues}";
3311 qemu_deviceadd
($vmid, $devicefull);
3312 qemu_deviceaddverify
($vmid, $deviceid);
3314 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3316 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3317 qemu_driveadd
($storecfg, $vmid, $device);
3319 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3320 eval { qemu_deviceadd
($vmid, $devicefull); };
3322 eval { qemu_drivedel
($vmid, $deviceid); };
3327 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3329 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3330 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3331 qemu_deviceadd
($vmid, $netdevicefull);
3332 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3334 eval { qemu_netdevdel
($vmid, $deviceid); };
3339 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3342 my $pciaddr = print_pci_addr
($deviceid);
3343 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3345 qemu_deviceadd
($vmid, $devicefull);
3346 qemu_deviceaddverify
($vmid, $deviceid);
3349 die "can't hotplug device '$deviceid'\n";
3355 # fixme: this should raise exceptions on error!
3356 sub vm_deviceunplug
{
3357 my ($vmid, $conf, $deviceid) = @_;
3359 my $devices_list = vm_devices_list
($vmid);
3360 return 1 if !defined($devices_list->{$deviceid});
3362 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3364 if ($deviceid eq 'tablet') {
3366 qemu_devicedel
($vmid, $deviceid);
3368 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3370 qemu_devicedel
($vmid, $deviceid);
3371 qemu_devicedelverify
($vmid, $deviceid);
3372 qemu_drivedel
($vmid, $deviceid);
3373 qemu_iothread_del
($conf, $vmid, $deviceid);
3375 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3377 qemu_devicedel
($vmid, $deviceid);
3378 qemu_devicedelverify
($vmid, $deviceid);
3379 qemu_iothread_del
($conf, $vmid, $deviceid);
3381 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3383 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3384 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3385 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3387 qemu_devicedel
($vmid, $deviceid);
3388 qemu_drivedel
($vmid, $deviceid);
3389 qemu_deletescsihw
($conf, $vmid, $deviceid);
3391 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3393 qemu_devicedel
($vmid, $deviceid);
3394 qemu_devicedelverify
($vmid, $deviceid);
3395 qemu_netdevdel
($vmid, $deviceid);
3398 die "can't unplug device '$deviceid'\n";
3404 sub qemu_deviceadd
{
3405 my ($vmid, $devicefull) = @_;
3407 $devicefull = "driver=".$devicefull;
3408 my %options = split(/[=,]/, $devicefull);
3410 vm_mon_cmd
($vmid, "device_add" , %options);
3413 sub qemu_devicedel
{
3414 my ($vmid, $deviceid) = @_;
3416 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3419 sub qemu_iothread_add
{
3420 my($vmid, $deviceid, $device) = @_;
3422 if ($device->{iothread
}) {
3423 my $iothreads = vm_iothreads_list
($vmid);
3424 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3428 sub qemu_iothread_del
{
3429 my($conf, $vmid, $deviceid) = @_;
3431 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3432 if ($device->{iothread
}) {
3433 my $iothreads = vm_iothreads_list
($vmid);
3434 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3438 sub qemu_objectadd
{
3439 my($vmid, $objectid, $qomtype) = @_;
3441 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3446 sub qemu_objectdel
{
3447 my($vmid, $objectid) = @_;
3449 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3455 my ($storecfg, $vmid, $device) = @_;
3457 my $drive = print_drive_full
($storecfg, $vmid, $device);
3458 $drive =~ s/\\/\\\\/g;
3459 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3461 # If the command succeeds qemu prints: "OK
"
3462 return 1 if $ret =~ m/OK/s;
3464 die "adding drive failed
: $ret\n";
3468 my($vmid, $deviceid) = @_;
3470 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3473 return 1 if $ret eq "";
3475 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3476 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3478 die "deleting drive
$deviceid failed
: $ret\n";
3481 sub qemu_deviceaddverify {
3482 my ($vmid, $deviceid) = @_;
3484 for (my $i = 0; $i <= 5; $i++) {
3485 my $devices_list = vm_devices_list($vmid);
3486 return 1 if defined($devices_list->{$deviceid});
3490 die "error on hotplug device
'$deviceid'\n";
3494 sub qemu_devicedelverify {
3495 my ($vmid, $deviceid) = @_;
3497 # need to verify that the device is correctly removed as device_del
3498 # is async and empty return is not reliable
3500 for (my $i = 0; $i <= 5; $i++) {
3501 my $devices_list = vm_devices_list($vmid);
3502 return 1 if !defined($devices_list->{$deviceid});
3506 die "error on hot-unplugging device
'$deviceid'\n";
3509 sub qemu_findorcreatescsihw {
3510 my ($storecfg, $conf, $vmid, $device) = @_;
3512 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3514 my $scsihwid="$controller_prefix$controller";
3515 my $devices_list = vm_devices_list($vmid);
3517 if(!defined($devices_list->{$scsihwid})) {
3518 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3524 sub qemu_deletescsihw {
3525 my ($conf, $vmid, $opt) = @_;
3527 my $device = parse_drive($opt, $conf->{$opt});
3529 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3530 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3534 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3536 my $devices_list = vm_devices_list($vmid);
3537 foreach my $opt (keys %{$devices_list}) {
3538 if (PVE::QemuServer::valid_drivename($opt)) {
3539 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3540 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3546 my $scsihwid="scsihw
$controller";
3548 vm_deviceunplug($vmid, $conf, $scsihwid);
3553 sub qemu_add_pci_bridge {
3554 my ($storecfg, $conf, $vmid, $device) = @_;
3560 print_pci_addr($device, $bridges);
3562 while (my ($k, $v) = each %$bridges) {
3565 return 1 if !defined($bridgeid) || $bridgeid < 1;
3567 my $bridge = "pci
.$bridgeid";
3568 my $devices_list = vm_devices_list($vmid);
3570 if (!defined($devices_list->{$bridge})) {
3571 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3577 sub qemu_set_link_status {
3578 my ($vmid, $device, $up) = @_;
3580 vm_mon_cmd($vmid, "set_link
", name => $device,
3581 up => $up ? JSON::true : JSON::false);
3584 sub qemu_netdevadd {
3585 my ($vmid, $conf, $device, $deviceid) = @_;
3587 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3588 my %options = split(/[=,]/, $netdev);
3590 vm_mon_cmd($vmid, "netdev_add
", %options);
3594 sub qemu_netdevdel {
3595 my ($vmid, $deviceid) = @_;
3597 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3600 sub qemu_cpu_hotplug {
3601 my ($vmid, $conf, $vcpus) = @_;
3604 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3605 $sockets = $conf->{sockets} if $conf->{sockets};
3606 my $cores = $conf->{cores} || 1;
3607 my $maxcpus = $sockets * $cores;
3609 $vcpus = $maxcpus if !$vcpus;
3611 die "you can
't add more vcpus than maxcpus\n"
3612 if $vcpus > $maxcpus;
3614 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3615 die "online cpu unplug is not yet possible\n"
3616 if $vcpus < $currentvcpus;
3618 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3619 die "vcpus in running vm is different than configuration\n"
3620 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3622 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3623 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3627 sub qemu_memory_hotplug {
3628 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3630 return $value if !check_running($vmid);
3632 my $memory = $conf->{memory} || $defaults->{memory};
3633 $value = $defaults->{memory} if !$value;
3634 return $value if $value == $memory;
3636 my $static_memory = $STATICMEM;
3637 my $dimm_memory = $memory - $static_memory;
3639 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3640 die "memory unplug
is not yet available
" if $value < $memory;
3641 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3645 $sockets = $conf->{sockets} if $conf->{sockets};
3647 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3648 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3650 return if $current_size <= $conf->{memory};
3652 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3654 eval { qemu_objectdel($vmid, "mem-
$name"); };
3658 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3660 eval { qemu_objectdel($vmid, "mem-
$name"); };
3663 #update conf after each succesful module hotplug
3664 $conf->{memory} = $current_size;
3665 update_config_nolock($vmid, $conf, 1);
3669 sub qemu_block_set_io_throttle {
3670 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3672 return if !check_running($vmid) ;
3674 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));
3678 # old code, only used to shutdown old VM after update
3680 my ($fh, $timeout) = @_;
3682 my $sel = new IO::Select;
3689 while (scalar (@ready = $sel->can_read($timeout))) {
3691 if ($count = $fh->sysread($buf, 8192)) {
3692 if ($buf =~ /^(.*)\(qemu\) $/s) {
3699 if (!defined($count)) {
3706 die "monitor
read timeout
\n" if !scalar(@ready);
3711 # old code, only used to shutdown old VM after update
3712 sub vm_monitor_command {
3713 my ($vmid, $cmdstr, $nocheck) = @_;
3718 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3720 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3722 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3723 die "unable to
connect to VM
$vmid socket - $!\n";
3727 # hack: migrate sometime blocks the monitor (when migrate_downtime
3729 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3730 $timeout = 60*60; # 1 hour
3734 my $data = __read_avail($sock, $timeout);
3736 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3737 die "got unexpected qemu monitor banner
\n";
3740 my $sel = new IO::Select;
3743 if (!scalar(my @ready = $sel->can_write($timeout))) {
3744 die "monitor
write error
- timeout
";
3747 my $fullcmd = "$cmdstr\r";
3749 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3752 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3753 die "monitor
write error
- $!";
3756 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3760 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3761 $timeout = 60*60; # 1 hour
3762 } elsif ($cmdstr =~ m/^(eject|change)/) {
3763 $timeout = 60; # note: cdrom mount command is slow
3765 if ($res = __read_avail($sock, $timeout)) {
3767 my @lines = split("\r?
\n", $res);
3769 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3771 $res = join("\n", @lines);
3779 syslog("err
", "VM
$vmid monitor command failed
- $err");
3786 sub qemu_block_resize {
3787 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3789 my $running = check_running($vmid);
3791 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3793 return if !$running;
3795 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3799 sub qemu_volume_snapshot {
3800 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3802 my $running = check_running($vmid);
3804 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3805 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3807 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3811 sub qemu_volume_snapshot_delete {
3812 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3814 my $running = check_running($vmid);
3816 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3818 return if !$running;
3820 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3823 sub set_migration_caps {
3829 "auto-converge
" => 1,
3831 "x-rdma-pin-all
" => 0,
3835 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3837 for my $supported_capability (@$supported_capabilities) {
3839 capability => $supported_capability->{capability},
3840 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3844 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3847 my $fast_plug_option = {
3855 # hotplug changes in [PENDING]
3856 # $selection hash can be used to only apply specified options, for
3857 # example: { cores => 1 } (only apply changed 'cores')
3858 # $errors ref is used to return error messages
3859 sub vmconfig_hotplug_pending {
3860 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3862 my $defaults = load_defaults();
3864 # commit values which do not have any impact on running VM first
3865 # Note: those option cannot raise errors, we we do not care about
3866 # $selection and always apply them.
3868 my $add_error = sub {
3869 my ($opt, $msg) = @_;
3870 $errors->{$opt} = "hotplug problem
- $msg";
3874 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3875 if ($fast_plug_option->{$opt}) {
3876 $conf->{$opt} = $conf->{pending}->{$opt};
3877 delete $conf->{pending}->{$opt};
3883 update_config_nolock($vmid, $conf, 1);
3884 $conf = load_config($vmid); # update/reload
3887 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3889 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3890 foreach my $opt (@delete) {
3891 next if $selection && !$selection->{$opt};
3893 if ($opt eq 'hotplug') {
3894 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3895 } elsif ($opt eq 'tablet') {
3896 die "skip
\n" if !$hotplug_features->{usb};
3897 if ($defaults->{tablet}) {
3898 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3900 vm_deviceunplug($vmid, $conf, $opt);
3902 } elsif ($opt eq 'vcpus') {
3903 die "skip
\n" if !$hotplug_features->{cpu};
3904 qemu_cpu_hotplug($vmid, $conf, undef);
3905 } elsif ($opt eq 'balloon') {
3906 # enable balloon device is not hotpluggable
3907 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3908 } elsif ($fast_plug_option->{$opt}) {
3910 } elsif ($opt =~ m/^net(\d+)$/) {
3911 die "skip
\n" if !$hotplug_features->{network};
3912 vm_deviceunplug($vmid, $conf, $opt);
3913 } elsif (valid_drivename($opt)) {
3914 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3915 vm_deviceunplug($vmid, $conf, $opt);
3916 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3917 } elsif ($opt =~ m/^memory$/) {
3918 die "skip
\n" if !$hotplug_features->{memory};
3919 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3920 } elsif ($opt eq 'cpuunits') {
3921 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3927 &$add_error($opt, $err) if $err ne "skip
\n";
3929 # save new config if hotplug was successful
3930 delete $conf->{$opt};
3931 vmconfig_undelete_pending_option($conf, $opt);
3932 update_config_nolock($vmid, $conf, 1);
3933 $conf = load_config($vmid); # update/reload
3937 foreach my $opt (keys %{$conf->{pending}}) {
3938 next if $selection && !$selection->{$opt};
3939 my $value = $conf->{pending}->{$opt};
3941 if ($opt eq 'hotplug') {
3942 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3943 } elsif ($opt eq 'tablet') {
3944 die "skip
\n" if !$hotplug_features->{usb};
3946 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3947 } elsif ($value == 0) {
3948 vm_deviceunplug($vmid, $conf, $opt);
3950 } elsif ($opt eq 'vcpus') {
3951 die "skip
\n" if !$hotplug_features->{cpu};
3952 qemu_cpu_hotplug($vmid, $conf, $value);
3953 } elsif ($opt eq 'balloon') {
3954 # enable/disable balloning device is not hotpluggable
3955 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3956 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3957 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3959 # allow manual ballooning if shares is set to zero
3960 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3961 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3962 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3964 } elsif ($opt =~ m/^net(\d+)$/) {
3965 # some changes can be done without hotplug
3966 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3967 $vmid, $opt, $value);
3968 } elsif (valid_drivename($opt)) {
3969 # some changes can be done without hotplug
3970 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3971 $vmid, $opt, $value, 1);
3972 } elsif ($opt =~ m/^memory$/) { #dimms
3973 die "skip
\n" if !$hotplug_features->{memory};
3974 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3975 } elsif ($opt eq 'cpuunits') {
3976 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
3978 die "skip
\n"; # skip non-hot-pluggable options
3982 &$add_error($opt, $err) if $err ne "skip
\n";
3984 # save new config if hotplug was successful
3985 $conf->{$opt} = $value;
3986 delete $conf->{pending}->{$opt};
3987 update_config_nolock($vmid, $conf, 1);
3988 $conf = load_config($vmid); # update/reload
3993 sub vmconfig_apply_pending {
3994 my ($vmid, $conf, $storecfg) = @_;
3998 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3999 foreach my $opt (@delete) { # delete
4000 die "internal error
" if $opt =~ m/^unused/;
4001 $conf = load_config($vmid); # update/reload
4002 if (!defined($conf->{$opt})) {
4003 vmconfig_undelete_pending_option($conf, $opt);
4004 update_config_nolock($vmid, $conf, 1);
4005 } elsif (valid_drivename($opt)) {
4006 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
4007 vmconfig_undelete_pending_option($conf, $opt);
4008 delete $conf->{$opt};
4009 update_config_nolock($vmid, $conf, 1);
4011 vmconfig_undelete_pending_option($conf, $opt);
4012 delete $conf->{$opt};
4013 update_config_nolock($vmid, $conf, 1);
4017 $conf = load_config($vmid); # update/reload
4019 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4020 $conf = load_config($vmid); # update/reload
4022 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4023 # skip if nothing changed
4024 } elsif (valid_drivename($opt)) {
4025 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4026 if defined($conf->{$opt});
4027 $conf->{$opt} = $conf->{pending}->{$opt};
4029 $conf->{$opt} = $conf->{pending}->{$opt};
4032 delete $conf->{pending}->{$opt};
4033 update_config_nolock($vmid, $conf, 1);
4037 my $safe_num_ne = sub {
4040 return 0 if !defined($a) && !defined($b);
4041 return 1 if !defined($a);
4042 return 1 if !defined($b);
4047 my $safe_string_ne = sub {
4050 return 0 if !defined($a) && !defined($b);
4051 return 1 if !defined($a);
4052 return 1 if !defined($b);
4057 sub vmconfig_update_net {
4058 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4060 my $newnet = parse_net($value);
4062 if ($conf->{$opt}) {
4063 my $oldnet = parse_net($conf->{$opt});
4065 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4066 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4067 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4068 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4070 # for non online change, we try to hot-unplug
4071 die "skip
\n" if !$hotplug;
4072 vm_deviceunplug($vmid, $conf, $opt);
4075 die "internal error
" if $opt !~ m/net(\d+)/;
4076 my $iface = "tap
${vmid
}i
$1";
4078 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4079 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4082 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4083 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4084 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4085 PVE::Network::tap_unplug($iface);
4086 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4089 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4090 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4098 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4104 sub vmconfig_update_disk {
4105 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4107 # fixme: do we need force?
4109 my $drive = parse_drive($opt, $value);
4111 if ($conf->{$opt}) {
4113 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4115 my $media = $drive->{media} || 'disk';
4116 my $oldmedia = $old_drive->{media} || 'disk';
4117 die "unable to change media type
\n" if $media ne $oldmedia;
4119 if (!drive_is_cdrom($old_drive)) {
4121 if ($drive->{file} ne $old_drive->{file}) {
4123 die "skip
\n" if !$hotplug;
4125 # unplug and register as unused
4126 vm_deviceunplug($vmid, $conf, $opt);
4127 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4130 # update existing disk
4132 # skip non hotpluggable value
4133 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4134 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4135 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4136 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4141 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4142 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4143 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4144 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4145 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4146 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4147 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4148 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4149 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4150 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4151 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4152 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4154 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4155 ($drive->{mbps} || 0)*1024*1024,
4156 ($drive->{mbps_rd} || 0)*1024*1024,
4157 ($drive->{mbps_wr} || 0)*1024*1024,
4158 $drive->{iops} || 0,
4159 $drive->{iops_rd} || 0,
4160 $drive->{iops_wr} || 0,
4161 ($drive->{mbps_max} || 0)*1024*1024,
4162 ($drive->{mbps_rd_max} || 0)*1024*1024,
4163 ($drive->{mbps_wr_max} || 0)*1024*1024,
4164 $drive->{iops_max} || 0,
4165 $drive->{iops_rd_max} || 0,
4166 $drive->{iops_wr_max} || 0);
4175 if ($drive->{file} eq 'none') {
4176 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4178 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4179 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4180 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4188 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4190 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4194 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4196 lock_config($vmid, sub {
4197 my $conf = load_config($vmid, $migratedfrom);
4199 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4201 check_lock($conf) if !$skiplock;
4203 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4205 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4206 vmconfig_apply_pending($vmid, $conf, $storecfg);
4207 $conf = load_config($vmid); # update/reload
4210 my $defaults = load_defaults();
4212 # set environment variable useful inside network script
4213 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4215 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4217 my $migrate_port = 0;
4220 if ($statefile eq 'tcp') {
4221 my $localip = "localhost
";
4222 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4223 my $nodename = PVE::INotify::nodename();
4224 if ($datacenterconf->{migration_unsecure}) {
4225 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4227 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4228 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4229 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4230 push @$cmd, '-incoming', $migrate_uri;
4233 push @$cmd, '-loadstate', $statefile;
4240 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4241 my $d = parse_hostpci($conf->{"hostpci
$i"});
4243 my $pcidevices = $d->{pciid};
4244 foreach my $pcidevice (@$pcidevices) {
4245 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4247 my $info = pci_device_info("0000:$pciid");
4248 die "IOMMU
not present
\n" if !check_iommu_support();
4249 die "no pci device info
for device
'$pciid'\n" if !$info;
4251 if ($d->{driver} && $d->{driver} eq "vfio
") {
4252 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4254 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4257 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4261 PVE::Storage::activate_volumes($storecfg, $vollist);
4263 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4266 die "start failed: $err" if $err;
4268 print "migration listens on $migrate_uri\n" if $migrate_uri;
4270 if ($statefile && $statefile ne 'tcp
') {
4271 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4275 if ($migratedfrom) {
4278 set_migration_caps($vmid);
4283 print "spice listens on port $spice_port\n";
4284 if ($spice_ticket) {
4285 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4286 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4292 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4293 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4294 if $conf->{balloon};
4297 foreach my $opt (keys %$conf) {
4298 next if $opt !~ m/^net\d+$/;
4299 my $nicconf = parse_net($conf->{$opt});
4300 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4304 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4305 path => "machine/peripheral/balloon0",
4306 property => "guest-stats-polling-interval",
4307 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4313 my ($vmid, $execute, %params) = @_;
4315 my $cmd = { execute => $execute, arguments => \%params };
4316 vm_qmp_command($vmid, $cmd);
4319 sub vm_mon_cmd_nocheck {
4320 my ($vmid, $execute, %params) = @_;
4322 my $cmd = { execute => $execute, arguments => \%params };
4323 vm_qmp_command($vmid, $cmd, 1);
4326 sub vm_qmp_command {
4327 my ($vmid, $cmd, $nocheck) = @_;
4332 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4333 $timeout = $cmd->{arguments}->{timeout};
4334 delete $cmd->{arguments}->{timeout};
4338 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4339 my $sname = qmp_socket($vmid);
4340 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4341 my $qmpclient = PVE::QMPClient->new();
4343 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4344 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4345 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4346 if scalar(%{$cmd->{arguments}});
4347 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4349 die "unable to
open monitor
socket\n";
4353 syslog("err
", "VM
$vmid qmp command failed
- $err");
4360 sub vm_human_monitor_command {
4361 my ($vmid, $cmdline) = @_;
4366 execute => 'human-monitor-command',
4367 arguments => { 'command-line' => $cmdline},
4370 return vm_qmp_command($vmid, $cmd);
4373 sub vm_commandline {
4374 my ($storecfg, $vmid) = @_;
4376 my $conf = load_config($vmid);
4378 my $defaults = load_defaults();
4380 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4382 return join(' ', @$cmd);
4386 my ($vmid, $skiplock) = @_;
4388 lock_config($vmid, sub {
4390 my $conf = load_config($vmid);
4392 check_lock($conf) if !$skiplock;
4394 vm_mon_cmd($vmid, "system_reset
");
4398 sub get_vm_volumes {
4402 foreach_volid($conf, sub {
4403 my ($volid, $is_cdrom) = @_;
4405 return if $volid =~ m|^/|;
4407 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4410 push @$vollist, $volid;
4416 sub vm_stop_cleanup {
4417 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4420 fairsched_rmnod($vmid); # try to destroy group
4423 my $vollist = get_vm_volumes($conf);
4424 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4427 foreach my $ext (qw(mon qmp pid vnc qga)) {
4428 unlink "/var/run/qemu-server/${vmid}.$ext";
4431 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4433 warn $@ if $@; # avoid errors - just warn
4436 # Note: use $nockeck to skip tests if VM configuration file exists.
4437 # We need that when migration VMs to other nodes (files already moved)
4438 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4440 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4442 $force = 1 if !defined($force) && !$shutdown;
4445 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4446 kill 15, $pid if $pid;
4447 my $conf = load_config
($vmid, $migratedfrom);
4448 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4452 lock_config
($vmid, sub {
4454 my $pid = check_running
($vmid, $nocheck);
4459 $conf = load_config
($vmid);
4460 check_lock
($conf) if !$skiplock;
4461 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4462 my $opts = parse_startup
($conf->{startup
});
4463 $timeout = $opts->{down
} if $opts->{down
};
4467 $timeout = 60 if !defined($timeout);
4471 if (defined($conf) && $conf->{agent
}) {
4472 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4474 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4477 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4484 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4489 if ($count >= $timeout) {
4491 warn "VM still running - terminating now with SIGTERM\n";
4494 die "VM quit/powerdown failed - got timeout\n";
4497 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4502 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4505 die "VM quit/powerdown failed\n";
4513 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4518 if ($count >= $timeout) {
4519 warn "VM still running - terminating now with SIGKILL\n";
4524 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4529 my ($vmid, $skiplock) = @_;
4531 lock_config
($vmid, sub {
4533 my $conf = load_config
($vmid);
4535 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4537 vm_mon_cmd
($vmid, "stop");
4542 my ($vmid, $skiplock) = @_;
4544 lock_config
($vmid, sub {
4546 my $conf = load_config
($vmid);
4548 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4550 vm_mon_cmd
($vmid, "cont");
4555 my ($vmid, $skiplock, $key) = @_;
4557 lock_config
($vmid, sub {
4559 my $conf = load_config
($vmid);
4561 # there is no qmp command, so we use the human monitor command
4562 vm_human_monitor_command
($vmid, "sendkey $key");
4567 my ($storecfg, $vmid, $skiplock) = @_;
4569 lock_config
($vmid, sub {
4571 my $conf = load_config
($vmid);
4573 check_lock
($conf) if !$skiplock;
4575 if (!check_running
($vmid)) {
4576 fairsched_rmnod
($vmid); # try to destroy group
4577 destroy_vm
($storecfg, $vmid);
4579 die "VM $vmid is running - destroy failed\n";
4587 my ($filename, $buf) = @_;
4589 my $fh = IO
::File-
>new($filename, "w");
4590 return undef if !$fh;
4592 my $res = print $fh $buf;
4599 sub pci_device_info
{
4604 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4605 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4607 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4608 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4610 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4611 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4613 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4614 return undef if !defined($product) || $product !~ s/^0x//;
4619 product
=> $product,
4625 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4634 my $name = $dev->{name
};
4636 my $fn = "$pcisysfs/devices/$name/reset";
4638 return file_write
($fn, "1");
4641 sub pci_dev_bind_to_stub
{
4644 my $name = $dev->{name
};
4646 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4647 return 1 if -d
$testdir;
4649 my $data = "$dev->{vendor} $dev->{product}";
4650 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4652 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4653 if (!file_write
($fn, $name)) {
4654 return undef if -f
$fn;
4657 $fn = "$pcisysfs/drivers/pci-stub/bind";
4658 if (! -d
$testdir) {
4659 return undef if !file_write
($fn, $name);
4665 sub pci_dev_bind_to_vfio
{
4668 my $name = $dev->{name
};
4670 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4672 if (!-d
$vfio_basedir) {
4673 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4675 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4677 my $testdir = "$vfio_basedir/$name";
4678 return 1 if -d
$testdir;
4680 my $data = "$dev->{vendor} $dev->{product}";
4681 return undef if !file_write
("$vfio_basedir/new_id", $data);
4683 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4684 if (!file_write
($fn, $name)) {
4685 return undef if -f
$fn;
4688 $fn = "$vfio_basedir/bind";
4689 if (! -d
$testdir) {
4690 return undef if !file_write
($fn, $name);
4696 sub pci_dev_group_bind_to_vfio
{
4699 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4701 if (!-d
$vfio_basedir) {
4702 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4704 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4706 # get IOMMU group devices
4707 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4708 my @devs = grep /^0000:/, readdir($D);
4711 foreach my $pciid (@devs) {
4712 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4714 # pci bridges, switches or root ports are not supported
4715 # they have a pci_bus subdirectory so skip them
4716 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4718 my $info = pci_device_info
($1);
4719 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4725 sub print_pci_addr
{
4726 my ($id, $bridges) = @_;
4730 piix3
=> { bus
=> 0, addr
=> 1 },
4731 #addr2 : first videocard
4732 balloon0
=> { bus
=> 0, addr
=> 3 },
4733 watchdog
=> { bus
=> 0, addr
=> 4 },
4734 scsihw0
=> { bus
=> 0, addr
=> 5 },
4735 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4736 scsihw1
=> { bus
=> 0, addr
=> 6 },
4737 ahci0
=> { bus
=> 0, addr
=> 7 },
4738 qga0
=> { bus
=> 0, addr
=> 8 },
4739 spice
=> { bus
=> 0, addr
=> 9 },
4740 virtio0
=> { bus
=> 0, addr
=> 10 },
4741 virtio1
=> { bus
=> 0, addr
=> 11 },
4742 virtio2
=> { bus
=> 0, addr
=> 12 },
4743 virtio3
=> { bus
=> 0, addr
=> 13 },
4744 virtio4
=> { bus
=> 0, addr
=> 14 },
4745 virtio5
=> { bus
=> 0, addr
=> 15 },
4746 hostpci0
=> { bus
=> 0, addr
=> 16 },
4747 hostpci1
=> { bus
=> 0, addr
=> 17 },
4748 net0
=> { bus
=> 0, addr
=> 18 },
4749 net1
=> { bus
=> 0, addr
=> 19 },
4750 net2
=> { bus
=> 0, addr
=> 20 },
4751 net3
=> { bus
=> 0, addr
=> 21 },
4752 net4
=> { bus
=> 0, addr
=> 22 },
4753 net5
=> { bus
=> 0, addr
=> 23 },
4754 vga1
=> { bus
=> 0, addr
=> 24 },
4755 vga2
=> { bus
=> 0, addr
=> 25 },
4756 vga3
=> { bus
=> 0, addr
=> 26 },
4757 hostpci2
=> { bus
=> 0, addr
=> 27 },
4758 hostpci3
=> { bus
=> 0, addr
=> 28 },
4759 #addr29 : usb-host (pve-usb.cfg)
4760 'pci.1' => { bus
=> 0, addr
=> 30 },
4761 'pci.2' => { bus
=> 0, addr
=> 31 },
4762 'net6' => { bus
=> 1, addr
=> 1 },
4763 'net7' => { bus
=> 1, addr
=> 2 },
4764 'net8' => { bus
=> 1, addr
=> 3 },
4765 'net9' => { bus
=> 1, addr
=> 4 },
4766 'net10' => { bus
=> 1, addr
=> 5 },
4767 'net11' => { bus
=> 1, addr
=> 6 },
4768 'net12' => { bus
=> 1, addr
=> 7 },
4769 'net13' => { bus
=> 1, addr
=> 8 },
4770 'net14' => { bus
=> 1, addr
=> 9 },
4771 'net15' => { bus
=> 1, addr
=> 10 },
4772 'net16' => { bus
=> 1, addr
=> 11 },
4773 'net17' => { bus
=> 1, addr
=> 12 },
4774 'net18' => { bus
=> 1, addr
=> 13 },
4775 'net19' => { bus
=> 1, addr
=> 14 },
4776 'net20' => { bus
=> 1, addr
=> 15 },
4777 'net21' => { bus
=> 1, addr
=> 16 },
4778 'net22' => { bus
=> 1, addr
=> 17 },
4779 'net23' => { bus
=> 1, addr
=> 18 },
4780 'net24' => { bus
=> 1, addr
=> 19 },
4781 'net25' => { bus
=> 1, addr
=> 20 },
4782 'net26' => { bus
=> 1, addr
=> 21 },
4783 'net27' => { bus
=> 1, addr
=> 22 },
4784 'net28' => { bus
=> 1, addr
=> 23 },
4785 'net29' => { bus
=> 1, addr
=> 24 },
4786 'net30' => { bus
=> 1, addr
=> 25 },
4787 'net31' => { bus
=> 1, addr
=> 26 },
4788 'virtio6' => { bus
=> 2, addr
=> 1 },
4789 'virtio7' => { bus
=> 2, addr
=> 2 },
4790 'virtio8' => { bus
=> 2, addr
=> 3 },
4791 'virtio9' => { bus
=> 2, addr
=> 4 },
4792 'virtio10' => { bus
=> 2, addr
=> 5 },
4793 'virtio11' => { bus
=> 2, addr
=> 6 },
4794 'virtio12' => { bus
=> 2, addr
=> 7 },
4795 'virtio13' => { bus
=> 2, addr
=> 8 },
4796 'virtio14' => { bus
=> 2, addr
=> 9 },
4797 'virtio15' => { bus
=> 2, addr
=> 10 },
4798 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4799 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4800 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4801 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4802 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4803 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4804 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4805 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4806 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4807 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4808 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4809 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4810 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4811 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4812 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4813 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4814 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4815 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4816 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4817 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4818 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4819 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4820 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4821 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4822 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4823 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4824 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4825 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4826 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4827 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4828 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4832 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4833 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4834 my $bus = $devices->{$id}->{bus
};
4835 $res = ",bus=pci.$bus,addr=$addr";
4836 $bridges->{$bus} = 1 if $bridges;
4842 sub print_pcie_addr
{
4847 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4848 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4849 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4850 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4853 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4854 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4855 my $bus = $devices->{$id}->{bus
};
4856 $res = ",bus=$bus,addr=$addr";
4862 # vzdump restore implementaion
4864 sub tar_archive_read_firstfile
{
4865 my $archive = shift;
4867 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4869 # try to detect archive type first
4870 my $pid = open (TMP
, "tar tf '$archive'|") ||
4871 die "unable to open file '$archive'\n";
4872 my $firstfile = <TMP
>;
4876 die "ERROR: archive contaions no data\n" if !$firstfile;
4882 sub tar_restore_cleanup
{
4883 my ($storecfg, $statfile) = @_;
4885 print STDERR
"starting cleanup\n";
4887 if (my $fd = IO
::File-
>new($statfile, "r")) {
4888 while (defined(my $line = <$fd>)) {
4889 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4892 if ($volid =~ m
|^/|) {
4893 unlink $volid || die 'unlink failed\n';
4895 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4897 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4899 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4901 print STDERR
"unable to parse line in statfile - $line";
4908 sub restore_archive
{
4909 my ($archive, $vmid, $user, $opts) = @_;
4911 my $format = $opts->{format
};
4914 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4915 $format = 'tar' if !$format;
4917 } elsif ($archive =~ m/\.tar$/) {
4918 $format = 'tar' if !$format;
4919 } elsif ($archive =~ m/.tar.lzo$/) {
4920 $format = 'tar' if !$format;
4922 } elsif ($archive =~ m/\.vma$/) {
4923 $format = 'vma' if !$format;
4924 } elsif ($archive =~ m/\.vma\.gz$/) {
4925 $format = 'vma' if !$format;
4927 } elsif ($archive =~ m/\.vma\.lzo$/) {
4928 $format = 'vma' if !$format;
4931 $format = 'vma' if !$format; # default
4934 # try to detect archive format
4935 if ($format eq 'tar') {
4936 return restore_tar_archive
($archive, $vmid, $user, $opts);
4938 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4942 sub restore_update_config_line
{
4943 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4945 return if $line =~ m/^\#qmdump\#/;
4946 return if $line =~ m/^\#vzdump\#/;
4947 return if $line =~ m/^lock:/;
4948 return if $line =~ m/^unused\d+:/;
4949 return if $line =~ m/^parent:/;
4950 return if $line =~ m/^template:/; # restored VM is never a template
4952 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4953 # try to convert old 1.X settings
4954 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4955 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4956 my ($model, $macaddr) = split(/\=/, $devconfig);
4957 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4960 bridge
=> "vmbr$ind",
4961 macaddr
=> $macaddr,
4963 my $netstr = print_net
($net);
4965 print $outfd "net$cookie->{netcount}: $netstr\n";
4966 $cookie->{netcount
}++;
4968 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4969 my ($id, $netstr) = ($1, $2);
4970 my $net = parse_net
($netstr);
4971 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4972 $netstr = print_net
($net);
4973 print $outfd "$id: $netstr\n";
4974 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4977 if ($line =~ m/backup=no/) {
4978 print $outfd "#$line";
4979 } elsif ($virtdev && $map->{$virtdev}) {
4980 my $di = parse_drive
($virtdev, $value);
4981 delete $di->{format
}; # format can change on restore
4982 $di->{file
} = $map->{$virtdev};
4983 $value = print_drive
($vmid, $di);
4984 print $outfd "$virtdev: $value\n";
4994 my ($cfg, $vmid) = @_;
4996 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4998 my $volid_hash = {};
4999 foreach my $storeid (keys %$info) {
5000 foreach my $item (@{$info->{$storeid}}) {
5001 next if !($item->{volid
} && $item->{size
});
5002 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5003 $volid_hash->{$item->{volid
}} = $item;
5010 sub get_used_paths
{
5011 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5015 my $scan_config = sub {
5016 my ($cref, $snapname) = @_;
5018 foreach my $key (keys %$cref) {
5019 my $value = $cref->{$key};
5020 if (valid_drivename
($key)) {
5021 next if $skip_drive && $key eq $skip_drive;
5022 my $drive = parse_drive
($key, $value);
5023 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5024 if ($drive->{file
} =~ m!^/!) {
5025 $used_path->{$drive->{file
}}++; # = 1;
5027 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5029 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5031 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5032 $used_path->{$path}++; # = 1;
5038 &$scan_config($conf);
5042 if ($scan_snapshots) {
5043 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5044 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5051 sub update_disksize
{
5052 my ($vmid, $conf, $volid_hash) = @_;
5058 # Note: it is allowed to define multiple storages with same path (alias), so
5059 # we need to check both 'volid' and real 'path' (two different volid can point
5060 # to the same path).
5065 foreach my $opt (keys %$conf) {
5066 if (valid_drivename
($opt)) {
5067 my $drive = parse_drive
($opt, $conf->{$opt});
5068 my $volid = $drive->{file
};
5071 $used->{$volid} = 1;
5072 if ($volid_hash->{$volid} &&
5073 (my $path = $volid_hash->{$volid}->{path
})) {
5074 $usedpath->{$path} = 1;
5077 next if drive_is_cdrom
($drive);
5078 next if !$volid_hash->{$volid};
5080 $drive->{size
} = $volid_hash->{$volid}->{size
};
5081 my $new = print_drive
($vmid, $drive);
5082 if ($new ne $conf->{$opt}) {
5084 $conf->{$opt} = $new;
5089 # remove 'unusedX' entry if volume is used
5090 foreach my $opt (keys %$conf) {
5091 next if $opt !~ m/^unused\d+$/;
5092 my $volid = $conf->{$opt};
5093 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5094 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5096 delete $conf->{$opt};
5100 foreach my $volid (sort keys %$volid_hash) {
5101 next if $volid =~ m/vm-$vmid-state-/;
5102 next if $used->{$volid};
5103 my $path = $volid_hash->{$volid}->{path
};
5104 next if !$path; # just to be sure
5105 next if $usedpath->{$path};
5107 add_unused_volume
($conf, $volid);
5108 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5115 my ($vmid, $nolock) = @_;
5117 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5119 my $volid_hash = scan_volids
($cfg, $vmid);
5121 my $updatefn = sub {
5124 my $conf = load_config
($vmid);
5129 foreach my $volid (keys %$volid_hash) {
5130 my $info = $volid_hash->{$volid};
5131 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5134 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5136 update_config_nolock
($vmid, $conf, 1) if $changes;
5139 if (defined($vmid)) {
5143 lock_config
($vmid, $updatefn, $vmid);
5146 my $vmlist = config_list
();
5147 foreach my $vmid (keys %$vmlist) {
5151 lock_config
($vmid, $updatefn, $vmid);
5157 sub restore_vma_archive
{
5158 my ($archive, $vmid, $user, $opts, $comp) = @_;
5160 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5161 my $readfrom = $archive;
5166 my $qarchive = PVE
::Tools
::shellquote
($archive);
5167 if ($comp eq 'gzip') {
5168 $uncomp = "zcat $qarchive|";
5169 } elsif ($comp eq 'lzop') {
5170 $uncomp = "lzop -d -c $qarchive|";
5172 die "unknown compression method '$comp'\n";
5177 my $tmpdir = "/var/tmp/vzdumptmp$$";
5180 # disable interrupts (always do cleanups)
5181 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5182 warn "got interrupt - ignored\n";
5185 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5186 POSIX
::mkfifo
($mapfifo, 0600);
5189 my $openfifo = sub {
5190 open($fifofh, '>', $mapfifo) || die $!;
5193 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5200 my $rpcenv = PVE
::RPCEnvironment
::get
();
5202 my $conffile = config_file
($vmid);
5203 my $tmpfn = "$conffile.$$.tmp";
5205 # Note: $oldconf is undef if VM does not exists
5206 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5208 my $print_devmap = sub {
5209 my $virtdev_hash = {};
5211 my $cfgfn = "$tmpdir/qemu-server.conf";
5213 # we can read the config - that is already extracted
5214 my $fh = IO
::File-
>new($cfgfn, "r") ||
5215 "unable to read qemu-server.conf - $!\n";
5217 while (defined(my $line = <$fh>)) {
5218 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5219 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5220 die "archive does not contain data for drive '$virtdev'\n"
5221 if !$devinfo->{$devname};
5222 if (defined($opts->{storage
})) {
5223 $storeid = $opts->{storage
} || 'local';
5224 } elsif (!$storeid) {
5227 $format = 'raw' if !$format;
5228 $devinfo->{$devname}->{devname
} = $devname;
5229 $devinfo->{$devname}->{virtdev
} = $virtdev;
5230 $devinfo->{$devname}->{format
} = $format;
5231 $devinfo->{$devname}->{storeid
} = $storeid;
5233 # check permission on storage
5234 my $pool = $opts->{pool
}; # todo: do we need that?
5235 if ($user ne 'root@pam') {
5236 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5239 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5243 foreach my $devname (keys %$devinfo) {
5244 die "found no device mapping information for device '$devname'\n"
5245 if !$devinfo->{$devname}->{virtdev
};
5248 my $cfg = cfs_read_file
('storage.cfg');
5250 # create empty/temp config
5252 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5253 foreach_drive
($oldconf, sub {
5254 my ($ds, $drive) = @_;
5256 return if drive_is_cdrom
($drive);
5258 my $volid = $drive->{file
};
5260 return if !$volid || $volid =~ m
|^/|;
5262 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5263 return if !$path || !$owner || ($owner != $vmid);
5265 # Note: only delete disk we want to restore
5266 # other volumes will become unused
5267 if ($virtdev_hash->{$ds}) {
5268 PVE
::Storage
::vdisk_free
($cfg, $volid);
5274 foreach my $virtdev (sort keys %$virtdev_hash) {
5275 my $d = $virtdev_hash->{$virtdev};
5276 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5277 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5279 # test if requested format is supported
5280 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5281 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5282 $d->{format
} = $defFormat if !$supported;
5284 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5285 $d->{format
}, undef, $alloc_size);
5286 print STDERR
"new volume ID is '$volid'\n";
5287 $d->{volid
} = $volid;
5288 my $path = PVE
::Storage
::path
($cfg, $volid);
5290 my $write_zeros = 1;
5291 # fixme: what other storages types initialize volumes with zero?
5292 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5293 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5297 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5299 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5300 $map->{$virtdev} = $volid;
5303 $fh->seek(0, 0) || die "seek failed - $!\n";
5305 my $outfd = new IO
::File
($tmpfn, "w") ||
5306 die "unable to write config for VM $vmid\n";
5308 my $cookie = { netcount
=> 0 };
5309 while (defined(my $line = <$fh>)) {
5310 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5319 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5320 die "interrupted by signal\n";
5322 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5324 $oldtimeout = alarm($timeout);
5331 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5332 my ($dev_id, $size, $devname) = ($1, $2, $3);
5333 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5334 } elsif ($line =~ m/^CTIME: /) {
5335 # we correctly received the vma config, so we can disable
5336 # the timeout now for disk allocation (set to 10 minutes, so
5337 # that we always timeout if something goes wrong)
5340 print $fifofh "done\n";
5341 my $tmp = $oldtimeout || 0;
5342 $oldtimeout = undef;
5348 print "restore vma archive: $cmd\n";
5349 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5353 alarm($oldtimeout) if $oldtimeout;
5361 my $cfg = cfs_read_file
('storage.cfg');
5362 foreach my $devname (keys %$devinfo) {
5363 my $volid = $devinfo->{$devname}->{volid
};
5366 if ($volid =~ m
|^/|) {
5367 unlink $volid || die 'unlink failed\n';
5369 PVE
::Storage
::vdisk_free
($cfg, $volid);
5371 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5373 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5380 rename($tmpfn, $conffile) ||
5381 die "unable to commit configuration file '$conffile'\n";
5383 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5385 eval { rescan
($vmid, 1); };
5389 sub restore_tar_archive
{
5390 my ($archive, $vmid, $user, $opts) = @_;
5392 if ($archive ne '-') {
5393 my $firstfile = tar_archive_read_firstfile
($archive);
5394 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5395 if $firstfile ne 'qemu-server.conf';
5398 my $storecfg = cfs_read_file
('storage.cfg');
5400 # destroy existing data - keep empty config
5401 my $vmcfgfn = config_file
($vmid);
5402 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5404 my $tocmd = "/usr/lib/qemu-server/qmextract";
5406 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5407 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5408 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5409 $tocmd .= ' --info' if $opts->{info
};
5411 # tar option "xf" does not autodetect compression when read from STDIN,
5412 # so we pipe to zcat
5413 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5414 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5416 my $tmpdir = "/var/tmp/vzdumptmp$$";
5419 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5420 local $ENV{VZDUMP_VMID
} = $vmid;
5421 local $ENV{VZDUMP_USER
} = $user;
5423 my $conffile = config_file
($vmid);
5424 my $tmpfn = "$conffile.$$.tmp";
5426 # disable interrupts (always do cleanups)
5427 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5428 print STDERR
"got interrupt - ignored\n";
5433 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5434 die "interrupted by signal\n";
5437 if ($archive eq '-') {
5438 print "extracting archive from STDIN\n";
5439 run_command
($cmd, input
=> "<&STDIN");
5441 print "extracting archive '$archive'\n";
5445 return if $opts->{info
};
5449 my $statfile = "$tmpdir/qmrestore.stat";
5450 if (my $fd = IO
::File-
>new($statfile, "r")) {
5451 while (defined (my $line = <$fd>)) {
5452 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5453 $map->{$1} = $2 if $1;
5455 print STDERR
"unable to parse line in statfile - $line\n";
5461 my $confsrc = "$tmpdir/qemu-server.conf";
5463 my $srcfd = new IO
::File
($confsrc, "r") ||
5464 die "unable to open file '$confsrc'\n";
5466 my $outfd = new IO
::File
($tmpfn, "w") ||
5467 die "unable to write config for VM $vmid\n";
5469 my $cookie = { netcount
=> 0 };
5470 while (defined (my $line = <$srcfd>)) {
5471 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5483 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5490 rename $tmpfn, $conffile ||
5491 die "unable to commit configuration file '$conffile'\n";
5493 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5495 eval { rescan
($vmid, 1); };
5500 # Internal snapshots
5502 # NOTE: Snapshot create/delete involves several non-atomic
5503 # action, and can take a long time.
5504 # So we try to avoid locking the file and use 'lock' variable
5505 # inside the config file instead.
5507 my $snapshot_copy_config = sub {
5508 my ($source, $dest) = @_;
5510 foreach my $k (keys %$source) {
5511 next if $k eq 'snapshots';
5512 next if $k eq 'snapstate';
5513 next if $k eq 'snaptime';
5514 next if $k eq 'vmstate';
5515 next if $k eq 'lock';
5516 next if $k eq 'digest';
5517 next if $k eq 'description';
5518 next if $k =~ m/^unused\d+$/;
5520 $dest->{$k} = $source->{$k};
5524 my $snapshot_apply_config = sub {
5525 my ($conf, $snap) = @_;
5527 # copy snapshot list
5529 snapshots
=> $conf->{snapshots
},
5532 # keep description and list of unused disks
5533 foreach my $k (keys %$conf) {
5534 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5535 $newconf->{$k} = $conf->{$k};
5538 &$snapshot_copy_config($snap, $newconf);
5543 sub foreach_writable_storage
{
5544 my ($conf, $func) = @_;
5548 foreach my $ds (keys %$conf) {
5549 next if !valid_drivename
($ds);
5551 my $drive = parse_drive
($ds, $conf->{$ds});
5553 next if drive_is_cdrom
($drive);
5555 my $volid = $drive->{file
};
5557 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5558 $sidhash->{$sid} = $sid if $sid;
5561 foreach my $sid (sort keys %$sidhash) {
5566 my $alloc_vmstate_volid = sub {
5567 my ($storecfg, $vmid, $conf, $snapname) = @_;
5569 # Note: we try to be smart when selecting a $target storage
5573 # search shared storage first
5574 foreach_writable_storage
($conf, sub {
5576 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5577 return if !$scfg->{shared
};
5579 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5583 # now search local storage
5584 foreach_writable_storage
($conf, sub {
5586 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5587 return if $scfg->{shared
};
5589 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5593 $target = 'local' if !$target;
5595 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5596 # we abort live save after $conf->{memory}, so we need at max twice that space
5597 my $size = $conf->{memory
}*2 + $driver_state_size;
5599 my $name = "vm-$vmid-state-$snapname";
5600 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5601 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5602 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5607 my $snapshot_prepare = sub {
5608 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5612 my $updatefn = sub {
5614 my $conf = load_config
($vmid);
5616 die "you can't take a snapshot if it's a template\n"
5617 if is_template
($conf);
5621 $conf->{lock} = 'snapshot';
5623 die "snapshot name '$snapname' already used\n"
5624 if defined($conf->{snapshots
}->{$snapname});
5626 my $storecfg = PVE
::Storage
::config
();
5627 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5629 $snap = $conf->{snapshots
}->{$snapname} = {};
5631 if ($save_vmstate && check_running
($vmid)) {
5632 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5635 &$snapshot_copy_config($conf, $snap);
5637 $snap->{snapstate
} = "prepare";
5638 $snap->{snaptime
} = time();
5639 $snap->{description
} = $comment if $comment;
5641 # always overwrite machine if we save vmstate. This makes sure we
5642 # can restore it later using correct machine type
5643 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5645 update_config_nolock
($vmid, $conf, 1);
5648 lock_config
($vmid, $updatefn);
5653 my $snapshot_commit = sub {
5654 my ($vmid, $snapname) = @_;
5656 my $updatefn = sub {
5658 my $conf = load_config
($vmid);
5660 die "missing snapshot lock\n"
5661 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5663 my $has_machine_config = defined($conf->{machine
});
5665 my $snap = $conf->{snapshots
}->{$snapname};
5667 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5669 die "wrong snapshot state\n"
5670 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5672 delete $snap->{snapstate
};
5673 delete $conf->{lock};
5675 my $newconf = &$snapshot_apply_config($conf, $snap);
5677 delete $newconf->{machine
} if !$has_machine_config;
5679 $newconf->{parent
} = $snapname;
5681 update_config_nolock
($vmid, $newconf, 1);
5684 lock_config
($vmid, $updatefn);
5687 sub snapshot_rollback
{
5688 my ($vmid, $snapname) = @_;
5692 my $storecfg = PVE
::Storage
::config
();
5694 my $conf = load_config
($vmid);
5696 my $get_snapshot_config = sub {
5698 die "you can't rollback if vm is a template\n" if is_template
($conf);
5700 my $res = $conf->{snapshots
}->{$snapname};
5702 die "snapshot '$snapname' does not exist\n" if !defined($res);
5707 my $snap = &$get_snapshot_config();
5709 foreach_drive
($snap, sub {
5710 my ($ds, $drive) = @_;
5712 return if drive_is_cdrom
($drive);
5714 my $volid = $drive->{file
};
5716 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5719 my $updatefn = sub {
5721 $conf = load_config
($vmid);
5723 $snap = &$get_snapshot_config();
5725 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5726 if $snap->{snapstate
};
5730 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5733 die "unable to rollback vm $vmid: vm is running\n"
5734 if check_running
($vmid);
5737 $conf->{lock} = 'rollback';
5739 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5740 delete $conf->{lock};
5746 my $has_machine_config = defined($conf->{machine
});
5748 # copy snapshot config to current config
5749 $conf = &$snapshot_apply_config($conf, $snap);
5750 $conf->{parent
} = $snapname;
5752 # Note: old code did not store 'machine', so we try to be smart
5753 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5754 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5755 # we remove the 'machine' configuration if not explicitly specified
5756 # in the original config.
5757 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5760 update_config_nolock
($vmid, $conf, 1);
5762 if (!$prepare && $snap->{vmstate
}) {
5763 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5764 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5768 lock_config
($vmid, $updatefn);
5770 foreach_drive
($snap, sub {
5771 my ($ds, $drive) = @_;
5773 return if drive_is_cdrom
($drive);
5775 my $volid = $drive->{file
};
5776 my $device = "drive-$ds";
5778 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5782 lock_config
($vmid, $updatefn);
5785 my $savevm_wait = sub {
5789 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5790 if (!$stat->{status
}) {
5791 die "savevm not active\n";
5792 } elsif ($stat->{status
} eq 'active') {
5795 } elsif ($stat->{status
} eq 'completed') {
5798 die "query-savevm returned status '$stat->{status}'\n";
5803 sub do_snapshots_with_qemu
{
5804 my ($storecfg, $volid) = @_;
5806 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5808 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5812 if ($volid =~ m/\.(qcow2|qed)$/){
5819 sub snapshot_create
{
5820 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5822 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5824 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5826 my $config = load_config
($vmid);
5828 my $running = check_running
($vmid);
5830 my $freezefs = $running && $config->{agent
};
5831 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5836 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5837 warn "guest-fsfreeze-freeze problems - $@" if $@;
5841 # create internal snapshots of all drives
5843 my $storecfg = PVE
::Storage
::config
();
5846 if ($snap->{vmstate
}) {
5847 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5848 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5849 &$savevm_wait($vmid);
5851 vm_mon_cmd
($vmid, "savevm-start");
5855 foreach_drive
($snap, sub {
5856 my ($ds, $drive) = @_;
5858 return if drive_is_cdrom
($drive);
5860 my $volid = $drive->{file
};
5861 my $device = "drive-$ds";
5863 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5864 $drivehash->{$ds} = 1;
5870 eval { vm_mon_cmd
($vmid, "savevm-end") };
5874 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5875 warn "guest-fsfreeze-thaw problems - $@" if $@;
5878 # savevm-end is async, we need to wait
5880 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5881 if (!$stat->{bytes
}) {
5884 print "savevm not yet finished\n";
5892 warn "snapshot create failed: starting cleanup\n";
5893 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5898 &$snapshot_commit($vmid, $snapname);
5901 # Note: $drivehash is only set when called from snapshot_create.
5902 sub snapshot_delete
{
5903 my ($vmid, $snapname, $force, $drivehash) = @_;
5910 my $unlink_parent = sub {
5911 my ($confref, $new_parent) = @_;
5913 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5915 $confref->{parent
} = $new_parent;
5917 delete $confref->{parent
};
5922 my $updatefn = sub {
5923 my ($remove_drive) = @_;
5925 my $conf = load_config
($vmid);
5929 die "you can't delete a snapshot if vm is a template\n"
5930 if is_template
($conf);
5933 $snap = $conf->{snapshots
}->{$snapname};
5935 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5937 # remove parent refs
5939 &$unlink_parent($conf, $snap->{parent
});
5940 foreach my $sn (keys %{$conf->{snapshots
}}) {
5941 next if $sn eq $snapname;
5942 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5946 if ($remove_drive) {
5947 if ($remove_drive eq 'vmstate') {
5948 delete $snap->{$remove_drive};
5950 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5951 my $volid = $drive->{file
};
5952 delete $snap->{$remove_drive};
5953 add_unused_volume
($conf, $volid);
5958 $snap->{snapstate
} = 'delete';
5960 delete $conf->{snapshots
}->{$snapname};
5961 delete $conf->{lock} if $drivehash;
5962 foreach my $volid (@$unused) {
5963 add_unused_volume
($conf, $volid);
5967 update_config_nolock
($vmid, $conf, 1);
5970 lock_config
($vmid, $updatefn);
5972 # now remove vmstate file
5974 my $storecfg = PVE
::Storage
::config
();
5976 if ($snap->{vmstate
}) {
5977 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5979 die $err if !$force;
5982 # save changes (remove vmstate from snapshot)
5983 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5986 # now remove all internal snapshots
5987 foreach_drive
($snap, sub {
5988 my ($ds, $drive) = @_;
5990 return if drive_is_cdrom
($drive);
5992 my $volid = $drive->{file
};
5993 my $device = "drive-$ds";
5995 if (!$drivehash || $drivehash->{$ds}) {
5996 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
5998 die $err if !$force;
6003 # save changes (remove drive fron snapshot)
6004 lock_config
($vmid, $updatefn, $ds) if !$force;
6005 push @$unused, $volid;
6008 # now cleanup config
6010 lock_config
($vmid, $updatefn);
6014 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6017 foreach_drive
($conf, sub {
6018 my ($ds, $drive) = @_;
6020 return if drive_is_cdrom
($drive);
6021 my $volid = $drive->{file
};
6022 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6025 return $err ?
0 : 1;
6028 sub template_create
{
6029 my ($vmid, $conf, $disk) = @_;
6031 my $storecfg = PVE
::Storage
::config
();
6033 foreach_drive
($conf, sub {
6034 my ($ds, $drive) = @_;
6036 return if drive_is_cdrom
($drive);
6037 return if $disk && $ds ne $disk;
6039 my $volid = $drive->{file
};
6040 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6042 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6043 $drive->{file
} = $voliddst;
6044 $conf->{$ds} = print_drive
($vmid, $drive);
6045 update_config_nolock
($vmid, $conf, 1);
6052 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6055 sub qemu_img_convert
{
6056 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6058 my $storecfg = PVE
::Storage
::config
();
6059 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6060 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6062 if ($src_storeid && $dst_storeid) {
6063 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6064 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6066 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6067 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6069 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6070 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6073 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6074 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6075 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6079 if($line =~ m/\((\S+)\/100\
%\)/){
6081 my $transferred = int($size * $percent / 100);
6082 my $remaining = $size - $transferred;
6084 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6089 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6091 die "copy failed: $err" if $err;
6095 sub qemu_img_format
{
6096 my ($scfg, $volname) = @_;
6098 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
6100 } elsif ($scfg->{type
} eq 'iscsi') {
6101 return "host_device";
6107 sub qemu_drive_mirror
{
6108 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6110 my $storecfg = PVE
::Storage
::config
();
6111 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6113 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6116 if ($dst_volname =~ m/\.(raw|qcow2)$/){
6120 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6122 #drive-mirror is doing lseek on source image before starting, and this can take a lot of time for big nfs volume
6123 #during this time, qmp socket is hanging
6124 #http://lists.nongnu.org/archive/html/qemu-devel/2015-05/msg01838.html
6125 #so we need to setup a big timeout
6126 my $opts = { timeout
=> 14400, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6127 $opts->{format
} = $format if $format;
6129 print "drive mirror is starting : this step can take some minutes/hours, depend of disk size and storage speed\n";
6131 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6134 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6135 my $stat = @$stats[0];
6136 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6137 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6139 my $busy = $stat->{busy
};
6140 my $ready = $stat->{ready
};
6142 if (my $total = $stat->{len
}) {
6143 my $transferred = $stat->{offset
} || 0;
6144 my $remaining = $total - $transferred;
6145 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6147 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6151 if ($stat->{ready
} eq 'true') {
6153 last if $vmiddst != $vmid;
6155 # try to switch the disk if source and destination are on the same guest
6156 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6158 die $@ if $@ !~ m/cannot be completed/;
6167 my $cancel_job = sub {
6168 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6170 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6171 my $stat = @$stats[0];
6178 eval { &$cancel_job(); };
6179 die "mirroring error: $err";
6182 if ($vmiddst != $vmid) {
6183 # if we clone a disk for a new target vm, we don't switch the disk
6184 &$cancel_job(); # so we call block-job-cancel
6189 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6190 $newvmid, $storage, $format, $full, $newvollist) = @_;
6195 print "create linked clone of drive $drivename ($drive->{file})\n";
6196 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6197 push @$newvollist, $newvolid;
6199 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6200 $storeid = $storage if $storage;
6202 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6204 $format = $drive->{format
} || $defFormat;
6207 # test if requested format is supported - else use default
6208 my $supported = grep { $_ eq $format } @$validFormats;
6209 $format = $defFormat if !$supported;
6211 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6213 print "create full clone of drive $drivename ($drive->{file})\n";
6214 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6215 push @$newvollist, $newvolid;
6217 if (!$running || $snapname) {
6218 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6220 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6224 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6227 $disk->{format
} = undef;
6228 $disk->{file
} = $newvolid;
6229 $disk->{size
} = $size;
6234 # this only works if VM is running
6235 sub get_current_qemu_machine
{
6238 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6239 my $res = vm_qmp_command
($vmid, $cmd);
6241 my ($current, $default);
6242 foreach my $e (@$res) {
6243 $default = $e->{name
} if $e->{'is-default'};
6244 $current = $e->{name
} if $e->{'is-current'};
6247 # fallback to the default machine if current is not supported by qemu
6248 return $current || $default || 'pc';
6251 sub qemu_machine_feature_enabled
{
6252 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6257 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6259 $current_major = $3;
6260 $current_minor = $4;
6262 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6264 $current_major = $1;
6265 $current_minor = $2;
6268 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6277 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6278 my (undef, $id, $function) = @_;
6279 my $res = { id
=> $id, function
=> $function};
6280 push @{$devices->{$id}}, $res;
6286 sub vm_iothreads_list
{
6289 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6292 foreach my $iothread (@$res) {
6293 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6300 my ($conf, $drive) = @_;
6304 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6306 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6312 my $controller = int($drive->{index} / $maxdev);
6313 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6315 return ($maxdev, $controller, $controller_prefix);