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 $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
36 # Note about locking: we use flock on the config file protect
37 # against concurent actions.
38 # Aditionaly, we have a 'lock' setting in the config file. This
39 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
40 # allowed when such lock is set. But you can ignore this kind of
41 # lock with the --skiplock flag.
43 cfs_register_file
('/qemu-server/',
47 PVE
::JSONSchema
::register_standard_option
('skiplock', {
48 description
=> "Ignore locks - only root is allowed to use this option.",
53 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
54 description
=> "Some command save/restore state from this location.",
60 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
61 description
=> "The name of the snapshot.",
62 type
=> 'string', format
=> 'pve-configid',
66 #no warnings 'redefine';
68 unless(defined(&_VZSYSCALLS_H_
)) {
69 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
70 require 'sys/syscall.ph';
71 if(defined(&__x86_64__
)) {
72 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
73 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
74 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
75 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
76 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
77 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
78 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
79 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
81 elsif(defined( &__i386__
) ) {
82 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
83 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
84 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
85 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
86 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
87 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
88 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
89 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
91 die("no fairsched syscall for this arch");
93 require 'asm/ioctl.ph';
94 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
98 my ($parent, $weight, $desired) = @_;
100 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
103 sub fairsched_rmnod
{
106 return syscall(&__NR_fairsched_rmnod
, int($id));
110 my ($pid, $newid) = @_;
112 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
115 sub fairsched_vcpus
{
116 my ($id, $vcpus) = @_;
118 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
122 my ($id, $op, $rate) = @_;
124 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
127 use constant FAIRSCHED_SET_RATE
=> 0;
128 use constant FAIRSCHED_DROP_RATE
=> 1;
129 use constant FAIRSCHED_GET_RATE
=> 2;
131 sub fairsched_cpulimit
{
132 my ($id, $limit) = @_;
134 my $cpulim1024 = int($limit * 1024 / 100);
135 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
137 return fairsched_rate
($id, $op, $cpulim1024);
140 my $nodename = PVE
::INotify
::nodename
();
142 mkdir "/etc/pve/nodes/$nodename";
143 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
146 my $var_run_tmpdir = "/var/run/qemu-server";
147 mkdir $var_run_tmpdir;
149 my $lock_dir = "/var/lock/qemu-server";
152 my $pcisysfs = "/sys/bus/pci";
158 description
=> "Enable iothread dataplane.",
164 description
=> "Specifies whether a VM will be started during system bootup.",
170 description
=> "Automatic restart after crash (currently ignored).",
176 description
=> "Allow hotplug for disk and network device",
182 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
188 description
=> "Lock/unlock the VM.",
189 enum
=> [qw(migrate backup snapshot rollback)],
194 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.",
201 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.",
209 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
216 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
222 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",
230 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
231 enum
=> PVE
::Tools
::kvmkeymaplist
(),
236 type
=> 'string', format
=> 'dns-name',
237 description
=> "Set a name for the VM. Only used on the configuration web interface.",
242 description
=> "scsi controller model",
243 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)],
249 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
254 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
255 description
=> <<EODESC,
256 Used to enable special optimization/features for specific
259 other => unspecified OS
260 wxp => Microsoft Windows XP
261 w2k => Microsoft Windows 2000
262 w2k3 => Microsoft Windows 2003
263 w2k8 => Microsoft Windows 2008
264 wvista => Microsoft Windows Vista
265 win7 => Microsoft Windows 7
266 win8 => Microsoft Windows 8/2012
267 l24 => Linux 2.4 Kernel
268 l26 => Linux 2.6/3.X Kernel
269 solaris => solaris/opensolaris/openindiania kernel
271 other|l24|l26|solaris ... no special behaviour
272 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
278 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
279 pattern
=> '[acdn]{1,4}',
284 type
=> 'string', format
=> 'pve-qm-bootdisk',
285 description
=> "Enable booting from specified disk.",
286 pattern
=> '(ide|sata|scsi|virtio)\d+',
291 description
=> "The number of CPUs. Please use option -sockets instead.",
298 description
=> "The number of CPU sockets.",
305 description
=> "The number of cores per socket.",
312 description
=> "Enable/disable Numa.",
318 description
=> "Maximum cpus for hotplug.",
325 description
=> "Enable/disable ACPI.",
331 description
=> "Enable/disable Qemu GuestAgent.",
337 description
=> "Enable/disable KVM hardware virtualization.",
343 description
=> "Enable/disable time drift fix.",
349 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
354 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
359 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.",
360 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
364 type
=> 'string', format
=> 'pve-qm-watchdog',
365 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
366 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)",
371 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
372 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'.",
373 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
378 type
=> 'string', format
=> 'pve-qm-startup',
379 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
380 description
=> "Startup and shutdown behavior. Order is a non-negative number defining the general startup order. Shutdown in done with reverse ordering. Additionally you can set the 'up' or 'down' delay in seconds, which specifies a delay to wait before the next VM is started or stopped.",
385 description
=> "Enable/disable Template.",
391 description
=> <<EODESCR,
392 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
394 args: -no-reboot -no-hpet
401 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).",
406 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
410 migrate_downtime
=> {
413 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
419 type
=> 'string', format
=> 'pve-qm-drive',
420 typetext
=> 'volume',
421 description
=> "This is an alias for option -ide2",
425 description
=> "Emulated CPU type.",
427 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
430 parent
=> get_standard_option
('pve-snapshot-name', {
432 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
436 description
=> "Timestamp for snapshots.",
442 type
=> 'string', format
=> 'pve-volume-id',
443 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
446 description
=> "Specific the Qemu machine type.",
448 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
453 description
=> "Specify SMBIOS type 1 fields.",
454 type
=> 'string', format
=> 'pve-qm-smbios1',
455 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
461 # what about other qemu settings ?
463 #machine => 'string',
476 ##soundhw => 'string',
478 while (my ($k, $v) = each %$confdesc) {
479 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
482 my $MAX_IDE_DISKS = 4;
483 my $MAX_SCSI_DISKS = 14;
484 my $MAX_VIRTIO_DISKS = 16;
485 my $MAX_SATA_DISKS = 6;
486 my $MAX_USB_DEVICES = 5;
488 my $MAX_UNUSED_DISKS = 8;
489 my $MAX_HOSTPCI_DEVICES = 4;
490 my $MAX_SERIAL_PORTS = 4;
491 my $MAX_PARALLEL_PORTS = 3;
496 type
=> 'string', format
=> 'pve-qm-numanode',
497 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>][,policy=<preferred|bind|interleave>]]",
498 description
=> "numa topology",
500 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
502 for (my $i = 0; $i < $MAX_NUMA; $i++) {
503 $confdesc->{"numa$i"} = $numadesc;
506 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
507 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3'];
508 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
512 type
=> 'string', format
=> 'pve-qm-net',
513 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>][,tag=<vlanid>][,firewall=0|1]",
514 description
=> <<EODESCR,
515 Specify network devices.
517 MODEL is one of: $nic_model_list_txt
519 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
520 automatically generated if not specified.
522 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
524 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'.
526 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
532 The DHCP server assign addresses to the guest starting from 10.0.2.15.
536 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
538 for (my $i = 0; $i < $MAX_NETS; $i++) {
539 $confdesc->{"net$i"} = $netdesc;
546 type
=> 'string', format
=> 'pve-qm-drive',
547 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]',
548 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
550 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
554 type
=> 'string', format
=> 'pve-qm-drive',
555 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]',
556 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
558 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
562 type
=> 'string', format
=> 'pve-qm-drive',
563 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]',
564 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
566 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
570 type
=> 'string', format
=> 'pve-qm-drive',
571 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]',
572 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
574 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
578 type
=> 'string', format
=> 'pve-qm-usb-device',
579 typetext
=> 'host=HOSTUSBDEVICE|spice',
580 description
=> <<EODESCR,
581 Configure an USB device (n is 0 to 4). This can be used to
582 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
584 'bus-port(.port)*' (decimal numbers) or
585 'vendor_id:product_id' (hexadeciaml numbers)
587 You can use the 'lsusb -t' command to list existing usb devices.
589 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
591 The value 'spice' can be used to add a usb redirection devices for spice.
595 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
599 type
=> 'string', format
=> 'pve-qm-hostpci',
600 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
601 description
=> <<EODESCR,
602 Map host pci devices. HOSTPCIDEVICE syntax is:
604 'bus:dev.func' (hexadecimal numbers)
606 You can us the 'lspci' command to list existing pci devices.
608 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
610 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
612 Experimental: user reported problems with this option.
615 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
620 pattern
=> '(/dev/.+|socket)',
621 description
=> <<EODESCR,
622 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).
624 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
626 Experimental: user reported problems with this option.
633 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
634 description
=> <<EODESCR,
635 Map host parallel devices (n is 0 to 2).
637 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
639 Experimental: user reported problems with this option.
643 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
644 $confdesc->{"parallel$i"} = $paralleldesc;
647 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
648 $confdesc->{"serial$i"} = $serialdesc;
651 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
652 $confdesc->{"hostpci$i"} = $hostpcidesc;
655 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
656 $drivename_hash->{"ide$i"} = 1;
657 $confdesc->{"ide$i"} = $idedesc;
660 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
661 $drivename_hash->{"sata$i"} = 1;
662 $confdesc->{"sata$i"} = $satadesc;
665 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
666 $drivename_hash->{"scsi$i"} = 1;
667 $confdesc->{"scsi$i"} = $scsidesc ;
670 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
671 $drivename_hash->{"virtio$i"} = 1;
672 $confdesc->{"virtio$i"} = $virtiodesc;
675 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
676 $confdesc->{"usb$i"} = $usbdesc;
681 type
=> 'string', format
=> 'pve-volume-id',
682 description
=> "Reference to unused volumes.",
685 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
686 $confdesc->{"unused$i"} = $unuseddesc;
689 my $kvm_api_version = 0;
693 return $kvm_api_version if $kvm_api_version;
695 my $fh = IO
::File-
>new("</dev/kvm") ||
698 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
699 $kvm_api_version = $v;
704 return $kvm_api_version;
707 my $kvm_user_version;
709 sub kvm_user_version
{
711 return $kvm_user_version if $kvm_user_version;
713 $kvm_user_version = 'unknown';
715 my $tmp = `kvm -help 2>/dev/null`;
717 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
718 $kvm_user_version = $2;
721 return $kvm_user_version;
725 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
728 # order is important - used to autoselect boot disk
729 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
730 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
731 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
732 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
735 sub valid_drivename
{
738 return defined($drivename_hash->{$dev});
743 return defined($confdesc->{$key});
747 return $nic_model_list;
750 sub os_list_description
{
755 w2k
=> 'Windows 2000',
756 w2k3
=>, 'Windows 2003',
757 w2k8
=> 'Windows 2008',
758 wvista
=> 'Windows Vista',
760 win8
=> 'Windows 8/2012',
770 return $cdrom_path if $cdrom_path;
772 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
773 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
774 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
778 my ($storecfg, $vmid, $cdrom) = @_;
780 if ($cdrom eq 'cdrom') {
781 return get_cdrom_path
();
782 } elsif ($cdrom eq 'none') {
784 } elsif ($cdrom =~ m
|^/|) {
787 return PVE
::Storage
::path
($storecfg, $cdrom);
791 # try to convert old style file names to volume IDs
792 sub filename_to_volume_id
{
793 my ($vmid, $file, $media) = @_;
795 if (!($file eq 'none' || $file eq 'cdrom' ||
796 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
798 return undef if $file =~ m
|/|;
800 if ($media && $media eq 'cdrom') {
801 $file = "local:iso/$file";
803 $file = "local:$vmid/$file";
810 sub verify_media_type
{
811 my ($opt, $vtype, $media) = @_;
816 if ($media eq 'disk') {
818 } elsif ($media eq 'cdrom') {
821 die "internal error";
824 return if ($vtype eq $etype);
826 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
829 sub cleanup_drive_path
{
830 my ($opt, $storecfg, $drive) = @_;
832 # try to convert filesystem paths to volume IDs
834 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
835 ($drive->{file
} !~ m
|^/dev/.+|) &&
836 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
837 ($drive->{file
} !~ m/^\d+$/)) {
838 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
839 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
840 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
841 verify_media_type
($opt, $vtype, $drive->{media
});
842 $drive->{file
} = $volid;
845 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
848 sub create_conf_nolock
{
849 my ($vmid, $settings) = @_;
851 my $filename = config_file
($vmid);
853 die "configuration file '$filename' already exists\n" if -f
$filename;
855 my $defaults = load_defaults
();
857 $settings->{name
} = "vm$vmid" if !$settings->{name
};
858 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
861 foreach my $opt (keys %$settings) {
862 next if !$confdesc->{$opt};
864 my $value = $settings->{$opt};
867 $data .= "$opt: $value\n";
870 PVE
::Tools
::file_set_contents
($filename, $data);
873 my $parse_size = sub {
876 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
877 my ($size, $unit) = ($1, $3);
880 $size = $size * 1024;
881 } elsif ($unit eq 'M') {
882 $size = $size * 1024 * 1024;
883 } elsif ($unit eq 'G') {
884 $size = $size * 1024 * 1024 * 1024;
890 my $format_size = sub {
895 my $kb = int($size/1024);
896 return $size if $kb*1024 != $size;
898 my $mb = int($kb/1024);
899 return "${kb}K" if $mb*1024 != $kb;
901 my $gb = int($mb/1024);
902 return "${mb}M" if $gb*1024 != $mb;
907 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
908 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
909 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
910 # [,aio=native|threads][,discard=ignore|on]
913 my ($key, $data) = @_;
917 # $key may be undefined - used to verify JSON parameters
918 if (!defined($key)) {
919 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
921 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
922 $res->{interface
} = $1;
928 foreach my $p (split (/,/, $data)) {
929 next if $p =~ m/^\s*$/;
931 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)=(.+)$/) {
932 my ($k, $v) = ($1, $2);
934 $k = 'file' if $k eq 'volume';
936 return undef if defined $res->{$k};
938 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
939 return undef if !$v || $v !~ m/^\d+/;
941 $v = sprintf("%.3f", $v / (1024*1024));
945 if (!$res->{file
} && $p !~ m/=/) {
953 return undef if !$res->{file
};
955 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
959 return undef if $res->{cache
} &&
960 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
961 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
962 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
963 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
964 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
965 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
966 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
967 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
968 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
969 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
970 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
971 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
972 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
974 return undef if $res->{mbps_rd
} && $res->{mbps
};
975 return undef if $res->{mbps_wr
} && $res->{mbps
};
977 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
978 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
979 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
980 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
981 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
982 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
984 return undef if $res->{iops_rd
} && $res->{iops
};
985 return undef if $res->{iops_wr
} && $res->{iops
};
988 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
989 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
990 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
991 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
992 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
993 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
997 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
1000 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1001 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1002 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1003 return undef if $res->{interface
} eq 'virtio';
1006 # rerror does not work with scsi drives
1007 if ($res->{rerror
}) {
1008 return undef if $res->{interface
} eq 'scsi';
1014 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);
1017 my ($vmid, $drive) = @_;
1020 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
1021 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1024 if ($drive->{size
}) {
1025 $opts .= ",size=" . &$format_size($drive->{size
});
1028 return "$drive->{file}$opts";
1032 my($fh, $noerr) = @_;
1035 my $SG_GET_VERSION_NUM = 0x2282;
1037 my $versionbuf = "\x00" x
8;
1038 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1040 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1043 my $version = unpack("I", $versionbuf);
1044 if ($version < 30000) {
1045 die "scsi generic interface too old\n" if !$noerr;
1049 my $buf = "\x00" x
36;
1050 my $sensebuf = "\x00" x
8;
1051 my $cmd = pack("C x3 C x1", 0x12, 36);
1053 # see /usr/include/scsi/sg.h
1054 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";
1056 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1057 length($sensebuf), 0, length($buf), $buf,
1058 $cmd, $sensebuf, 6000);
1060 $ret = ioctl($fh, $SG_IO, $packet);
1062 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1066 my @res = unpack($sg_io_hdr_t, $packet);
1067 if ($res[17] || $res[18]) {
1068 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1073 (my $byte0, my $byte1, $res->{vendor
},
1074 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1076 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1077 $res->{type
} = $byte0 & 31;
1085 my $fh = IO
::File-
>new("+<$path") || return undef;
1086 my $res = scsi_inquiry
($fh, 1);
1092 sub machine_type_is_q35
{
1095 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1098 sub print_tabletdevice_full
{
1101 my $q35 = machine_type_is_q35
($conf);
1103 # we use uhci for old VMs because tablet driver was buggy in older qemu
1104 my $usbbus = $q35 ?
"ehci" : "uhci";
1106 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1109 sub print_drivedevice_full
{
1110 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1115 if ($drive->{interface
} eq 'virtio') {
1116 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1117 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1118 $device .= ",iothread=iothread0" if $conf->{iothread
};
1119 } elsif ($drive->{interface
} eq 'scsi') {
1120 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1121 my $controller = int($drive->{index} / $maxdev);
1122 my $unit = $drive->{index} % $maxdev;
1123 my $devicetype = 'hd';
1125 if (drive_is_cdrom
($drive)) {
1128 if ($drive->{file
} =~ m
|^/|) {
1129 $path = $drive->{file
};
1131 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1134 if($path =~ m/^iscsi\:\/\
//){
1135 $devicetype = 'generic';
1137 if (my $info = path_is_scsi
($path)) {
1138 if ($info->{type
} == 0) {
1139 $devicetype = 'block';
1140 } elsif ($info->{type
} == 1) { # tape
1141 $devicetype = 'generic';
1147 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1148 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1150 $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1153 } elsif ($drive->{interface
} eq 'ide'){
1155 my $controller = int($drive->{index} / $maxdev);
1156 my $unit = $drive->{index} % $maxdev;
1157 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1159 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1160 } elsif ($drive->{interface
} eq 'sata'){
1161 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1162 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1163 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1164 } elsif ($drive->{interface
} eq 'usb') {
1166 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1168 die "unsupported interface type";
1171 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1176 sub get_initiator_name
{
1179 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1180 while (defined(my $line = <$fh>)) {
1181 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1190 sub print_drive_full
{
1191 my ($storecfg, $vmid, $drive) = @_;
1194 foreach my $o (@qemu_drive_options) {
1195 next if $o eq 'bootindex';
1196 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1199 foreach my $o (qw(bps bps_rd bps_wr)) {
1200 my $v = $drive->{"m$o"};
1201 $opts .= ",$o=" . int($v*1024*1024) if $v;
1204 # use linux-aio by default (qemu default is threads)
1205 $opts .= ",aio=native" if !$drive->{aio
};
1208 my $volid = $drive->{file
};
1209 if (drive_is_cdrom
($drive)) {
1210 $path = get_iso_path
($storecfg, $vmid, $volid);
1212 if ($volid =~ m
|^/|) {
1215 $path = PVE
::Storage
::path
($storecfg, $volid);
1219 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1221 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1222 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1224 my $pathinfo = $path ?
"file=$path," : '';
1226 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1229 sub print_netdevice_full
{
1230 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1232 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1234 my $device = $net->{model
};
1235 if ($net->{model
} eq 'virtio') {
1236 $device = 'virtio-net-pci';
1239 # qemu > 0.15 always try to boot from network - we disable that by
1240 # not loading the pxe rom file
1241 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1242 my $pciaddr = print_pci_addr
("$netid", $bridges);
1243 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1244 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1245 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1246 my $vectors = $net->{queues
} * 2 + 2;
1247 $tmpstr .= ",vectors=$vectors,mq=on";
1249 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1253 sub print_netdev_full
{
1254 my ($vmid, $conf, $net, $netid) = @_;
1257 if ($netid =~ m/^net(\d+)$/) {
1261 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1263 my $ifname = "tap${vmid}i$i";
1265 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1266 die "interface name '$ifname' is too long (max 15 character)\n"
1267 if length($ifname) >= 16;
1269 my $vhostparam = '';
1270 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1272 my $vmname = $conf->{name
} || "vm$vmid";
1276 if ($net->{bridge
}) {
1277 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1279 $netdev = "type=user,id=$netid,hostname=$vmname";
1282 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1287 sub drive_is_cdrom
{
1290 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1299 foreach my $kvp (split(/,/, $data)) {
1301 if ($kvp =~ m/^memory=(\S+)$/) {
1302 $res->{memory
} = $1;
1303 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1304 $res->{policy
} = $1;
1305 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1306 $res->{cpus
}->{start
} = $1;
1307 $res->{cpus
}->{end
} = $3;
1308 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1309 $res->{hostnodes
}->{start
} = $1;
1310 $res->{hostnodes
}->{end
} = $3;
1322 return undef if !$value;
1325 my @list = split(/,/, $value);
1329 foreach my $kv (@list) {
1331 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1334 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1337 my $pcidevices = lspci
($2);
1338 $res->{pciid
} = $pcidevices->{$2};
1340 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1341 $res->{driver
} = $1;
1342 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1343 $res->{rombar
} = $1;
1344 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1345 $res->{'x-vga'} = $1;
1346 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1347 $res->{pcie
} = 1 if $1 == 1;
1349 warn "unknown hostpci setting '$kv'\n";
1353 return undef if !$found;
1358 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1364 foreach my $kvp (split(/,/, $data)) {
1366 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1368 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1369 $res->{model
} = $model;
1370 $res->{macaddr
} = $mac;
1371 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1372 $res->{bridge
} = $1;
1373 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1374 $res->{queues
} = $1;
1375 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1377 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1379 } elsif ($kvp =~ m/^firewall=(\d+)$/) {
1380 $res->{firewall
} = $1;
1387 return undef if !$res->{model
};
1395 my $res = "$net->{model}";
1396 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1397 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1398 $res .= ",rate=$net->{rate}" if $net->{rate
};
1399 $res .= ",tag=$net->{tag}" if $net->{tag
};
1400 $res .= ",firewall=$net->{firewall}" if $net->{firewall
};
1405 sub add_random_macs
{
1406 my ($settings) = @_;
1408 foreach my $opt (keys %$settings) {
1409 next if $opt !~ m/^net(\d+)$/;
1410 my $net = parse_net
($settings->{$opt});
1412 $settings->{$opt} = print_net
($net);
1416 sub add_unused_volume
{
1417 my ($config, $volid) = @_;
1420 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1421 my $test = "unused$ind";
1422 if (my $vid = $config->{$test}) {
1423 return if $vid eq $volid; # do not add duplicates
1429 die "To many unused volume - please delete them first.\n" if !$key;
1431 $config->{$key} = $volid;
1436 my $valid_smbios1_options = {
1437 manufacturer
=> '\S+',
1441 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1446 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1452 foreach my $kvp (split(/,/, $data)) {
1453 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1454 my ($k, $v) = split(/=/, $kvp);
1455 return undef if !defined($k) || !defined($v);
1456 return undef if !$valid_smbios1_options->{$k};
1457 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1468 foreach my $k (keys %$smbios1) {
1469 next if !defined($smbios1->{$k});
1470 next if !$valid_smbios1_options->{$k};
1471 $data .= ',' if $data;
1472 $data .= "$k=$smbios1->{$k}";
1477 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1478 sub verify_smbios1
{
1479 my ($value, $noerr) = @_;
1481 return $value if parse_smbios1
($value);
1483 return undef if $noerr;
1485 die "unable to parse smbios (type 1) options\n";
1488 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1489 sub verify_bootdisk
{
1490 my ($value, $noerr) = @_;
1492 return $value if valid_drivename
($value);
1494 return undef if $noerr;
1496 die "invalid boot disk '$value'\n";
1499 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1501 my ($value, $noerr) = @_;
1503 return $value if parse_numa
($value);
1505 return undef if $noerr;
1507 die "unable to parse numa options\n";
1510 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1512 my ($value, $noerr) = @_;
1514 return $value if parse_net
($value);
1516 return undef if $noerr;
1518 die "unable to parse network options\n";
1521 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1523 my ($value, $noerr) = @_;
1525 return $value if parse_drive
(undef, $value);
1527 return undef if $noerr;
1529 die "unable to parse drive options\n";
1532 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1533 sub verify_hostpci
{
1534 my ($value, $noerr) = @_;
1536 return $value if parse_hostpci
($value);
1538 return undef if $noerr;
1540 die "unable to parse pci id\n";
1543 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1544 sub verify_watchdog
{
1545 my ($value, $noerr) = @_;
1547 return $value if parse_watchdog
($value);
1549 return undef if $noerr;
1551 die "unable to parse watchdog options\n";
1554 sub parse_watchdog
{
1557 return undef if !$value;
1561 foreach my $p (split(/,/, $value)) {
1562 next if $p =~ m/^\s*$/;
1564 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1566 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1567 $res->{action
} = $2;
1576 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1577 sub verify_startup
{
1578 my ($value, $noerr) = @_;
1580 return $value if parse_startup
($value);
1582 return undef if $noerr;
1584 die "unable to parse startup options\n";
1590 return undef if !$value;
1594 foreach my $p (split(/,/, $value)) {
1595 next if $p =~ m/^\s*$/;
1597 if ($p =~ m/^(order=)?(\d+)$/) {
1599 } elsif ($p =~ m/^up=(\d+)$/) {
1601 } elsif ($p =~ m/^down=(\d+)$/) {
1611 sub parse_usb_device
{
1614 return undef if !$value;
1616 my @dl = split(/,/, $value);
1620 foreach my $v (@dl) {
1621 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1623 $res->{vendorid
} = $2;
1624 $res->{productid
} = $4;
1625 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1627 $res->{hostbus
} = $1;
1628 $res->{hostport
} = $2;
1629 } elsif ($v =~ m/^spice$/) {
1636 return undef if !$found;
1641 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1642 sub verify_usb_device
{
1643 my ($value, $noerr) = @_;
1645 return $value if parse_usb_device
($value);
1647 return undef if $noerr;
1649 die "unable to parse usb device\n";
1652 # add JSON properties for create and set function
1653 sub json_config_properties
{
1656 foreach my $opt (keys %$confdesc) {
1657 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1658 $prop->{$opt} = $confdesc->{$opt};
1665 my ($key, $value) = @_;
1667 die "unknown setting '$key'\n" if !$confdesc->{$key};
1669 my $type = $confdesc->{$key}->{type
};
1671 if (!defined($value)) {
1672 die "got undefined value\n";
1675 if ($value =~ m/[\n\r]/) {
1676 die "property contains a line feed\n";
1679 if ($type eq 'boolean') {
1680 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1681 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1682 die "type check ('boolean') failed - got '$value'\n";
1683 } elsif ($type eq 'integer') {
1684 return int($1) if $value =~ m/^(\d+)$/;
1685 die "type check ('integer') failed - got '$value'\n";
1686 } elsif ($type eq 'number') {
1687 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1688 die "type check ('number') failed - got '$value'\n";
1689 } elsif ($type eq 'string') {
1690 if (my $fmt = $confdesc->{$key}->{format
}) {
1691 if ($fmt eq 'pve-qm-drive') {
1692 # special case - we need to pass $key to parse_drive()
1693 my $drive = parse_drive
($key, $value);
1694 return $value if $drive;
1695 die "unable to parse drive options\n";
1697 PVE
::JSONSchema
::check_format
($fmt, $value);
1700 $value =~ s/^\"(.*)\"$/$1/;
1703 die "internal error"
1707 sub lock_config_full
{
1708 my ($vmid, $timeout, $code, @param) = @_;
1710 my $filename = config_file_lock
($vmid);
1712 my $res = lock_file
($filename, $timeout, $code, @param);
1719 sub lock_config_mode
{
1720 my ($vmid, $timeout, $shared, $code, @param) = @_;
1722 my $filename = config_file_lock
($vmid);
1724 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1732 my ($vmid, $code, @param) = @_;
1734 return lock_config_full
($vmid, 10, $code, @param);
1737 sub cfs_config_path
{
1738 my ($vmid, $node) = @_;
1740 $node = $nodename if !$node;
1741 return "nodes/$node/qemu-server/$vmid.conf";
1744 sub check_iommu_support
{
1745 #fixme : need to check IOMMU support
1746 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1754 my ($vmid, $node) = @_;
1756 my $cfspath = cfs_config_path
($vmid, $node);
1757 return "/etc/pve/$cfspath";
1760 sub config_file_lock
{
1763 return "$lock_dir/lock-$vmid.conf";
1769 my $conf = config_file
($vmid);
1770 utime undef, undef, $conf;
1774 my ($storecfg, $vmid, $keep_empty_config) = @_;
1776 my $conffile = config_file
($vmid);
1778 my $conf = load_config
($vmid);
1782 # only remove disks owned by this VM
1783 foreach_drive
($conf, sub {
1784 my ($ds, $drive) = @_;
1786 return if drive_is_cdrom
($drive);
1788 my $volid = $drive->{file
};
1790 return if !$volid || $volid =~ m
|^/|;
1792 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1793 return if !$path || !$owner || ($owner != $vmid);
1795 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1798 if ($keep_empty_config) {
1799 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1804 # also remove unused disk
1806 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1809 PVE
::Storage
::foreach_volid
($dl, sub {
1810 my ($volid, $sid, $volname, $d) = @_;
1811 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1821 my ($vmid, $node) = @_;
1823 my $cfspath = cfs_config_path
($vmid, $node);
1825 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1827 die "no such VM ('$vmid')\n" if !defined($conf);
1832 sub parse_vm_config
{
1833 my ($filename, $raw) = @_;
1835 return undef if !defined($raw);
1838 digest
=> Digest
::SHA
::sha1_hex
($raw),
1843 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1844 || die "got strange filename '$filename'";
1851 my @lines = split(/\n/, $raw);
1852 foreach my $line (@lines) {
1853 next if $line =~ m/^\s*$/;
1855 if ($line =~ m/^\[PENDING\]\s*$/i) {
1856 $conf->{description
} = $descr if $descr;
1858 $conf = $res->{pending
} = {};
1861 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1863 $conf->{description
} = $descr if $descr;
1865 $conf = $res->{snapshots
}->{$snapname} = {};
1869 if ($line =~ m/^\#(.*)\s*$/) {
1870 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1874 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1875 $descr .= PVE
::Tools
::decode_text
($2);
1876 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1877 $conf->{snapstate
} = $1;
1878 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1881 $conf->{$key} = $value;
1882 } elsif ($line =~ m/^(delete):\s*(.*\S)\s*$/) {
1885 foreach my $opt (split(/,/, $value)) {
1886 $conf->{del
}->{$opt} = 1;
1888 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1891 eval { $value = check_type
($key, $value); };
1893 warn "vm $vmid - unable to parse value of '$key' - $@";
1895 my $fmt = $confdesc->{$key}->{format
};
1896 if ($fmt && $fmt eq 'pve-qm-drive') {
1897 my $v = parse_drive
($key, $value);
1898 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1899 $v->{file
} = $volid;
1900 $value = print_drive
($vmid, $v);
1902 warn "vm $vmid - unable to parse value of '$key'\n";
1907 if ($key eq 'cdrom') {
1908 $conf->{ide2
} = $value;
1910 $conf->{$key} = $value;
1916 $conf->{description
} = $descr if $descr;
1918 delete $res->{snapstate
}; # just to be sure
1923 sub write_vm_config
{
1924 my ($filename, $conf) = @_;
1926 delete $conf->{snapstate
}; # just to be sure
1928 if ($conf->{cdrom
}) {
1929 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1930 $conf->{ide2
} = $conf->{cdrom
};
1931 delete $conf->{cdrom
};
1934 # we do not use 'smp' any longer
1935 if ($conf->{sockets
}) {
1936 delete $conf->{smp
};
1937 } elsif ($conf->{smp
}) {
1938 $conf->{sockets
} = $conf->{smp
};
1939 delete $conf->{cores
};
1940 delete $conf->{smp
};
1943 if ($conf->{maxcpus
} && $conf->{sockets
}) {
1944 delete $conf->{sockets
};
1947 my $used_volids = {};
1949 my $cleanup_config = sub {
1950 my ($cref, $snapname) = @_;
1952 foreach my $key (keys %$cref) {
1953 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1954 $key eq 'snapstate';
1955 my $value = $cref->{$key};
1956 eval { $value = check_type
($key, $value); };
1957 die "unable to parse value of '$key' - $@" if $@;
1959 $cref->{$key} = $value;
1961 if (!$snapname && valid_drivename
($key)) {
1962 my $drive = parse_drive
($key, $value);
1963 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1968 &$cleanup_config($conf);
1969 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1970 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1973 # remove 'unusedX' settings if we re-add a volume
1974 foreach my $key (keys %$conf) {
1975 my $value = $conf->{$key};
1976 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1977 delete $conf->{$key};
1981 my $generate_raw_config = sub {
1986 # add description as comment to top of file
1987 my $descr = $conf->{description
} || '';
1988 foreach my $cl (split(/\n/, $descr)) {
1989 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1992 foreach my $key (sort keys %$conf) {
1993 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1994 $raw .= "$key: $conf->{$key}\n";
1999 my $raw = &$generate_raw_config($conf);
2000 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2001 $raw .= "\n[$snapname]\n";
2002 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2008 sub update_config_nolock
{
2009 my ($vmid, $conf, $skiplock) = @_;
2011 check_lock
($conf) if !$skiplock;
2013 my $cfspath = cfs_config_path
($vmid);
2015 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2019 my ($vmid, $conf, $skiplock) = @_;
2021 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2028 # we use static defaults from our JSON schema configuration
2029 foreach my $key (keys %$confdesc) {
2030 if (defined(my $default = $confdesc->{$key}->{default})) {
2031 $res->{$key} = $default;
2035 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2036 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2042 my $vmlist = PVE
::Cluster
::get_vmlist
();
2044 return $res if !$vmlist || !$vmlist->{ids
};
2045 my $ids = $vmlist->{ids
};
2047 foreach my $vmid (keys %$ids) {
2048 my $d = $ids->{$vmid};
2049 next if !$d->{node
} || $d->{node
} ne $nodename;
2050 next if !$d->{type
} || $d->{type
} ne 'qemu';
2051 $res->{$vmid}->{exists} = 1;
2056 # test if VM uses local resources (to prevent migration)
2057 sub check_local_resources
{
2058 my ($conf, $noerr) = @_;
2062 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2063 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2065 foreach my $k (keys %$conf) {
2066 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2067 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2070 die "VM uses local resources\n" if $loc_res && !$noerr;
2075 # check if used storages are available on all nodes (use by migrate)
2076 sub check_storage_availability
{
2077 my ($storecfg, $conf, $node) = @_;
2079 foreach_drive
($conf, sub {
2080 my ($ds, $drive) = @_;
2082 my $volid = $drive->{file
};
2085 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2088 # check if storage is available on both nodes
2089 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2090 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2094 # list nodes where all VM images are available (used by has_feature API)
2096 my ($conf, $storecfg) = @_;
2098 my $nodelist = PVE
::Cluster
::get_nodelist
();
2099 my $nodehash = { map { $_ => 1 } @$nodelist };
2100 my $nodename = PVE
::INotify
::nodename
();
2102 foreach_drive
($conf, sub {
2103 my ($ds, $drive) = @_;
2105 my $volid = $drive->{file
};
2108 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2110 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2111 if ($scfg->{disable
}) {
2113 } elsif (my $avail = $scfg->{nodes
}) {
2114 foreach my $node (keys %$nodehash) {
2115 delete $nodehash->{$node} if !$avail->{$node};
2117 } elsif (!$scfg->{shared
}) {
2118 foreach my $node (keys %$nodehash) {
2119 delete $nodehash->{$node} if $node ne $nodename
2131 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2135 my ($pidfile, $pid) = @_;
2137 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2141 return undef if !$line;
2142 my @param = split(/\0/, $line);
2144 my $cmd = $param[0];
2145 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2147 for (my $i = 0; $i < scalar (@param); $i++) {
2150 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2151 my $p = $param[$i+1];
2152 return 1 if $p && ($p eq $pidfile);
2161 my ($vmid, $nocheck, $node) = @_;
2163 my $filename = config_file
($vmid, $node);
2165 die "unable to find configuration file for VM $vmid - no such machine\n"
2166 if !$nocheck && ! -f
$filename;
2168 my $pidfile = pidfile_name
($vmid);
2170 if (my $fd = IO
::File-
>new("<$pidfile")) {
2175 my $mtime = $st->mtime;
2176 if ($mtime > time()) {
2177 warn "file '$filename' modified in future\n";
2180 if ($line =~ m/^(\d+)$/) {
2182 if (check_cmdline
($pidfile, $pid)) {
2183 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2195 my $vzlist = config_list
();
2197 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2199 while (defined(my $de = $fd->read)) {
2200 next if $de !~ m/^(\d+)\.pid$/;
2202 next if !defined($vzlist->{$vmid});
2203 if (my $pid = check_running
($vmid)) {
2204 $vzlist->{$vmid}->{pid
} = $pid;
2212 my ($storecfg, $conf) = @_;
2214 my $bootdisk = $conf->{bootdisk
};
2215 return undef if !$bootdisk;
2216 return undef if !valid_drivename
($bootdisk);
2218 return undef if !$conf->{$bootdisk};
2220 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2221 return undef if !defined($drive);
2223 return undef if drive_is_cdrom
($drive);
2225 my $volid = $drive->{file
};
2226 return undef if !$volid;
2228 return $drive->{size
};
2231 my $last_proc_pid_stat;
2233 # get VM status information
2234 # This must be fast and should not block ($full == false)
2235 # We only query KVM using QMP if $full == true (this can be slow)
2237 my ($opt_vmid, $full) = @_;
2241 my $storecfg = PVE
::Storage
::config
();
2243 my $list = vzlist
();
2244 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2246 my $cpucount = $cpuinfo->{cpus
} || 1;
2248 foreach my $vmid (keys %$list) {
2249 next if $opt_vmid && ($vmid ne $opt_vmid);
2251 my $cfspath = cfs_config_path
($vmid);
2252 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2255 $d->{pid
} = $list->{$vmid}->{pid
};
2257 # fixme: better status?
2258 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2260 my $size = disksize
($storecfg, $conf);
2261 if (defined($size)) {
2262 $d->{disk
} = 0; # no info available
2263 $d->{maxdisk
} = $size;
2269 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2270 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2272 $d->{name
} = $conf->{name
} || "VM $vmid";
2273 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2275 if ($conf->{balloon
}) {
2276 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2277 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2288 $d->{diskwrite
} = 0;
2290 $d->{template
} = is_template
($conf);
2295 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2296 foreach my $dev (keys %$netdev) {
2297 next if $dev !~ m/^tap([1-9]\d*)i/;
2299 my $d = $res->{$vmid};
2302 $d->{netout
} += $netdev->{$dev}->{receive
};
2303 $d->{netin
} += $netdev->{$dev}->{transmit
};
2306 my $ctime = gettimeofday
;
2308 foreach my $vmid (keys %$list) {
2310 my $d = $res->{$vmid};
2311 my $pid = $d->{pid
};
2314 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2315 next if !$pstat; # not running
2317 my $used = $pstat->{utime} + $pstat->{stime
};
2319 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2321 if ($pstat->{vsize
}) {
2322 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2325 my $old = $last_proc_pid_stat->{$pid};
2327 $last_proc_pid_stat->{$pid} = {
2335 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2337 if ($dtime > 1000) {
2338 my $dutime = $used - $old->{used
};
2340 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2341 $last_proc_pid_stat->{$pid} = {
2347 $d->{cpu
} = $old->{cpu
};
2351 return $res if !$full;
2353 my $qmpclient = PVE
::QMPClient-
>new();
2355 my $ballooncb = sub {
2356 my ($vmid, $resp) = @_;
2358 my $info = $resp->{'return'};
2359 return if !$info->{max_mem
};
2361 my $d = $res->{$vmid};
2363 # use memory assigned to VM
2364 $d->{maxmem
} = $info->{max_mem
};
2365 $d->{balloon
} = $info->{actual
};
2367 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2368 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2369 $d->{freemem
} = $info->{free_mem
};
2374 my $blockstatscb = sub {
2375 my ($vmid, $resp) = @_;
2376 my $data = $resp->{'return'} || [];
2377 my $totalrdbytes = 0;
2378 my $totalwrbytes = 0;
2379 for my $blockstat (@$data) {
2380 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2381 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2383 $res->{$vmid}->{diskread
} = $totalrdbytes;
2384 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2387 my $statuscb = sub {
2388 my ($vmid, $resp) = @_;
2390 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2391 # this fails if ballon driver is not loaded, so this must be
2392 # the last commnand (following command are aborted if this fails).
2393 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2395 my $status = 'unknown';
2396 if (!defined($status = $resp->{'return'}->{status
})) {
2397 warn "unable to get VM status\n";
2401 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2404 foreach my $vmid (keys %$list) {
2405 next if $opt_vmid && ($vmid ne $opt_vmid);
2406 next if !$res->{$vmid}->{pid
}; # not running
2407 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2410 $qmpclient->queue_execute(undef, 1);
2412 foreach my $vmid (keys %$list) {
2413 next if $opt_vmid && ($vmid ne $opt_vmid);
2414 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2421 my ($conf, $func) = @_;
2423 foreach my $ds (keys %$conf) {
2424 next if !valid_drivename
($ds);
2426 my $drive = parse_drive
($ds, $conf->{$ds});
2429 &$func($ds, $drive);
2434 my ($conf, $func) = @_;
2438 my $test_volid = sub {
2439 my ($volid, $is_cdrom) = @_;
2443 $volhash->{$volid} = $is_cdrom || 0;
2446 foreach_drive
($conf, sub {
2447 my ($ds, $drive) = @_;
2448 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2451 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2452 my $snap = $conf->{snapshots
}->{$snapname};
2453 &$test_volid($snap->{vmstate
}, 0);
2454 foreach_drive
($snap, sub {
2455 my ($ds, $drive) = @_;
2456 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2460 foreach my $volid (keys %$volhash) {
2461 &$func($volid, $volhash->{$volid});
2465 sub vga_conf_has_spice
{
2468 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2473 sub config_to_command
{
2474 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2477 my $globalFlags = [];
2478 my $machineFlags = [];
2484 my $kvmver = kvm_user_version
();
2485 my $vernum = 0; # unknown
2486 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2487 $vernum = $1*1000000+$2*1000;
2488 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2489 $vernum = $1*1000000+$2*1000+$3;
2492 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2494 my $have_ovz = -f
'/proc/vz/vestat';
2496 my $q35 = machine_type_is_q35
($conf);
2498 push @$cmd, '/usr/bin/kvm';
2500 push @$cmd, '-id', $vmid;
2504 my $qmpsocket = qmp_socket
($vmid);
2505 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2506 push @$cmd, '-mon', "chardev=qmp,mode=control";
2508 my $socket = vnc_socket
($vmid);
2509 push @$cmd, '-vnc', "unix:$socket,x509,password";
2511 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2513 push @$cmd, '-daemonize';
2515 if ($conf->{smbios1
}) {
2516 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2519 push @$cmd, '-object', "iothread,id=iothread0" if $conf->{iothread
};
2522 # the q35 chipset support native usb2, so we enable usb controller
2523 # by default for this machine type
2524 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2526 $pciaddr = print_pci_addr
("piix3", $bridges);
2527 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2530 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2531 next if !$conf->{"usb$i"};
2534 # include usb device config
2535 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2538 my $vga = $conf->{vga
};
2540 my $qxlnum = vga_conf_has_spice
($vga);
2541 $vga = 'qxl' if $qxlnum;
2544 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2545 $conf->{ostype
} eq 'win7' ||
2546 $conf->{ostype
} eq 'w2k8')) {
2553 # enable absolute mouse coordinates (needed by vnc)
2555 if (defined($conf->{tablet
})) {
2556 $tablet = $conf->{tablet
};
2558 $tablet = $defaults->{tablet
};
2559 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2560 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2563 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2566 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2567 my $d = parse_hostpci
($conf->{"hostpci$i"});
2570 my $pcie = $d->{pcie
};
2572 die "q35 machine model is not enabled" if !$q35;
2573 $pciaddr = print_pcie_addr
("hostpci$i");
2575 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2578 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2579 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2580 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2581 if ($xvga && $xvga ne '') {
2582 push @$cpuFlags, 'kvm=off';
2585 $driver = "vfio-pci" if $xvga ne '';
2586 my $pcidevices = $d->{pciid
};
2587 my $multifunction = 1 if @$pcidevices > 1;
2590 foreach my $pcidevice (@$pcidevices) {
2592 my $id = "hostpci$i";
2593 $id .= ".$j" if $multifunction;
2594 my $addr = $pciaddr;
2595 $addr .= ".$j" if $multifunction;
2596 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2599 $devicestr .= "$rombar$xvga";
2600 $devicestr .= ",multifunction=on" if $multifunction;
2603 push @$devices, '-device', $devicestr;
2609 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2610 my $d = parse_usb_device
($conf->{"usb$i"});
2612 if ($d->{vendorid
} && $d->{productid
}) {
2613 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2614 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2615 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2616 } elsif ($d->{spice
}) {
2617 # usb redir support for spice
2618 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2619 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2624 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2625 if (my $path = $conf->{"serial$i"}) {
2626 if ($path eq 'socket') {
2627 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2628 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2629 push @$devices, '-device', "isa-serial,chardev=serial$i";
2631 die "no such serial device\n" if ! -c
$path;
2632 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2633 push @$devices, '-device', "isa-serial,chardev=serial$i";
2639 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2640 if (my $path = $conf->{"parallel$i"}) {
2641 die "no such parallel device\n" if ! -c
$path;
2642 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2643 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2644 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2648 my $vmname = $conf->{name
} || "vm$vmid";
2650 push @$cmd, '-name', $vmname;
2653 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2654 $sockets = $conf->{sockets
} if $conf->{sockets
};
2656 my $cores = $conf->{cores
} || 1;
2657 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2659 my $total_cores = $sockets * $cores;
2660 my $allowed_cores = $cpuinfo->{cpus
};
2662 die "MAX $allowed_cores cores allowed per VM on this node\n"
2663 if ($allowed_cores < $total_cores);
2666 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2668 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2671 push @$cmd, '-nodefaults';
2673 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2675 my $bootindex_hash = {};
2677 foreach my $o (split(//, $bootorder)) {
2678 $bootindex_hash->{$o} = $i*100;
2682 push @$cmd, '-boot', "menu=on";
2684 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2686 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2688 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2691 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2693 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2694 my $useLocaltime = $conf->{localtime};
2696 if (my $ost = $conf->{ostype
}) {
2697 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2699 if ($ost =~ m/^w/) { # windows
2700 $useLocaltime = 1 if !defined($conf->{localtime});
2702 # use time drift fix when acpi is enabled
2703 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2704 $tdf = 1 if !defined($conf->{tdf
});
2708 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2710 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2711 push @$cmd, '-no-hpet';
2712 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2713 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2716 if ($ost eq 'win7' || $ost eq 'win8') {
2717 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2721 push @$rtcFlags, 'driftfix=slew' if $tdf;
2724 push @$machineFlags, 'accel=tcg';
2726 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2729 my $machine_type = $forcemachine || $conf->{machine
};
2730 if ($machine_type) {
2731 push @$machineFlags, "type=${machine_type}";
2734 if ($conf->{startdate
}) {
2735 push @$rtcFlags, "base=$conf->{startdate}";
2736 } elsif ($useLocaltime) {
2737 push @$rtcFlags, 'base=localtime';
2740 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2741 $cpu = $conf->{cpu
} if $conf->{cpu
};
2743 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2745 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2747 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2749 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2751 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2753 # Note: enforce needs kernel 3.10, so we do not use it for now
2754 # push @$cmd, '-cpu', "$cpu,enforce";
2755 push @$cmd, '-cpu', $cpu;
2757 my $memory = $conf->{memory
} || $defaults->{memory
};
2758 push @$cmd, '-m', $memory;
2760 if ($conf->{numa
}) {
2762 my $numa_totalmemory = undef;
2763 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2764 next if !$conf->{"numa$i"};
2765 my $numa = parse_numa
($conf->{"numa$i"});
2768 die "missing numa node$i memory value\n" if !$numa->{memory
};
2769 my $numa_memory = $numa->{memory
};
2770 $numa_totalmemory += $numa_memory;
2771 my $numa_object = "memory-backend-ram,id=ram-node$i,size=$numa_memory"."M";
2774 my $cpus_start = $numa->{cpus
}->{start
};
2775 die "missing numa node$i cpus\n" if !defined($cpus_start);
2776 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2777 my $cpus = $cpus_start;
2778 if (defined($cpus_end)) {
2779 $cpus .= "-$cpus_end";
2780 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2784 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2785 if (defined($hostnodes_start)) {
2786 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2787 my $hostnodes = $hostnodes_start;
2788 if (defined($hostnodes_end)) {
2789 $hostnodes .= "-$hostnodes_end";
2790 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2793 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2794 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2795 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2799 my $policy = $numa->{policy
};
2800 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2801 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2804 push @$cmd, '-object', $numa_object;
2805 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2808 die "total memory for NUMA nodes must be equal to vm memory\n"
2809 if $numa_totalmemory && $numa_totalmemory != $memory;
2811 #if no custom tology, we split memory and cores across numa nodes
2812 if(!$numa_totalmemory) {
2814 my $numa_memory = ($memory / $sockets) . "M";
2816 for (my $i = 0; $i < $sockets; $i++) {
2818 my $cpustart = ($cores * $i);
2819 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2820 my $cpus = $cpustart;
2821 $cpus .= "-$cpuend" if $cpuend;
2823 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2824 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2829 push @$cmd, '-S' if $conf->{freeze
};
2831 # set keyboard layout
2832 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2833 push @$cmd, '-k', $kb if $kb;
2836 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2837 #push @$cmd, '-soundhw', 'es1370';
2838 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2840 if($conf->{agent
}) {
2841 my $qgasocket = qmp_socket
($vmid, 1);
2842 my $pciaddr = print_pci_addr
("qga0", $bridges);
2843 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2844 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2845 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2852 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2853 for(my $i = 1; $i < $qxlnum; $i++){
2854 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2855 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2858 # assume other OS works like Linux
2859 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2860 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2864 my $pciaddr = print_pci_addr
("spice", $bridges);
2866 $spice_port = PVE
::Tools
::next_spice_port
();
2868 push @$devices, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2870 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
2871 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2872 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2875 # enable balloon by default, unless explicitly disabled
2876 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2877 $pciaddr = print_pci_addr
("balloon0", $bridges);
2878 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2881 if ($conf->{watchdog
}) {
2882 my $wdopts = parse_watchdog
($conf->{watchdog
});
2883 $pciaddr = print_pci_addr
("watchdog", $bridges);
2884 my $watchdog = $wdopts->{model
} || 'i6300esb';
2885 push @$devices, '-device', "$watchdog$pciaddr";
2886 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2890 my $scsicontroller = {};
2891 my $ahcicontroller = {};
2892 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2894 # Add iscsi initiator name if available
2895 if (my $initiator = get_initiator_name
()) {
2896 push @$devices, '-iscsi', "initiator-name=$initiator";
2899 foreach_drive
($conf, sub {
2900 my ($ds, $drive) = @_;
2902 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2903 push @$vollist, $drive->{file
};
2906 $use_virtio = 1 if $ds =~ m/^virtio/;
2908 if (drive_is_cdrom
($drive)) {
2909 if ($bootindex_hash->{d
}) {
2910 $drive->{bootindex
} = $bootindex_hash->{d
};
2911 $bootindex_hash->{d
} += 1;
2914 if ($bootindex_hash->{c
}) {
2915 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2916 $bootindex_hash->{c
} += 1;
2920 if ($drive->{interface
} eq 'scsi') {
2922 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2923 my $controller = int($drive->{index} / $maxdev);
2924 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2925 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2926 $scsicontroller->{$controller}=1;
2929 if ($drive->{interface
} eq 'sata') {
2930 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2931 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2932 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2933 $ahcicontroller->{$controller}=1;
2936 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
2937 push @$devices, '-drive',$drive_cmd;
2938 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2941 for (my $i = 0; $i < $MAX_NETS; $i++) {
2942 next if !$conf->{"net$i"};
2943 my $d = parse_net
($conf->{"net$i"});
2946 $use_virtio = 1 if $d->{model
} eq 'virtio';
2948 if ($bootindex_hash->{n
}) {
2949 $d->{bootindex
} = $bootindex_hash->{n
};
2950 $bootindex_hash->{n
} += 1;
2953 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2954 push @$devices, '-netdev', $netdevfull;
2956 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2957 push @$devices, '-device', $netdevicefull;
2962 while (my ($k, $v) = each %$bridges) {
2963 $pciaddr = print_pci_addr
("pci.$k");
2964 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2968 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2969 # when the VM uses virtio devices.
2970 if (!$use_virtio && $have_ovz) {
2972 my $cpuunits = defined($conf->{cpuunits
}) ?
2973 $conf->{cpuunits
} : $defaults->{cpuunits
};
2975 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2977 # fixme: cpulimit is currently ignored
2978 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2982 if ($conf->{args
}) {
2983 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2987 push @$cmd, @$devices;
2988 push @$cmd, '-rtc', join(',', @$rtcFlags)
2989 if scalar(@$rtcFlags);
2990 push @$cmd, '-machine', join(',', @$machineFlags)
2991 if scalar(@$machineFlags);
2992 push @$cmd, '-global', join(',', @$globalFlags)
2993 if scalar(@$globalFlags);
2995 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3000 return "${var_run_tmpdir}/$vmid.vnc";
3006 my $res = vm_mon_cmd
($vmid, 'query-spice');
3008 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3012 my ($vmid, $qga) = @_;
3013 my $sockettype = $qga ?
'qga' : 'qmp';
3014 return "${var_run_tmpdir}/$vmid.$sockettype";
3019 return "${var_run_tmpdir}/$vmid.pid";
3022 sub vm_devices_list
{
3025 my $res = vm_mon_cmd
($vmid, 'query-pci');
3028 foreach my $pcibus (@$res) {
3029 foreach my $device (@{$pcibus->{devices
}}) {
3030 next if !$device->{'qdev_id'};
3031 $devices->{$device->{'qdev_id'}} = 1;
3035 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3036 foreach my $block (@$resblock) {
3037 if($block->{device
} =~ m/^drive-(\S+)/){
3046 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3048 return 1 if !check_running
($vmid);
3050 my $q35 = machine_type_is_q35
($conf);
3052 if ($deviceid eq 'tablet') {
3053 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3057 return 1 if !$conf->{hotplug
};
3059 my $devices_list = vm_devices_list
($vmid);
3060 return 1 if defined($devices_list->{$deviceid});
3062 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
3064 if ($deviceid =~ m/^(virtio)(\d+)$/) {
3065 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
3066 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3067 qemu_deviceadd
($vmid, $devicefull);
3068 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
3069 qemu_drivedel
($vmid, $deviceid);
3074 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
3075 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3076 my $pciaddr = print_pci_addr
($deviceid);
3077 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
3078 qemu_deviceadd
($vmid, $devicefull);
3079 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
3082 if ($deviceid =~ m/^(scsi)(\d+)$/) {
3083 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3084 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
3085 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3086 if(!qemu_deviceadd
($vmid, $devicefull)) {
3087 qemu_drivedel
($vmid, $deviceid);
3092 if ($deviceid =~ m/^(net)(\d+)$/) {
3093 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3094 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3095 qemu_deviceadd
($vmid, $netdevicefull);
3096 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
3097 qemu_netdevdel
($vmid, $deviceid);
3103 if (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3105 my $pciaddr = print_pci_addr
($deviceid);
3106 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3107 qemu_deviceadd
($vmid, $devicefull);
3108 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
3114 sub vm_deviceunplug
{
3115 my ($vmid, $conf, $deviceid) = @_;
3117 return 1 if !check_running
($vmid);
3119 if ($deviceid eq 'tablet') {
3120 qemu_devicedel
($vmid, $deviceid);
3124 return 1 if !$conf->{hotplug
};
3126 my $devices_list = vm_devices_list
($vmid);
3127 return 1 if !defined($devices_list->{$deviceid});
3129 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3131 if ($deviceid =~ m/^(virtio)(\d+)$/) {
3132 qemu_devicedel
($vmid, $deviceid);
3133 return undef if !qemu_devicedelverify
($vmid, $deviceid);
3134 return undef if !qemu_drivedel
($vmid, $deviceid);
3137 if ($deviceid =~ m/^(lsi)(\d+)$/) {
3138 return undef if !qemu_devicedel
($vmid, $deviceid);
3141 if ($deviceid =~ m/^(scsi)(\d+)$/) {
3142 return undef if !qemu_devicedel
($vmid, $deviceid);
3143 return undef if !qemu_drivedel
($vmid, $deviceid);
3146 if ($deviceid =~ m/^(net)(\d+)$/) {
3147 qemu_devicedel
($vmid, $deviceid);
3148 return undef if !qemu_devicedelverify
($vmid, $deviceid);
3149 return undef if !qemu_netdevdel
($vmid, $deviceid);
3155 sub qemu_deviceadd
{
3156 my ($vmid, $devicefull) = @_;
3158 $devicefull = "driver=".$devicefull;
3159 my %options = split(/[=,]/, $devicefull);
3161 vm_mon_cmd
($vmid, "device_add" , %options);
3165 sub qemu_devicedel
{
3166 my($vmid, $deviceid) = @_;
3167 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3172 my($storecfg, $vmid, $device) = @_;
3174 my $drive = print_drive_full
($storecfg, $vmid, $device);
3175 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
3176 # If the command succeeds qemu prints: "OK"
3177 if ($ret !~ m/OK/s) {
3178 syslog
("err", "adding drive failed: $ret");
3185 my($vmid, $deviceid) = @_;
3187 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
3189 if ($ret =~ m/Device \'.*?\' not found/s) {
3190 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3192 elsif ($ret ne "") {
3193 syslog
("err", "deleting drive $deviceid failed : $ret");
3199 sub qemu_deviceaddverify
{
3200 my ($vmid,$deviceid) = @_;
3202 for (my $i = 0; $i <= 5; $i++) {
3203 my $devices_list = vm_devices_list
($vmid);
3204 return 1 if defined($devices_list->{$deviceid});
3207 syslog
("err", "error on hotplug device $deviceid");
3212 sub qemu_devicedelverify
{
3213 my ($vmid,$deviceid) = @_;
3215 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
3216 for (my $i = 0; $i <= 5; $i++) {
3217 my $devices_list = vm_devices_list
($vmid);
3218 return 1 if !defined($devices_list->{$deviceid});
3221 syslog
("err", "error on hot-unplugging device $deviceid");
3225 sub qemu_findorcreatescsihw
{
3226 my ($storecfg, $conf, $vmid, $device) = @_;
3228 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
3229 my $controller = int($device->{index} / $maxdev);
3230 my $scsihwid="scsihw$controller";
3231 my $devices_list = vm_devices_list
($vmid);
3233 if(!defined($devices_list->{$scsihwid})) {
3234 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
3239 sub qemu_bridgeadd
{
3240 my ($storecfg, $conf, $vmid, $device) = @_;
3243 my $bridgeid = undef;
3244 print_pci_addr
($device, $bridges);
3246 while (my ($k, $v) = each %$bridges) {
3249 return if !$bridgeid || $bridgeid < 1;
3250 my $bridge = "pci.$bridgeid";
3251 my $devices_list = vm_devices_list
($vmid);
3253 if(!defined($devices_list->{$bridge})) {
3254 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
3259 sub qemu_netdevadd
{
3260 my ($vmid, $conf, $device, $deviceid) = @_;
3262 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
3263 my %options = split(/[=,]/, $netdev);
3265 vm_mon_cmd
($vmid, "netdev_add", %options);
3269 sub qemu_netdevdel
{
3270 my ($vmid, $deviceid) = @_;
3272 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
3276 sub qemu_cpu_hotplug
{
3277 my ($vmid, $conf, $cores) = @_;
3279 die "new cores config is not defined" if !$cores;
3280 die "you can't add more cores than maxcpus"
3281 if $conf->{maxcpus
} && ($cores > $conf->{maxcpus
});
3282 return if !check_running
($vmid);
3284 my $currentcores = $conf->{cores
} if $conf->{cores
};
3285 die "current cores is not defined" if !$currentcores;
3286 die "maxcpus is not defined" if !$conf->{maxcpus
};
3287 raise_param_exc
({ 'cores' => "online cpu unplug is not yet possible" })
3288 if($cores < $currentcores);
3290 my $currentrunningcores = vm_mon_cmd
($vmid, "query-cpus");
3291 raise_param_exc
({ 'cores' => "cores number if running vm is different than configuration" })
3292 if scalar (@{$currentrunningcores}) != $currentcores;
3294 for(my $i = $currentcores; $i < $cores; $i++) {
3295 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
3299 sub qemu_block_set_io_throttle
{
3300 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3302 return if !check_running
($vmid) ;
3304 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));
3308 # old code, only used to shutdown old VM after update
3310 my ($fh, $timeout) = @_;
3312 my $sel = new IO
::Select
;
3319 while (scalar (@ready = $sel->can_read($timeout))) {
3321 if ($count = $fh->sysread($buf, 8192)) {
3322 if ($buf =~ /^(.*)\(qemu\) $/s) {
3329 if (!defined($count)) {
3336 die "monitor read timeout\n" if !scalar(@ready);
3341 # old code, only used to shutdown old VM after update
3342 sub vm_monitor_command
{
3343 my ($vmid, $cmdstr, $nocheck) = @_;
3348 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3350 my $sname = "${var_run_tmpdir}/$vmid.mon";
3352 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3353 die "unable to connect to VM $vmid socket - $!\n";
3357 # hack: migrate sometime blocks the monitor (when migrate_downtime
3359 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3360 $timeout = 60*60; # 1 hour
3364 my $data = __read_avail
($sock, $timeout);
3366 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3367 die "got unexpected qemu monitor banner\n";
3370 my $sel = new IO
::Select
;
3373 if (!scalar(my @ready = $sel->can_write($timeout))) {
3374 die "monitor write error - timeout";
3377 my $fullcmd = "$cmdstr\r";
3379 # syslog('info', "VM $vmid monitor command: $cmdstr");
3382 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3383 die "monitor write error - $!";
3386 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3390 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3391 $timeout = 60*60; # 1 hour
3392 } elsif ($cmdstr =~ m/^(eject|change)/) {
3393 $timeout = 60; # note: cdrom mount command is slow
3395 if ($res = __read_avail
($sock, $timeout)) {
3397 my @lines = split("\r?\n", $res);
3399 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3401 $res = join("\n", @lines);
3409 syslog
("err", "VM $vmid monitor command failed - $err");
3416 sub qemu_block_resize
{
3417 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3419 my $running = check_running
($vmid);
3421 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3423 return if !$running;
3425 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3429 sub qemu_volume_snapshot
{
3430 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3432 my $running = check_running
($vmid);
3434 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3436 return if !$running;
3438 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3442 sub qemu_volume_snapshot_delete
{
3443 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3445 my $running = check_running
($vmid);
3447 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3449 return if !$running;
3451 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3454 sub set_migration_caps
{
3460 "auto-converge" => 1,
3462 "x-rdma-pin-all" => 0,
3466 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3468 for my $supported_capability (@$supported_capabilities) {
3470 capability
=> $supported_capability->{capability
},
3471 state => $enabled_cap->{$supported_capability->{capability
}} ? JSON
::true
: JSON
::false
,
3475 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3479 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3481 lock_config
($vmid, sub {
3482 my $conf = load_config
($vmid, $migratedfrom);
3484 die "you can't start a vm if it's a template\n" if is_template
($conf);
3486 check_lock
($conf) if !$skiplock;
3488 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3490 my $defaults = load_defaults
();
3492 # set environment variable useful inside network script
3493 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3495 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3497 my $migrate_port = 0;
3500 if ($statefile eq 'tcp') {
3501 my $localip = "localhost";
3502 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3503 if ($datacenterconf->{migration_unsecure
}) {
3504 my $nodename = PVE
::INotify
::nodename
();
3505 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3507 $migrate_port = PVE
::Tools
::next_migrate_port
();
3508 $migrate_uri = "tcp:${localip}:${migrate_port}";
3509 push @$cmd, '-incoming', $migrate_uri;
3512 push @$cmd, '-loadstate', $statefile;
3519 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3520 my $d = parse_hostpci
($conf->{"hostpci$i"});
3522 my $pcidevices = $d->{pciid
};
3523 foreach my $pcidevice (@$pcidevices) {
3524 my $pciid = $pcidevice->{id
}.".".$pcidevice->{function
};
3526 my $info = pci_device_info
("0000:$pciid");
3527 die "IOMMU not present\n" if !check_iommu_support
();
3528 die "no pci device info for device '$pciid'\n" if !$info;
3530 if ($d->{driver
} && $d->{driver
} eq "vfio") {
3531 die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio
($pciid);
3533 die "can't unbind/bind to stub pci device '$pciid'\n" if !pci_dev_bind_to_stub
($info);
3536 die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset
} and !pci_dev_reset
($info);
3540 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3542 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3545 die "start failed: $err" if $err;
3547 print "migration listens on $migrate_uri\n" if $migrate_uri;
3549 if ($statefile && $statefile ne 'tcp') {
3550 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3554 if ($migratedfrom) {
3557 PVE
::QemuServer
::set_migration_caps
($vmid);
3562 print "spice listens on port $spice_port\n";
3563 if ($spice_ticket) {
3564 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3565 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3571 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3572 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3573 if $conf->{balloon
};
3574 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3575 path
=> "machine/peripheral/balloon0",
3576 property
=> "guest-stats-polling-interval",
3584 my ($vmid, $execute, %params) = @_;
3586 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3587 vm_qmp_command
($vmid, $cmd);
3590 sub vm_mon_cmd_nocheck
{
3591 my ($vmid, $execute, %params) = @_;
3593 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3594 vm_qmp_command
($vmid, $cmd, 1);
3597 sub vm_qmp_command
{
3598 my ($vmid, $cmd, $nocheck) = @_;
3603 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3604 $timeout = $cmd->{arguments
}->{timeout
};
3605 delete $cmd->{arguments
}->{timeout
};
3609 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3610 my $sname = qmp_socket
($vmid);
3611 if (-e
$sname) { # test if VM is reasonambe new and supports qmp/qga
3612 my $qmpclient = PVE
::QMPClient-
>new();
3614 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3615 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3616 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3617 if scalar(%{$cmd->{arguments
}});
3618 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3620 die "unable to open monitor socket\n";
3624 syslog
("err", "VM $vmid qmp command failed - $err");
3631 sub vm_human_monitor_command
{
3632 my ($vmid, $cmdline) = @_;
3637 execute
=> 'human-monitor-command',
3638 arguments
=> { 'command-line' => $cmdline},
3641 return vm_qmp_command
($vmid, $cmd);
3644 sub vm_commandline
{
3645 my ($storecfg, $vmid) = @_;
3647 my $conf = load_config
($vmid);
3649 my $defaults = load_defaults
();
3651 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3653 return join(' ', @$cmd);
3657 my ($vmid, $skiplock) = @_;
3659 lock_config
($vmid, sub {
3661 my $conf = load_config
($vmid);
3663 check_lock
($conf) if !$skiplock;
3665 vm_mon_cmd
($vmid, "system_reset");
3669 sub get_vm_volumes
{
3673 foreach_volid
($conf, sub {
3674 my ($volid, $is_cdrom) = @_;
3676 return if $volid =~ m
|^/|;
3678 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3681 push @$vollist, $volid;
3687 sub vm_stop_cleanup
{
3688 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3691 fairsched_rmnod
($vmid); # try to destroy group
3694 my $vollist = get_vm_volumes
($conf);
3695 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3698 foreach my $ext (qw(mon qmp pid vnc qga)) {
3699 unlink "/var/run/qemu-server/${vmid}.$ext";
3702 warn $@ if $@; # avoid errors - just warn
3705 # Note: use $nockeck to skip tests if VM configuration file exists.
3706 # We need that when migration VMs to other nodes (files already moved)
3707 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3709 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3711 $force = 1 if !defined($force) && !$shutdown;
3714 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3715 kill 15, $pid if $pid;
3716 my $conf = load_config
($vmid, $migratedfrom);
3717 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3721 lock_config
($vmid, sub {
3723 my $pid = check_running
($vmid, $nocheck);
3728 $conf = load_config
($vmid);
3729 check_lock
($conf) if !$skiplock;
3730 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3731 my $opts = parse_startup
($conf->{startup
});
3732 $timeout = $opts->{down
} if $opts->{down
};
3736 $timeout = 60 if !defined($timeout);
3740 if (!$nocheck && $conf->{agent
}) {
3741 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
3743 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
3746 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
3753 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3758 if ($count >= $timeout) {
3760 warn "VM still running - terminating now with SIGTERM\n";
3763 die "VM quit/powerdown failed - got timeout\n";
3766 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3771 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3774 die "VM quit/powerdown failed\n";
3782 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3787 if ($count >= $timeout) {
3788 warn "VM still running - terminating now with SIGKILL\n";
3793 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3798 my ($vmid, $skiplock) = @_;
3800 lock_config
($vmid, sub {
3802 my $conf = load_config
($vmid);
3804 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3806 vm_mon_cmd
($vmid, "stop");
3811 my ($vmid, $skiplock) = @_;
3813 lock_config
($vmid, sub {
3815 my $conf = load_config
($vmid);
3817 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3819 vm_mon_cmd
($vmid, "cont");
3824 my ($vmid, $skiplock, $key) = @_;
3826 lock_config
($vmid, sub {
3828 my $conf = load_config
($vmid);
3830 # there is no qmp command, so we use the human monitor command
3831 vm_human_monitor_command
($vmid, "sendkey $key");
3836 my ($storecfg, $vmid, $skiplock) = @_;
3838 lock_config
($vmid, sub {
3840 my $conf = load_config
($vmid);
3842 check_lock
($conf) if !$skiplock;
3844 if (!check_running
($vmid)) {
3845 fairsched_rmnod
($vmid); # try to destroy group
3846 destroy_vm
($storecfg, $vmid);
3848 die "VM $vmid is running - destroy failed\n";
3856 my ($filename, $buf) = @_;
3858 my $fh = IO
::File-
>new($filename, "w");
3859 return undef if !$fh;
3861 my $res = print $fh $buf;
3868 sub pci_device_info
{
3873 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3874 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3876 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3877 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3879 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3880 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3882 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3883 return undef if !defined($product) || $product !~ s/^0x//;
3888 product
=> $product,
3894 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3903 my $name = $dev->{name
};
3905 my $fn = "$pcisysfs/devices/$name/reset";
3907 return file_write
($fn, "1");
3910 sub pci_dev_bind_to_stub
{
3913 my $name = $dev->{name
};
3915 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3916 return 1 if -d
$testdir;
3918 my $data = "$dev->{vendor} $dev->{product}";
3919 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3921 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3922 if (!file_write
($fn, $name)) {
3923 return undef if -f
$fn;
3926 $fn = "$pcisysfs/drivers/pci-stub/bind";
3927 if (! -d
$testdir) {
3928 return undef if !file_write
($fn, $name);
3934 sub pci_dev_bind_to_vfio
{
3937 my $name = $dev->{name
};
3939 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
3941 if (!-d
$vfio_basedir) {
3942 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
3944 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
3946 my $testdir = "$vfio_basedir/$name";
3947 return 1 if -d
$testdir;
3949 my $data = "$dev->{vendor} $dev->{product}";
3950 return undef if !file_write
("$vfio_basedir/new_id", $data);
3952 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3953 if (!file_write
($fn, $name)) {
3954 return undef if -f
$fn;
3957 $fn = "$vfio_basedir/bind";
3958 if (! -d
$testdir) {
3959 return undef if !file_write
($fn, $name);
3965 sub pci_dev_group_bind_to_vfio
{
3968 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
3970 if (!-d
$vfio_basedir) {
3971 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
3973 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
3975 # get IOMMU group devices
3976 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
3977 my @devs = grep /^0000:/, readdir($D);
3980 foreach my $pciid (@devs) {
3981 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
3982 my $info = pci_device_info
($1);
3983 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
3989 sub print_pci_addr
{
3990 my ($id, $bridges) = @_;
3994 piix3
=> { bus
=> 0, addr
=> 1 },
3995 #addr2 : first videocard
3996 balloon0
=> { bus
=> 0, addr
=> 3 },
3997 watchdog
=> { bus
=> 0, addr
=> 4 },
3998 scsihw0
=> { bus
=> 0, addr
=> 5 },
3999 scsihw1
=> { bus
=> 0, addr
=> 6 },
4000 ahci0
=> { bus
=> 0, addr
=> 7 },
4001 qga0
=> { bus
=> 0, addr
=> 8 },
4002 spice
=> { bus
=> 0, addr
=> 9 },
4003 virtio0
=> { bus
=> 0, addr
=> 10 },
4004 virtio1
=> { bus
=> 0, addr
=> 11 },
4005 virtio2
=> { bus
=> 0, addr
=> 12 },
4006 virtio3
=> { bus
=> 0, addr
=> 13 },
4007 virtio4
=> { bus
=> 0, addr
=> 14 },
4008 virtio5
=> { bus
=> 0, addr
=> 15 },
4009 hostpci0
=> { bus
=> 0, addr
=> 16 },
4010 hostpci1
=> { bus
=> 0, addr
=> 17 },
4011 net0
=> { bus
=> 0, addr
=> 18 },
4012 net1
=> { bus
=> 0, addr
=> 19 },
4013 net2
=> { bus
=> 0, addr
=> 20 },
4014 net3
=> { bus
=> 0, addr
=> 21 },
4015 net4
=> { bus
=> 0, addr
=> 22 },
4016 net5
=> { bus
=> 0, addr
=> 23 },
4017 vga1
=> { bus
=> 0, addr
=> 24 },
4018 vga2
=> { bus
=> 0, addr
=> 25 },
4019 vga3
=> { bus
=> 0, addr
=> 26 },
4020 hostpci2
=> { bus
=> 0, addr
=> 27 },
4021 hostpci3
=> { bus
=> 0, addr
=> 28 },
4022 #addr29 : usb-host (pve-usb.cfg)
4023 'pci.1' => { bus
=> 0, addr
=> 30 },
4024 'pci.2' => { bus
=> 0, addr
=> 31 },
4025 'net6' => { bus
=> 1, addr
=> 1 },
4026 'net7' => { bus
=> 1, addr
=> 2 },
4027 'net8' => { bus
=> 1, addr
=> 3 },
4028 'net9' => { bus
=> 1, addr
=> 4 },
4029 'net10' => { bus
=> 1, addr
=> 5 },
4030 'net11' => { bus
=> 1, addr
=> 6 },
4031 'net12' => { bus
=> 1, addr
=> 7 },
4032 'net13' => { bus
=> 1, addr
=> 8 },
4033 'net14' => { bus
=> 1, addr
=> 9 },
4034 'net15' => { bus
=> 1, addr
=> 10 },
4035 'net16' => { bus
=> 1, addr
=> 11 },
4036 'net17' => { bus
=> 1, addr
=> 12 },
4037 'net18' => { bus
=> 1, addr
=> 13 },
4038 'net19' => { bus
=> 1, addr
=> 14 },
4039 'net20' => { bus
=> 1, addr
=> 15 },
4040 'net21' => { bus
=> 1, addr
=> 16 },
4041 'net22' => { bus
=> 1, addr
=> 17 },
4042 'net23' => { bus
=> 1, addr
=> 18 },
4043 'net24' => { bus
=> 1, addr
=> 19 },
4044 'net25' => { bus
=> 1, addr
=> 20 },
4045 'net26' => { bus
=> 1, addr
=> 21 },
4046 'net27' => { bus
=> 1, addr
=> 22 },
4047 'net28' => { bus
=> 1, addr
=> 23 },
4048 'net29' => { bus
=> 1, addr
=> 24 },
4049 'net30' => { bus
=> 1, addr
=> 25 },
4050 'net31' => { bus
=> 1, addr
=> 26 },
4051 'virtio6' => { bus
=> 2, addr
=> 1 },
4052 'virtio7' => { bus
=> 2, addr
=> 2 },
4053 'virtio8' => { bus
=> 2, addr
=> 3 },
4054 'virtio9' => { bus
=> 2, addr
=> 4 },
4055 'virtio10' => { bus
=> 2, addr
=> 5 },
4056 'virtio11' => { bus
=> 2, addr
=> 6 },
4057 'virtio12' => { bus
=> 2, addr
=> 7 },
4058 'virtio13' => { bus
=> 2, addr
=> 8 },
4059 'virtio14' => { bus
=> 2, addr
=> 9 },
4060 'virtio15' => { bus
=> 2, addr
=> 10 },
4063 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4064 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4065 my $bus = $devices->{$id}->{bus
};
4066 $res = ",bus=pci.$bus,addr=$addr";
4067 $bridges->{$bus} = 1 if $bridges;
4073 sub print_pcie_addr
{
4078 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4079 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4080 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4081 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4084 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4085 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4086 my $bus = $devices->{$id}->{bus
};
4087 $res = ",bus=$bus,addr=$addr";
4093 # vzdump restore implementaion
4095 sub tar_archive_read_firstfile
{
4096 my $archive = shift;
4098 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4100 # try to detect archive type first
4101 my $pid = open (TMP
, "tar tf '$archive'|") ||
4102 die "unable to open file '$archive'\n";
4103 my $firstfile = <TMP
>;
4107 die "ERROR: archive contaions no data\n" if !$firstfile;
4113 sub tar_restore_cleanup
{
4114 my ($storecfg, $statfile) = @_;
4116 print STDERR
"starting cleanup\n";
4118 if (my $fd = IO
::File-
>new($statfile, "r")) {
4119 while (defined(my $line = <$fd>)) {
4120 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4123 if ($volid =~ m
|^/|) {
4124 unlink $volid || die 'unlink failed\n';
4126 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4128 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4130 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4132 print STDERR
"unable to parse line in statfile - $line";
4139 sub restore_archive
{
4140 my ($archive, $vmid, $user, $opts) = @_;
4142 my $format = $opts->{format
};
4145 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4146 $format = 'tar' if !$format;
4148 } elsif ($archive =~ m/\.tar$/) {
4149 $format = 'tar' if !$format;
4150 } elsif ($archive =~ m/.tar.lzo$/) {
4151 $format = 'tar' if !$format;
4153 } elsif ($archive =~ m/\.vma$/) {
4154 $format = 'vma' if !$format;
4155 } elsif ($archive =~ m/\.vma\.gz$/) {
4156 $format = 'vma' if !$format;
4158 } elsif ($archive =~ m/\.vma\.lzo$/) {
4159 $format = 'vma' if !$format;
4162 $format = 'vma' if !$format; # default
4165 # try to detect archive format
4166 if ($format eq 'tar') {
4167 return restore_tar_archive
($archive, $vmid, $user, $opts);
4169 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4173 sub restore_update_config_line
{
4174 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4176 return if $line =~ m/^\#qmdump\#/;
4177 return if $line =~ m/^\#vzdump\#/;
4178 return if $line =~ m/^lock:/;
4179 return if $line =~ m/^unused\d+:/;
4180 return if $line =~ m/^parent:/;
4181 return if $line =~ m/^template:/; # restored VM is never a template
4183 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4184 # try to convert old 1.X settings
4185 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4186 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4187 my ($model, $macaddr) = split(/\=/, $devconfig);
4188 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4191 bridge
=> "vmbr$ind",
4192 macaddr
=> $macaddr,
4194 my $netstr = print_net
($net);
4196 print $outfd "net$cookie->{netcount}: $netstr\n";
4197 $cookie->{netcount
}++;
4199 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4200 my ($id, $netstr) = ($1, $2);
4201 my $net = parse_net
($netstr);
4202 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4203 $netstr = print_net
($net);
4204 print $outfd "$id: $netstr\n";
4205 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4208 if ($line =~ m/backup=no/) {
4209 print $outfd "#$line";
4210 } elsif ($virtdev && $map->{$virtdev}) {
4211 my $di = parse_drive
($virtdev, $value);
4212 delete $di->{format
}; # format can change on restore
4213 $di->{file
} = $map->{$virtdev};
4214 $value = print_drive
($vmid, $di);
4215 print $outfd "$virtdev: $value\n";
4225 my ($cfg, $vmid) = @_;
4227 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4229 my $volid_hash = {};
4230 foreach my $storeid (keys %$info) {
4231 foreach my $item (@{$info->{$storeid}}) {
4232 next if !($item->{volid
} && $item->{size
});
4233 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4234 $volid_hash->{$item->{volid
}} = $item;
4241 sub get_used_paths
{
4242 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
4246 my $scan_config = sub {
4247 my ($cref, $snapname) = @_;
4249 foreach my $key (keys %$cref) {
4250 my $value = $cref->{$key};
4251 if (valid_drivename
($key)) {
4252 next if $skip_drive && $key eq $skip_drive;
4253 my $drive = parse_drive
($key, $value);
4254 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
4255 if ($drive->{file
} =~ m!^/!) {
4256 $used_path->{$drive->{file
}}++; # = 1;
4258 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
4260 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
4262 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
4263 $used_path->{$path}++; # = 1;
4269 &$scan_config($conf);
4273 if ($scan_snapshots) {
4274 foreach my $snapname (keys %{$conf->{snapshots
}}) {
4275 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
4282 sub update_disksize
{
4283 my ($vmid, $conf, $volid_hash) = @_;
4289 # Note: it is allowed to define multiple storages with same path (alias), so
4290 # we need to check both 'volid' and real 'path' (two different volid can point
4291 # to the same path).
4296 foreach my $opt (keys %$conf) {
4297 if (valid_drivename
($opt)) {
4298 my $drive = parse_drive
($opt, $conf->{$opt});
4299 my $volid = $drive->{file
};
4302 $used->{$volid} = 1;
4303 if ($volid_hash->{$volid} &&
4304 (my $path = $volid_hash->{$volid}->{path
})) {
4305 $usedpath->{$path} = 1;
4308 next if drive_is_cdrom
($drive);
4309 next if !$volid_hash->{$volid};
4311 $drive->{size
} = $volid_hash->{$volid}->{size
};
4312 my $new = print_drive
($vmid, $drive);
4313 if ($new ne $conf->{$opt}) {
4315 $conf->{$opt} = $new;
4320 # remove 'unusedX' entry if volume is used
4321 foreach my $opt (keys %$conf) {
4322 next if $opt !~ m/^unused\d+$/;
4323 my $volid = $conf->{$opt};
4324 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
4325 if ($used->{$volid} || ($path && $usedpath->{$path})) {
4327 delete $conf->{$opt};
4331 foreach my $volid (sort keys %$volid_hash) {
4332 next if $volid =~ m/vm-$vmid-state-/;
4333 next if $used->{$volid};
4334 my $path = $volid_hash->{$volid}->{path
};
4335 next if !$path; # just to be sure
4336 next if $usedpath->{$path};
4338 add_unused_volume
($conf, $volid);
4339 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
4346 my ($vmid, $nolock) = @_;
4348 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
4350 my $volid_hash = scan_volids
($cfg, $vmid);
4352 my $updatefn = sub {
4355 my $conf = load_config
($vmid);
4360 foreach my $volid (keys %$volid_hash) {
4361 my $info = $volid_hash->{$volid};
4362 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
4365 my $changes = update_disksize
($vmid, $conf, $vm_volids);
4367 update_config_nolock
($vmid, $conf, 1) if $changes;
4370 if (defined($vmid)) {
4374 lock_config
($vmid, $updatefn, $vmid);
4377 my $vmlist = config_list
();
4378 foreach my $vmid (keys %$vmlist) {
4382 lock_config
($vmid, $updatefn, $vmid);
4388 sub restore_vma_archive
{
4389 my ($archive, $vmid, $user, $opts, $comp) = @_;
4391 my $input = $archive eq '-' ?
"<&STDIN" : undef;
4392 my $readfrom = $archive;
4397 my $qarchive = PVE
::Tools
::shellquote
($archive);
4398 if ($comp eq 'gzip') {
4399 $uncomp = "zcat $qarchive|";
4400 } elsif ($comp eq 'lzop') {
4401 $uncomp = "lzop -d -c $qarchive|";
4403 die "unknown compression method '$comp'\n";
4408 my $tmpdir = "/var/tmp/vzdumptmp$$";
4411 # disable interrupts (always do cleanups)
4412 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4413 warn "got interrupt - ignored\n";
4416 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4417 POSIX
::mkfifo
($mapfifo, 0600);
4420 my $openfifo = sub {
4421 open($fifofh, '>', $mapfifo) || die $!;
4424 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4431 my $rpcenv = PVE
::RPCEnvironment
::get
();
4433 my $conffile = config_file
($vmid);
4434 my $tmpfn = "$conffile.$$.tmp";
4436 # Note: $oldconf is undef if VM does not exists
4437 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4439 my $print_devmap = sub {
4440 my $virtdev_hash = {};
4442 my $cfgfn = "$tmpdir/qemu-server.conf";
4444 # we can read the config - that is already extracted
4445 my $fh = IO
::File-
>new($cfgfn, "r") ||
4446 "unable to read qemu-server.conf - $!\n";
4448 while (defined(my $line = <$fh>)) {
4449 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4450 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4451 die "archive does not contain data for drive '$virtdev'\n"
4452 if !$devinfo->{$devname};
4453 if (defined($opts->{storage
})) {
4454 $storeid = $opts->{storage
} || 'local';
4455 } elsif (!$storeid) {
4458 $format = 'raw' if !$format;
4459 $devinfo->{$devname}->{devname
} = $devname;
4460 $devinfo->{$devname}->{virtdev
} = $virtdev;
4461 $devinfo->{$devname}->{format
} = $format;
4462 $devinfo->{$devname}->{storeid
} = $storeid;
4464 # check permission on storage
4465 my $pool = $opts->{pool
}; # todo: do we need that?
4466 if ($user ne 'root@pam') {
4467 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4470 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4474 foreach my $devname (keys %$devinfo) {
4475 die "found no device mapping information for device '$devname'\n"
4476 if !$devinfo->{$devname}->{virtdev
};
4479 my $cfg = cfs_read_file
('storage.cfg');
4481 # create empty/temp config
4483 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4484 foreach_drive
($oldconf, sub {
4485 my ($ds, $drive) = @_;
4487 return if drive_is_cdrom
($drive);
4489 my $volid = $drive->{file
};
4491 return if !$volid || $volid =~ m
|^/|;
4493 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4494 return if !$path || !$owner || ($owner != $vmid);
4496 # Note: only delete disk we want to restore
4497 # other volumes will become unused
4498 if ($virtdev_hash->{$ds}) {
4499 PVE
::Storage
::vdisk_free
($cfg, $volid);
4505 foreach my $virtdev (sort keys %$virtdev_hash) {
4506 my $d = $virtdev_hash->{$virtdev};
4507 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4508 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4510 # test if requested format is supported
4511 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4512 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4513 $d->{format
} = $defFormat if !$supported;
4515 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4516 $d->{format
}, undef, $alloc_size);
4517 print STDERR
"new volume ID is '$volid'\n";
4518 $d->{volid
} = $volid;
4519 my $path = PVE
::Storage
::path
($cfg, $volid);
4521 my $write_zeros = 1;
4522 # fixme: what other storages types initialize volumes with zero?
4523 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4524 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4528 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4530 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4531 $map->{$virtdev} = $volid;
4534 $fh->seek(0, 0) || die "seek failed - $!\n";
4536 my $outfd = new IO
::File
($tmpfn, "w") ||
4537 die "unable to write config for VM $vmid\n";
4539 my $cookie = { netcount
=> 0 };
4540 while (defined(my $line = <$fh>)) {
4541 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4550 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4551 die "interrupted by signal\n";
4553 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4555 $oldtimeout = alarm($timeout);
4562 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4563 my ($dev_id, $size, $devname) = ($1, $2, $3);
4564 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4565 } elsif ($line =~ m/^CTIME: /) {
4566 # we correctly received the vma config, so we can disable
4567 # the timeout now for disk allocation (set to 10 minutes, so
4568 # that we always timeout if something goes wrong)
4571 print $fifofh "done\n";
4572 my $tmp = $oldtimeout || 0;
4573 $oldtimeout = undef;
4579 print "restore vma archive: $cmd\n";
4580 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4584 alarm($oldtimeout) if $oldtimeout;
4592 my $cfg = cfs_read_file
('storage.cfg');
4593 foreach my $devname (keys %$devinfo) {
4594 my $volid = $devinfo->{$devname}->{volid
};
4597 if ($volid =~ m
|^/|) {
4598 unlink $volid || die 'unlink failed\n';
4600 PVE
::Storage
::vdisk_free
($cfg, $volid);
4602 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4604 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4611 rename($tmpfn, $conffile) ||
4612 die "unable to commit configuration file '$conffile'\n";
4614 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4616 eval { rescan
($vmid, 1); };
4620 sub restore_tar_archive
{
4621 my ($archive, $vmid, $user, $opts) = @_;
4623 if ($archive ne '-') {
4624 my $firstfile = tar_archive_read_firstfile
($archive);
4625 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4626 if $firstfile ne 'qemu-server.conf';
4629 my $storecfg = cfs_read_file
('storage.cfg');
4631 # destroy existing data - keep empty config
4632 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4633 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4635 my $tocmd = "/usr/lib/qemu-server/qmextract";
4637 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4638 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4639 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4640 $tocmd .= ' --info' if $opts->{info
};
4642 # tar option "xf" does not autodetect compression when read from STDIN,
4643 # so we pipe to zcat
4644 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4645 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4647 my $tmpdir = "/var/tmp/vzdumptmp$$";
4650 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4651 local $ENV{VZDUMP_VMID
} = $vmid;
4652 local $ENV{VZDUMP_USER
} = $user;
4654 my $conffile = config_file
($vmid);
4655 my $tmpfn = "$conffile.$$.tmp";
4657 # disable interrupts (always do cleanups)
4658 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4659 print STDERR
"got interrupt - ignored\n";
4664 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4665 die "interrupted by signal\n";
4668 if ($archive eq '-') {
4669 print "extracting archive from STDIN\n";
4670 run_command
($cmd, input
=> "<&STDIN");
4672 print "extracting archive '$archive'\n";
4676 return if $opts->{info
};
4680 my $statfile = "$tmpdir/qmrestore.stat";
4681 if (my $fd = IO
::File-
>new($statfile, "r")) {
4682 while (defined (my $line = <$fd>)) {
4683 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4684 $map->{$1} = $2 if $1;
4686 print STDERR
"unable to parse line in statfile - $line\n";
4692 my $confsrc = "$tmpdir/qemu-server.conf";
4694 my $srcfd = new IO
::File
($confsrc, "r") ||
4695 die "unable to open file '$confsrc'\n";
4697 my $outfd = new IO
::File
($tmpfn, "w") ||
4698 die "unable to write config for VM $vmid\n";
4700 my $cookie = { netcount
=> 0 };
4701 while (defined (my $line = <$srcfd>)) {
4702 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4714 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4721 rename $tmpfn, $conffile ||
4722 die "unable to commit configuration file '$conffile'\n";
4724 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4726 eval { rescan
($vmid, 1); };
4731 # Internal snapshots
4733 # NOTE: Snapshot create/delete involves several non-atomic
4734 # action, and can take a long time.
4735 # So we try to avoid locking the file and use 'lock' variable
4736 # inside the config file instead.
4738 my $snapshot_copy_config = sub {
4739 my ($source, $dest) = @_;
4741 foreach my $k (keys %$source) {
4742 next if $k eq 'snapshots';
4743 next if $k eq 'snapstate';
4744 next if $k eq 'snaptime';
4745 next if $k eq 'vmstate';
4746 next if $k eq 'lock';
4747 next if $k eq 'digest';
4748 next if $k eq 'description';
4749 next if $k =~ m/^unused\d+$/;
4751 $dest->{$k} = $source->{$k};
4755 my $snapshot_apply_config = sub {
4756 my ($conf, $snap) = @_;
4758 # copy snapshot list
4760 snapshots
=> $conf->{snapshots
},
4763 # keep description and list of unused disks
4764 foreach my $k (keys %$conf) {
4765 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4766 $newconf->{$k} = $conf->{$k};
4769 &$snapshot_copy_config($snap, $newconf);
4774 sub foreach_writable_storage
{
4775 my ($conf, $func) = @_;
4779 foreach my $ds (keys %$conf) {
4780 next if !valid_drivename
($ds);
4782 my $drive = parse_drive
($ds, $conf->{$ds});
4784 next if drive_is_cdrom
($drive);
4786 my $volid = $drive->{file
};
4788 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4789 $sidhash->{$sid} = $sid if $sid;
4792 foreach my $sid (sort keys %$sidhash) {
4797 my $alloc_vmstate_volid = sub {
4798 my ($storecfg, $vmid, $conf, $snapname) = @_;
4800 # Note: we try to be smart when selecting a $target storage
4804 # search shared storage first
4805 foreach_writable_storage
($conf, sub {
4807 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4808 return if !$scfg->{shared
};
4810 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4814 # now search local storage
4815 foreach_writable_storage
($conf, sub {
4817 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4818 return if $scfg->{shared
};
4820 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4824 $target = 'local' if !$target;
4826 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4827 # we abort live save after $conf->{memory}, so we need at max twice that space
4828 my $size = $conf->{memory
}*2 + $driver_state_size;
4830 my $name = "vm-$vmid-state-$snapname";
4831 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4832 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4833 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4838 my $snapshot_prepare = sub {
4839 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4843 my $updatefn = sub {
4845 my $conf = load_config
($vmid);
4847 die "you can't take a snapshot if it's a template\n"
4848 if is_template
($conf);
4852 $conf->{lock} = 'snapshot';
4854 die "snapshot name '$snapname' already used\n"
4855 if defined($conf->{snapshots
}->{$snapname});
4857 my $storecfg = PVE
::Storage
::config
();
4858 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4860 $snap = $conf->{snapshots
}->{$snapname} = {};
4862 if ($save_vmstate && check_running
($vmid)) {
4863 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4866 &$snapshot_copy_config($conf, $snap);
4868 $snap->{snapstate
} = "prepare";
4869 $snap->{snaptime
} = time();
4870 $snap->{description
} = $comment if $comment;
4872 # always overwrite machine if we save vmstate. This makes sure we
4873 # can restore it later using correct machine type
4874 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4876 update_config_nolock
($vmid, $conf, 1);
4879 lock_config
($vmid, $updatefn);
4884 my $snapshot_commit = sub {
4885 my ($vmid, $snapname) = @_;
4887 my $updatefn = sub {
4889 my $conf = load_config
($vmid);
4891 die "missing snapshot lock\n"
4892 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4894 my $has_machine_config = defined($conf->{machine
});
4896 my $snap = $conf->{snapshots
}->{$snapname};
4898 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4900 die "wrong snapshot state\n"
4901 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4903 delete $snap->{snapstate
};
4904 delete $conf->{lock};
4906 my $newconf = &$snapshot_apply_config($conf, $snap);
4908 delete $newconf->{machine
} if !$has_machine_config;
4910 $newconf->{parent
} = $snapname;
4912 update_config_nolock
($vmid, $newconf, 1);
4915 lock_config
($vmid, $updatefn);
4918 sub snapshot_rollback
{
4919 my ($vmid, $snapname) = @_;
4925 my $storecfg = PVE
::Storage
::config
();
4927 my $updatefn = sub {
4929 my $conf = load_config
($vmid);
4931 die "you can't rollback if vm is a template\n" if is_template
($conf);
4933 $snap = $conf->{snapshots
}->{$snapname};
4935 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4937 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4938 if $snap->{snapstate
};
4942 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4945 die "unable to rollback vm $vmid: vm is running\n"
4946 if check_running
($vmid);
4949 $conf->{lock} = 'rollback';
4951 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4952 delete $conf->{lock};
4958 my $has_machine_config = defined($conf->{machine
});
4960 # copy snapshot config to current config
4961 $conf = &$snapshot_apply_config($conf, $snap);
4962 $conf->{parent
} = $snapname;
4964 # Note: old code did not store 'machine', so we try to be smart
4965 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4966 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4967 # we remove the 'machine' configuration if not explicitly specified
4968 # in the original config.
4969 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4972 update_config_nolock
($vmid, $conf, 1);
4974 if (!$prepare && $snap->{vmstate
}) {
4975 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4976 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4980 lock_config
($vmid, $updatefn);
4982 foreach_drive
($snap, sub {
4983 my ($ds, $drive) = @_;
4985 return if drive_is_cdrom
($drive);
4987 my $volid = $drive->{file
};
4988 my $device = "drive-$ds";
4990 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4994 lock_config
($vmid, $updatefn);
4997 my $savevm_wait = sub {
5001 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5002 if (!$stat->{status
}) {
5003 die "savevm not active\n";
5004 } elsif ($stat->{status
} eq 'active') {
5007 } elsif ($stat->{status
} eq 'completed') {
5010 die "query-savevm returned status '$stat->{status}'\n";
5015 sub snapshot_create
{
5016 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5018 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5020 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5022 my $config = load_config
($vmid);
5024 my $running = check_running
($vmid);
5026 my $freezefs = $running && $config->{agent
};
5027 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5032 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5033 warn "guest-fsfreeze-freeze problems - $@" if $@;
5037 # create internal snapshots of all drives
5039 my $storecfg = PVE
::Storage
::config
();
5042 if ($snap->{vmstate
}) {
5043 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5044 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5045 &$savevm_wait($vmid);
5047 vm_mon_cmd
($vmid, "savevm-start");
5051 foreach_drive
($snap, sub {
5052 my ($ds, $drive) = @_;
5054 return if drive_is_cdrom
($drive);
5056 my $volid = $drive->{file
};
5057 my $device = "drive-$ds";
5059 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5060 $drivehash->{$ds} = 1;
5066 eval { vm_mon_cmd
($vmid, "savevm-end") };
5070 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5071 warn "guest-fsfreeze-thaw problems - $@" if $@;
5074 # savevm-end is async, we need to wait
5076 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5077 if (!$stat->{bytes
}) {
5080 print "savevm not yet finished\n";
5088 warn "snapshot create failed: starting cleanup\n";
5089 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5094 &$snapshot_commit($vmid, $snapname);
5097 # Note: $drivehash is only set when called from snapshot_create.
5098 sub snapshot_delete
{
5099 my ($vmid, $snapname, $force, $drivehash) = @_;
5106 my $unlink_parent = sub {
5107 my ($confref, $new_parent) = @_;
5109 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5111 $confref->{parent
} = $new_parent;
5113 delete $confref->{parent
};
5118 my $updatefn = sub {
5119 my ($remove_drive) = @_;
5121 my $conf = load_config
($vmid);
5125 die "you can't delete a snapshot if vm is a template\n"
5126 if is_template
($conf);
5129 $snap = $conf->{snapshots
}->{$snapname};
5131 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5133 # remove parent refs
5135 &$unlink_parent($conf, $snap->{parent
});
5136 foreach my $sn (keys %{$conf->{snapshots
}}) {
5137 next if $sn eq $snapname;
5138 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5142 if ($remove_drive) {
5143 if ($remove_drive eq 'vmstate') {
5144 delete $snap->{$remove_drive};
5146 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5147 my $volid = $drive->{file
};
5148 delete $snap->{$remove_drive};
5149 add_unused_volume
($conf, $volid);
5154 $snap->{snapstate
} = 'delete';
5156 delete $conf->{snapshots
}->{$snapname};
5157 delete $conf->{lock} if $drivehash;
5158 foreach my $volid (@$unused) {
5159 add_unused_volume
($conf, $volid);
5163 update_config_nolock
($vmid, $conf, 1);
5166 lock_config
($vmid, $updatefn);
5168 # now remove vmstate file
5170 my $storecfg = PVE
::Storage
::config
();
5172 if ($snap->{vmstate
}) {
5173 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5175 die $err if !$force;
5178 # save changes (remove vmstate from snapshot)
5179 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5182 # now remove all internal snapshots
5183 foreach_drive
($snap, sub {
5184 my ($ds, $drive) = @_;
5186 return if drive_is_cdrom
($drive);
5188 my $volid = $drive->{file
};
5189 my $device = "drive-$ds";
5191 if (!$drivehash || $drivehash->{$ds}) {
5192 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
5194 die $err if !$force;
5199 # save changes (remove drive fron snapshot)
5200 lock_config
($vmid, $updatefn, $ds) if !$force;
5201 push @$unused, $volid;
5204 # now cleanup config
5206 lock_config
($vmid, $updatefn);
5210 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
5213 foreach_drive
($conf, sub {
5214 my ($ds, $drive) = @_;
5216 return if drive_is_cdrom
($drive);
5217 my $volid = $drive->{file
};
5218 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
5221 return $err ?
0 : 1;
5224 sub template_create
{
5225 my ($vmid, $conf, $disk) = @_;
5227 my $storecfg = PVE
::Storage
::config
();
5229 foreach_drive
($conf, sub {
5230 my ($ds, $drive) = @_;
5232 return if drive_is_cdrom
($drive);
5233 return if $disk && $ds ne $disk;
5235 my $volid = $drive->{file
};
5236 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5238 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5239 $drive->{file
} = $voliddst;
5240 $conf->{$ds} = print_drive
($vmid, $drive);
5241 update_config_nolock
($vmid, $conf, 1);
5248 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
5251 sub qemu_img_convert
{
5252 my ($src_volid, $dst_volid, $size, $snapname) = @_;
5254 my $storecfg = PVE
::Storage
::config
();
5255 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5256 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5258 if ($src_storeid && $dst_storeid) {
5259 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5260 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5262 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5263 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5265 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5266 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5269 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5270 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5271 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
5275 if($line =~ m/\((\S+)\/100\
%\)/){
5277 my $transferred = int($size * $percent / 100);
5278 my $remaining = $size - $transferred;
5280 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5285 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5287 die "copy failed: $err" if $err;
5291 sub qemu_img_format
{
5292 my ($scfg, $volname) = @_;
5294 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
5296 } elsif ($scfg->{type
} eq 'iscsi') {
5297 return "host_device";
5303 sub qemu_drive_mirror
{
5304 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
5311 my $storecfg = PVE
::Storage
::config
();
5312 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5314 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5317 if ($dst_volname =~ m/\.(raw|qcow2)$/){
5321 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5323 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
5324 $opts->{format
} = $format if $format;
5326 #fixme : sometime drive-mirror timeout, but works fine after.
5327 # (I have see the problem with big volume > 200GB), so we need to eval
5328 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); };
5329 # ignore errors here
5333 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5334 my $stat = @$stats[0];
5335 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5336 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5338 my $busy = $stat->{busy
};
5340 if (my $total = $stat->{len
}) {
5341 my $transferred = $stat->{offset
} || 0;
5342 my $remaining = $total - $transferred;
5343 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5345 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy\n";
5348 if ($stat->{len
} == $stat->{offset
}) {
5349 if ($busy eq 'false') {
5351 last if $vmiddst != $vmid;
5353 # try to switch the disk if source and destination are on the same guest
5354 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5356 die $@ if $@ !~ m/cannot be completed/;
5359 if ($count > $maxwait) {
5360 # if too much writes to disk occurs at the end of migration
5361 #the disk needs to be freezed to be able to complete the migration
5362 vm_suspend
($vmid,1);
5367 $old_len = $stat->{offset
};
5371 vm_resume
($vmid, 1) if $frozen;
5376 my $cancel_job = sub {
5377 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5379 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5380 my $stat = @$stats[0];
5387 eval { &$cancel_job(); };
5388 die "mirroring error: $err";
5391 if ($vmiddst != $vmid) {
5392 # if we clone a disk for a new target vm, we don't switch the disk
5393 &$cancel_job(); # so we call block-job-cancel
5398 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5399 $newvmid, $storage, $format, $full, $newvollist) = @_;
5404 print "create linked clone of drive $drivename ($drive->{file})\n";
5405 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5406 push @$newvollist, $newvolid;
5408 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5409 $storeid = $storage if $storage;
5411 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5413 $format = $drive->{format
} || $defFormat;
5416 # test if requested format is supported - else use default
5417 my $supported = grep { $_ eq $format } @$validFormats;
5418 $format = $defFormat if !$supported;
5420 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5422 print "create full clone of drive $drivename ($drive->{file})\n";
5423 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5424 push @$newvollist, $newvolid;
5426 if (!$running || $snapname) {
5427 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
5429 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
5433 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5436 $disk->{format
} = undef;
5437 $disk->{file
} = $newvolid;
5438 $disk->{size
} = $size;
5443 # this only works if VM is running
5444 sub get_current_qemu_machine
{
5447 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5448 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
5450 my ($current, $default);
5451 foreach my $e (@$res) {
5452 $default = $e->{name
} if $e->{'is-default'};
5453 $current = $e->{name
} if $e->{'is-current'};
5456 # fallback to the default machine if current is not supported by qemu
5457 return $current || $default || 'pc';
5464 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5465 my (undef, $id, $function) = @_;
5466 my $res = { id
=> $id, function
=> $function};
5467 push @{$devices->{$id}}, $res;