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).",
175 type
=> 'string', format
=> 'pve-hotplug-features',
176 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
177 default => 'network,disk,usb',
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
=> "Number of hotplugged vcpus.",
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 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
509 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
513 type
=> 'string', format
=> 'pve-qm-net',
514 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
515 description
=> <<EODESCR,
516 Specify network devices.
518 MODEL is one of: $nic_model_list_txt
520 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
521 automatically generated if not specified.
523 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
525 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'.
527 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
533 The DHCP server assign addresses to the guest starting from 10.0.2.15.
537 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
539 for (my $i = 0; $i < $MAX_NETS; $i++) {
540 $confdesc->{"net$i"} = $netdesc;
547 type
=> 'string', format
=> 'pve-qm-drive',
548 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]',
549 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
551 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
555 type
=> 'string', format
=> 'pve-qm-drive',
556 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]',
557 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
559 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
563 type
=> 'string', format
=> 'pve-qm-drive',
564 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]',
565 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
567 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
571 type
=> 'string', format
=> 'pve-qm-drive',
572 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]',
573 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
575 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
579 type
=> 'string', format
=> 'pve-qm-usb-device',
580 typetext
=> 'host=HOSTUSBDEVICE|spice',
581 description
=> <<EODESCR,
582 Configure an USB device (n is 0 to 4). This can be used to
583 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
585 'bus-port(.port)*' (decimal numbers) or
586 'vendor_id:product_id' (hexadeciaml numbers)
588 You can use the 'lsusb -t' command to list existing usb devices.
590 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
592 The value 'spice' can be used to add a usb redirection devices for spice.
596 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
600 type
=> 'string', format
=> 'pve-qm-hostpci',
601 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
602 description
=> <<EODESCR,
603 Map host pci devices. HOSTPCIDEVICE syntax is:
605 'bus:dev.func' (hexadecimal numbers)
607 You can us the 'lspci' command to list existing pci devices.
609 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
611 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
613 Experimental: user reported problems with this option.
616 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
621 pattern
=> '(/dev/.+|socket)',
622 description
=> <<EODESCR,
623 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).
625 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
627 Experimental: user reported problems with this option.
634 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
635 description
=> <<EODESCR,
636 Map host parallel devices (n is 0 to 2).
638 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
640 Experimental: user reported problems with this option.
644 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
645 $confdesc->{"parallel$i"} = $paralleldesc;
648 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
649 $confdesc->{"serial$i"} = $serialdesc;
652 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
653 $confdesc->{"hostpci$i"} = $hostpcidesc;
656 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
657 $drivename_hash->{"ide$i"} = 1;
658 $confdesc->{"ide$i"} = $idedesc;
661 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
662 $drivename_hash->{"sata$i"} = 1;
663 $confdesc->{"sata$i"} = $satadesc;
666 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
667 $drivename_hash->{"scsi$i"} = 1;
668 $confdesc->{"scsi$i"} = $scsidesc ;
671 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
672 $drivename_hash->{"virtio$i"} = 1;
673 $confdesc->{"virtio$i"} = $virtiodesc;
676 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
677 $confdesc->{"usb$i"} = $usbdesc;
682 type
=> 'string', format
=> 'pve-volume-id',
683 description
=> "Reference to unused volumes.",
686 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
687 $confdesc->{"unused$i"} = $unuseddesc;
690 my $kvm_api_version = 0;
694 return $kvm_api_version if $kvm_api_version;
696 my $fh = IO
::File-
>new("</dev/kvm") ||
699 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
700 $kvm_api_version = $v;
705 return $kvm_api_version;
708 my $kvm_user_version;
710 sub kvm_user_version
{
712 return $kvm_user_version if $kvm_user_version;
714 $kvm_user_version = 'unknown';
716 my $tmp = `kvm -help 2>/dev/null`;
718 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
719 $kvm_user_version = $2;
722 return $kvm_user_version;
726 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
729 # order is important - used to autoselect boot disk
730 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
731 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
732 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
733 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
736 sub valid_drivename
{
739 return defined($drivename_hash->{$dev});
744 return defined($confdesc->{$key});
748 return $nic_model_list;
751 sub os_list_description
{
756 w2k
=> 'Windows 2000',
757 w2k3
=>, 'Windows 2003',
758 w2k8
=> 'Windows 2008',
759 wvista
=> 'Windows Vista',
761 win8
=> 'Windows 8/2012',
771 return $cdrom_path if $cdrom_path;
773 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
774 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
775 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
779 my ($storecfg, $vmid, $cdrom) = @_;
781 if ($cdrom eq 'cdrom') {
782 return get_cdrom_path
();
783 } elsif ($cdrom eq 'none') {
785 } elsif ($cdrom =~ m
|^/|) {
788 return PVE
::Storage
::path
($storecfg, $cdrom);
792 # try to convert old style file names to volume IDs
793 sub filename_to_volume_id
{
794 my ($vmid, $file, $media) = @_;
796 if (!($file eq 'none' || $file eq 'cdrom' ||
797 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
799 return undef if $file =~ m
|/|;
801 if ($media && $media eq 'cdrom') {
802 $file = "local:iso/$file";
804 $file = "local:$vmid/$file";
811 sub verify_media_type
{
812 my ($opt, $vtype, $media) = @_;
817 if ($media eq 'disk') {
819 } elsif ($media eq 'cdrom') {
822 die "internal error";
825 return if ($vtype eq $etype);
827 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
830 sub cleanup_drive_path
{
831 my ($opt, $storecfg, $drive) = @_;
833 # try to convert filesystem paths to volume IDs
835 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
836 ($drive->{file
} !~ m
|^/dev/.+|) &&
837 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
838 ($drive->{file
} !~ m/^\d+$/)) {
839 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
840 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
841 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
842 verify_media_type
($opt, $vtype, $drive->{media
});
843 $drive->{file
} = $volid;
846 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
849 sub create_conf_nolock
{
850 my ($vmid, $settings) = @_;
852 my $filename = config_file
($vmid);
854 die "configuration file '$filename' already exists\n" if -f
$filename;
856 my $defaults = load_defaults
();
858 $settings->{name
} = "vm$vmid" if !$settings->{name
};
859 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
862 foreach my $opt (keys %$settings) {
863 next if !$confdesc->{$opt};
865 my $value = $settings->{$opt};
868 $data .= "$opt: $value\n";
871 PVE
::Tools
::file_set_contents
($filename, $data);
874 sub parse_hotplug_features
{
879 return $res if $data eq '0';
881 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
883 foreach my $feature (split(/,/, $data)) {
884 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
887 warn "ignoring unknown hotplug feature '$feature'\n";
893 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
894 sub pve_verify_hotplug_features
{
895 my ($value, $noerr) = @_;
897 return $value if parse_hotplug_features
($value);
899 return undef if $noerr;
901 die "unable to parse hotplug option\n";
904 my $parse_size = sub {
907 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
908 my ($size, $unit) = ($1, $3);
911 $size = $size * 1024;
912 } elsif ($unit eq 'M') {
913 $size = $size * 1024 * 1024;
914 } elsif ($unit eq 'G') {
915 $size = $size * 1024 * 1024 * 1024;
921 my $format_size = sub {
926 my $kb = int($size/1024);
927 return $size if $kb*1024 != $size;
929 my $mb = int($kb/1024);
930 return "${kb}K" if $mb*1024 != $kb;
932 my $gb = int($mb/1024);
933 return "${mb}M" if $gb*1024 != $mb;
938 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
939 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
940 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
941 # [,aio=native|threads][,discard=ignore|on]
944 my ($key, $data) = @_;
948 # $key may be undefined - used to verify JSON parameters
949 if (!defined($key)) {
950 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
952 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
953 $res->{interface
} = $1;
959 foreach my $p (split (/,/, $data)) {
960 next if $p =~ m/^\s*$/;
962 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)=(.+)$/) {
963 my ($k, $v) = ($1, $2);
965 $k = 'file' if $k eq 'volume';
967 return undef if defined $res->{$k};
969 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
970 return undef if !$v || $v !~ m/^\d+/;
972 $v = sprintf("%.3f", $v / (1024*1024));
976 if (!$res->{file
} && $p !~ m/=/) {
984 return undef if !$res->{file
};
986 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
990 return undef if $res->{cache
} &&
991 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
992 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
993 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
994 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
995 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
996 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
997 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
998 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
999 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
1000 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
1001 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
1002 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
1003 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
1005 return undef if $res->{mbps_rd
} && $res->{mbps
};
1006 return undef if $res->{mbps_wr
} && $res->{mbps
};
1008 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
1009 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
1010 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
1011 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
1012 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
1013 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
1015 return undef if $res->{iops_rd
} && $res->{iops
};
1016 return undef if $res->{iops_wr
} && $res->{iops
};
1019 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
1020 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
1021 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
1022 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
1023 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
1024 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
1028 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
1031 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1032 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1033 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1034 return undef if $res->{interface
} eq 'virtio';
1037 # rerror does not work with scsi drives
1038 if ($res->{rerror
}) {
1039 return undef if $res->{interface
} eq 'scsi';
1045 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);
1048 my ($vmid, $drive) = @_;
1051 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
1052 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1055 if ($drive->{size
}) {
1056 $opts .= ",size=" . &$format_size($drive->{size
});
1059 return "$drive->{file}$opts";
1063 my($fh, $noerr) = @_;
1066 my $SG_GET_VERSION_NUM = 0x2282;
1068 my $versionbuf = "\x00" x
8;
1069 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1071 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1074 my $version = unpack("I", $versionbuf);
1075 if ($version < 30000) {
1076 die "scsi generic interface too old\n" if !$noerr;
1080 my $buf = "\x00" x
36;
1081 my $sensebuf = "\x00" x
8;
1082 my $cmd = pack("C x3 C x1", 0x12, 36);
1084 # see /usr/include/scsi/sg.h
1085 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";
1087 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1088 length($sensebuf), 0, length($buf), $buf,
1089 $cmd, $sensebuf, 6000);
1091 $ret = ioctl($fh, $SG_IO, $packet);
1093 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1097 my @res = unpack($sg_io_hdr_t, $packet);
1098 if ($res[17] || $res[18]) {
1099 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1104 (my $byte0, my $byte1, $res->{vendor
},
1105 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1107 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1108 $res->{type
} = $byte0 & 31;
1116 my $fh = IO
::File-
>new("+<$path") || return undef;
1117 my $res = scsi_inquiry
($fh, 1);
1123 sub machine_type_is_q35
{
1126 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1129 sub print_tabletdevice_full
{
1132 my $q35 = machine_type_is_q35
($conf);
1134 # we use uhci for old VMs because tablet driver was buggy in older qemu
1135 my $usbbus = $q35 ?
"ehci" : "uhci";
1137 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1140 sub print_drivedevice_full
{
1141 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1146 if ($drive->{interface
} eq 'virtio') {
1147 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1148 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1149 $device .= ",iothread=iothread0" if $conf->{iothread
};
1150 } elsif ($drive->{interface
} eq 'scsi') {
1151 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1152 my $controller = int($drive->{index} / $maxdev);
1153 my $unit = $drive->{index} % $maxdev;
1154 my $devicetype = 'hd';
1156 if (drive_is_cdrom
($drive)) {
1159 if ($drive->{file
} =~ m
|^/|) {
1160 $path = $drive->{file
};
1162 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1165 if($path =~ m/^iscsi\:\/\
//){
1166 $devicetype = 'generic';
1168 if (my $info = path_is_scsi
($path)) {
1169 if ($info->{type
} == 0) {
1170 $devicetype = 'block';
1171 } elsif ($info->{type
} == 1) { # tape
1172 $devicetype = 'generic';
1178 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1179 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1181 $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}";
1184 } elsif ($drive->{interface
} eq 'ide'){
1186 my $controller = int($drive->{index} / $maxdev);
1187 my $unit = $drive->{index} % $maxdev;
1188 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1190 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1191 } elsif ($drive->{interface
} eq 'sata'){
1192 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1193 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1194 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1195 } elsif ($drive->{interface
} eq 'usb') {
1197 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1199 die "unsupported interface type";
1202 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1207 sub get_initiator_name
{
1210 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1211 while (defined(my $line = <$fh>)) {
1212 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1221 sub print_drive_full
{
1222 my ($storecfg, $vmid, $drive) = @_;
1225 foreach my $o (@qemu_drive_options) {
1226 next if $o eq 'bootindex';
1227 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1230 foreach my $o (qw(bps bps_rd bps_wr)) {
1231 my $v = $drive->{"m$o"};
1232 $opts .= ",$o=" . int($v*1024*1024) if $v;
1235 # use linux-aio by default (qemu default is threads)
1236 $opts .= ",aio=native" if !$drive->{aio
};
1239 my $volid = $drive->{file
};
1240 if (drive_is_cdrom
($drive)) {
1241 $path = get_iso_path
($storecfg, $vmid, $volid);
1243 if ($volid =~ m
|^/|) {
1246 $path = PVE
::Storage
::path
($storecfg, $volid);
1250 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1252 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1253 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1255 my $pathinfo = $path ?
"file=$path," : '';
1257 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1260 sub print_netdevice_full
{
1261 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1263 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1265 my $device = $net->{model
};
1266 if ($net->{model
} eq 'virtio') {
1267 $device = 'virtio-net-pci';
1270 my $pciaddr = print_pci_addr
("$netid", $bridges);
1271 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1272 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1273 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1274 my $vectors = $net->{queues
} * 2 + 2;
1275 $tmpstr .= ",vectors=$vectors,mq=on";
1277 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1281 sub print_netdev_full
{
1282 my ($vmid, $conf, $net, $netid) = @_;
1285 if ($netid =~ m/^net(\d+)$/) {
1289 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1291 my $ifname = "tap${vmid}i$i";
1293 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1294 die "interface name '$ifname' is too long (max 15 character)\n"
1295 if length($ifname) >= 16;
1297 my $vhostparam = '';
1298 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1300 my $vmname = $conf->{name
} || "vm$vmid";
1304 if ($net->{bridge
}) {
1305 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1307 $netdev = "type=user,id=$netid,hostname=$vmname";
1310 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1315 sub drive_is_cdrom
{
1318 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1327 foreach my $kvp (split(/,/, $data)) {
1329 if ($kvp =~ m/^memory=(\S+)$/) {
1330 $res->{memory
} = $1;
1331 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1332 $res->{policy
} = $1;
1333 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1334 $res->{cpus
}->{start
} = $1;
1335 $res->{cpus
}->{end
} = $3;
1336 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1337 $res->{hostnodes
}->{start
} = $1;
1338 $res->{hostnodes
}->{end
} = $3;
1350 return undef if !$value;
1353 my @list = split(/,/, $value);
1357 foreach my $kv (@list) {
1359 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1362 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1365 my $pcidevices = lspci
($2);
1366 $res->{pciid
} = $pcidevices->{$2};
1368 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1369 $res->{driver
} = $1;
1370 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1371 $res->{rombar
} = $1;
1372 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1373 $res->{'x-vga'} = $1;
1374 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1375 $res->{pcie
} = 1 if $1 == 1;
1377 warn "unknown hostpci setting '$kv'\n";
1381 return undef if !$found;
1386 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1392 foreach my $kvp (split(/,/, $data)) {
1394 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1396 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1397 $res->{model
} = $model;
1398 $res->{macaddr
} = $mac;
1399 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1400 $res->{bridge
} = $1;
1401 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1402 $res->{queues
} = $1;
1403 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1405 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1407 } elsif ($kvp =~ m/^firewall=([01])$/) {
1408 $res->{firewall
} = $1;
1409 } elsif ($kvp =~ m/^link_down=([01])$/) {
1410 $res->{link_down
} = $1;
1417 return undef if !$res->{model
};
1425 my $res = "$net->{model}";
1426 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1427 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1428 $res .= ",rate=$net->{rate}" if $net->{rate
};
1429 $res .= ",tag=$net->{tag}" if $net->{tag
};
1430 $res .= ",firewall=1" if $net->{firewall
};
1431 $res .= ",link_down=1" if $net->{link_down
};
1436 sub add_random_macs
{
1437 my ($settings) = @_;
1439 foreach my $opt (keys %$settings) {
1440 next if $opt !~ m/^net(\d+)$/;
1441 my $net = parse_net
($settings->{$opt});
1443 $settings->{$opt} = print_net
($net);
1447 sub add_unused_volume
{
1448 my ($config, $volid) = @_;
1451 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1452 my $test = "unused$ind";
1453 if (my $vid = $config->{$test}) {
1454 return if $vid eq $volid; # do not add duplicates
1460 die "To many unused volume - please delete them first.\n" if !$key;
1462 $config->{$key} = $volid;
1467 sub vm_is_volid_owner
{
1468 my ($storecfg, $vmid, $volid) = @_;
1470 if ($volid !~ m
|^/|) {
1472 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1473 if ($owner && ($owner == $vmid)) {
1481 sub vmconfig_delete_pending_option
{
1482 my ($conf, $key) = @_;
1484 delete $conf->{pending
}->{$key};
1485 my $pending_delete_hash = { $key => 1 };
1486 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1487 $pending_delete_hash->{$opt} = 1;
1489 $conf->{pending
}->{delete} = join(',', keys %$pending_delete_hash);
1492 sub vmconfig_undelete_pending_option
{
1493 my ($conf, $key) = @_;
1495 my $pending_delete_hash = {};
1496 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1497 $pending_delete_hash->{$opt} = 1;
1499 delete $pending_delete_hash->{$key};
1501 my @keylist = keys %$pending_delete_hash;
1502 if (scalar(@keylist)) {
1503 $conf->{pending
}->{delete} = join(',', @keylist);
1505 delete $conf->{pending
}->{delete};
1509 sub vmconfig_register_unused_drive
{
1510 my ($storecfg, $vmid, $conf, $drive) = @_;
1512 if (!drive_is_cdrom
($drive)) {
1513 my $volid = $drive->{file
};
1514 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1515 add_unused_volume
($conf, $volid, $vmid);
1520 sub vmconfig_cleanup_pending
{
1523 # remove pending changes when nothing changed
1525 foreach my $opt (keys %{$conf->{pending
}}) {
1526 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1528 delete $conf->{pending
}->{$opt};
1532 # remove delete if option is not set
1533 my $pending_delete_hash = {};
1534 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1535 if (defined($conf->{$opt})) {
1536 $pending_delete_hash->{$opt} = 1;
1542 my @keylist = keys %$pending_delete_hash;
1543 if (scalar(@keylist)) {
1544 $conf->{pending
}->{delete} = join(',', @keylist);
1546 delete $conf->{pending
}->{delete};
1552 my $valid_smbios1_options = {
1553 manufacturer
=> '\S+',
1557 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1562 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1568 foreach my $kvp (split(/,/, $data)) {
1569 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1570 my ($k, $v) = split(/=/, $kvp);
1571 return undef if !defined($k) || !defined($v);
1572 return undef if !$valid_smbios1_options->{$k};
1573 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1584 foreach my $k (keys %$smbios1) {
1585 next if !defined($smbios1->{$k});
1586 next if !$valid_smbios1_options->{$k};
1587 $data .= ',' if $data;
1588 $data .= "$k=$smbios1->{$k}";
1593 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1594 sub verify_smbios1
{
1595 my ($value, $noerr) = @_;
1597 return $value if parse_smbios1
($value);
1599 return undef if $noerr;
1601 die "unable to parse smbios (type 1) options\n";
1604 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1605 sub verify_bootdisk
{
1606 my ($value, $noerr) = @_;
1608 return $value if valid_drivename
($value);
1610 return undef if $noerr;
1612 die "invalid boot disk '$value'\n";
1615 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1617 my ($value, $noerr) = @_;
1619 return $value if parse_numa
($value);
1621 return undef if $noerr;
1623 die "unable to parse numa options\n";
1626 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1628 my ($value, $noerr) = @_;
1630 return $value if parse_net
($value);
1632 return undef if $noerr;
1634 die "unable to parse network options\n";
1637 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1639 my ($value, $noerr) = @_;
1641 return $value if parse_drive
(undef, $value);
1643 return undef if $noerr;
1645 die "unable to parse drive options\n";
1648 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1649 sub verify_hostpci
{
1650 my ($value, $noerr) = @_;
1652 return $value if parse_hostpci
($value);
1654 return undef if $noerr;
1656 die "unable to parse pci id\n";
1659 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1660 sub verify_watchdog
{
1661 my ($value, $noerr) = @_;
1663 return $value if parse_watchdog
($value);
1665 return undef if $noerr;
1667 die "unable to parse watchdog options\n";
1670 sub parse_watchdog
{
1673 return undef if !$value;
1677 foreach my $p (split(/,/, $value)) {
1678 next if $p =~ m/^\s*$/;
1680 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1682 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1683 $res->{action
} = $2;
1692 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1693 sub verify_startup
{
1694 my ($value, $noerr) = @_;
1696 return $value if parse_startup
($value);
1698 return undef if $noerr;
1700 die "unable to parse startup options\n";
1706 return undef if !$value;
1710 foreach my $p (split(/,/, $value)) {
1711 next if $p =~ m/^\s*$/;
1713 if ($p =~ m/^(order=)?(\d+)$/) {
1715 } elsif ($p =~ m/^up=(\d+)$/) {
1717 } elsif ($p =~ m/^down=(\d+)$/) {
1727 sub parse_usb_device
{
1730 return undef if !$value;
1732 my @dl = split(/,/, $value);
1736 foreach my $v (@dl) {
1737 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1739 $res->{vendorid
} = $2;
1740 $res->{productid
} = $4;
1741 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1743 $res->{hostbus
} = $1;
1744 $res->{hostport
} = $2;
1745 } elsif ($v =~ m/^spice$/) {
1752 return undef if !$found;
1757 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1758 sub verify_usb_device
{
1759 my ($value, $noerr) = @_;
1761 return $value if parse_usb_device
($value);
1763 return undef if $noerr;
1765 die "unable to parse usb device\n";
1768 # add JSON properties for create and set function
1769 sub json_config_properties
{
1772 foreach my $opt (keys %$confdesc) {
1773 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1774 $prop->{$opt} = $confdesc->{$opt};
1781 my ($key, $value) = @_;
1783 die "unknown setting '$key'\n" if !$confdesc->{$key};
1785 my $type = $confdesc->{$key}->{type
};
1787 if (!defined($value)) {
1788 die "got undefined value\n";
1791 if ($value =~ m/[\n\r]/) {
1792 die "property contains a line feed\n";
1795 if ($type eq 'boolean') {
1796 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1797 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1798 die "type check ('boolean') failed - got '$value'\n";
1799 } elsif ($type eq 'integer') {
1800 return int($1) if $value =~ m/^(\d+)$/;
1801 die "type check ('integer') failed - got '$value'\n";
1802 } elsif ($type eq 'number') {
1803 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1804 die "type check ('number') failed - got '$value'\n";
1805 } elsif ($type eq 'string') {
1806 if (my $fmt = $confdesc->{$key}->{format
}) {
1807 if ($fmt eq 'pve-qm-drive') {
1808 # special case - we need to pass $key to parse_drive()
1809 my $drive = parse_drive
($key, $value);
1810 return $value if $drive;
1811 die "unable to parse drive options\n";
1813 PVE
::JSONSchema
::check_format
($fmt, $value);
1816 $value =~ s/^\"(.*)\"$/$1/;
1819 die "internal error"
1823 sub lock_config_full
{
1824 my ($vmid, $timeout, $code, @param) = @_;
1826 my $filename = config_file_lock
($vmid);
1828 my $res = lock_file
($filename, $timeout, $code, @param);
1835 sub lock_config_mode
{
1836 my ($vmid, $timeout, $shared, $code, @param) = @_;
1838 my $filename = config_file_lock
($vmid);
1840 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1848 my ($vmid, $code, @param) = @_;
1850 return lock_config_full
($vmid, 10, $code, @param);
1853 sub cfs_config_path
{
1854 my ($vmid, $node) = @_;
1856 $node = $nodename if !$node;
1857 return "nodes/$node/qemu-server/$vmid.conf";
1860 sub check_iommu_support
{
1861 #fixme : need to check IOMMU support
1862 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1870 my ($vmid, $node) = @_;
1872 my $cfspath = cfs_config_path
($vmid, $node);
1873 return "/etc/pve/$cfspath";
1876 sub config_file_lock
{
1879 return "$lock_dir/lock-$vmid.conf";
1885 my $conf = config_file
($vmid);
1886 utime undef, undef, $conf;
1890 my ($storecfg, $vmid, $keep_empty_config) = @_;
1892 my $conffile = config_file
($vmid);
1894 my $conf = load_config
($vmid);
1898 # only remove disks owned by this VM
1899 foreach_drive
($conf, sub {
1900 my ($ds, $drive) = @_;
1902 return if drive_is_cdrom
($drive);
1904 my $volid = $drive->{file
};
1906 return if !$volid || $volid =~ m
|^/|;
1908 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1909 return if !$path || !$owner || ($owner != $vmid);
1911 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1914 if ($keep_empty_config) {
1915 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1920 # also remove unused disk
1922 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1925 PVE
::Storage
::foreach_volid
($dl, sub {
1926 my ($volid, $sid, $volname, $d) = @_;
1927 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1937 my ($vmid, $node) = @_;
1939 my $cfspath = cfs_config_path
($vmid, $node);
1941 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1943 die "no such VM ('$vmid')\n" if !defined($conf);
1948 sub parse_vm_config
{
1949 my ($filename, $raw) = @_;
1951 return undef if !defined($raw);
1954 digest
=> Digest
::SHA
::sha1_hex
($raw),
1959 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1960 || die "got strange filename '$filename'";
1968 my @lines = split(/\n/, $raw);
1969 foreach my $line (@lines) {
1970 next if $line =~ m/^\s*$/;
1972 if ($line =~ m/^\[PENDING\]\s*$/i) {
1973 $section = 'pending';
1974 $conf->{description
} = $descr if $descr;
1976 $conf = $res->{$section} = {};
1979 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1981 $conf->{description
} = $descr if $descr;
1983 $conf = $res->{snapshots
}->{$section} = {};
1987 if ($line =~ m/^\#(.*)\s*$/) {
1988 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1992 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1993 $descr .= PVE
::Tools
::decode_text
($2);
1994 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1995 $conf->{snapstate
} = $1;
1996 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1999 $conf->{$key} = $value;
2000 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2002 if ($section eq 'pending') {
2003 $conf->{delete} = $value; # we parse this later
2005 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2007 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2010 eval { $value = check_type
($key, $value); };
2012 warn "vm $vmid - unable to parse value of '$key' - $@";
2014 my $fmt = $confdesc->{$key}->{format
};
2015 if ($fmt && $fmt eq 'pve-qm-drive') {
2016 my $v = parse_drive
($key, $value);
2017 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2018 $v->{file
} = $volid;
2019 $value = print_drive
($vmid, $v);
2021 warn "vm $vmid - unable to parse value of '$key'\n";
2026 if ($key eq 'cdrom') {
2027 $conf->{ide2
} = $value;
2029 $conf->{$key} = $value;
2035 $conf->{description
} = $descr if $descr;
2037 delete $res->{snapstate
}; # just to be sure
2042 sub write_vm_config
{
2043 my ($filename, $conf) = @_;
2045 delete $conf->{snapstate
}; # just to be sure
2047 if ($conf->{cdrom
}) {
2048 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2049 $conf->{ide2
} = $conf->{cdrom
};
2050 delete $conf->{cdrom
};
2053 # we do not use 'smp' any longer
2054 if ($conf->{sockets
}) {
2055 delete $conf->{smp
};
2056 } elsif ($conf->{smp
}) {
2057 $conf->{sockets
} = $conf->{smp
};
2058 delete $conf->{cores
};
2059 delete $conf->{smp
};
2062 my $used_volids = {};
2064 my $cleanup_config = sub {
2065 my ($cref, $pending, $snapname) = @_;
2067 foreach my $key (keys %$cref) {
2068 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2069 $key eq 'snapstate' || $key eq 'pending';
2070 my $value = $cref->{$key};
2071 if ($key eq 'delete') {
2072 die "propertry 'delete' is only allowed in [PENDING]\n"
2074 # fixme: check syntax?
2077 eval { $value = check_type
($key, $value); };
2078 die "unable to parse value of '$key' - $@" if $@;
2080 $cref->{$key} = $value;
2082 if (!$snapname && valid_drivename
($key)) {
2083 my $drive = parse_drive
($key, $value);
2084 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2089 &$cleanup_config($conf);
2091 &$cleanup_config($conf->{pending
}, 1);
2093 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2094 die "internal error" if $snapname eq 'pending';
2095 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2098 # remove 'unusedX' settings if we re-add a volume
2099 foreach my $key (keys %$conf) {
2100 my $value = $conf->{$key};
2101 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2102 delete $conf->{$key};
2106 my $generate_raw_config = sub {
2111 # add description as comment to top of file
2112 my $descr = $conf->{description
} || '';
2113 foreach my $cl (split(/\n/, $descr)) {
2114 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2117 foreach my $key (sort keys %$conf) {
2118 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2119 $raw .= "$key: $conf->{$key}\n";
2124 my $raw = &$generate_raw_config($conf);
2126 if (scalar(keys %{$conf->{pending
}})){
2127 $raw .= "\n[PENDING]\n";
2128 $raw .= &$generate_raw_config($conf->{pending
});
2131 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2132 $raw .= "\n[$snapname]\n";
2133 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2139 sub update_config_nolock
{
2140 my ($vmid, $conf, $skiplock) = @_;
2142 check_lock
($conf) if !$skiplock;
2144 my $cfspath = cfs_config_path
($vmid);
2146 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2150 my ($vmid, $conf, $skiplock) = @_;
2152 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2159 # we use static defaults from our JSON schema configuration
2160 foreach my $key (keys %$confdesc) {
2161 if (defined(my $default = $confdesc->{$key}->{default})) {
2162 $res->{$key} = $default;
2166 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2167 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2173 my $vmlist = PVE
::Cluster
::get_vmlist
();
2175 return $res if !$vmlist || !$vmlist->{ids
};
2176 my $ids = $vmlist->{ids
};
2178 foreach my $vmid (keys %$ids) {
2179 my $d = $ids->{$vmid};
2180 next if !$d->{node
} || $d->{node
} ne $nodename;
2181 next if !$d->{type
} || $d->{type
} ne 'qemu';
2182 $res->{$vmid}->{exists} = 1;
2187 # test if VM uses local resources (to prevent migration)
2188 sub check_local_resources
{
2189 my ($conf, $noerr) = @_;
2193 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2194 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2196 foreach my $k (keys %$conf) {
2197 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2198 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2201 die "VM uses local resources\n" if $loc_res && !$noerr;
2206 # check if used storages are available on all nodes (use by migrate)
2207 sub check_storage_availability
{
2208 my ($storecfg, $conf, $node) = @_;
2210 foreach_drive
($conf, sub {
2211 my ($ds, $drive) = @_;
2213 my $volid = $drive->{file
};
2216 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2219 # check if storage is available on both nodes
2220 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2221 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2225 # list nodes where all VM images are available (used by has_feature API)
2227 my ($conf, $storecfg) = @_;
2229 my $nodelist = PVE
::Cluster
::get_nodelist
();
2230 my $nodehash = { map { $_ => 1 } @$nodelist };
2231 my $nodename = PVE
::INotify
::nodename
();
2233 foreach_drive
($conf, sub {
2234 my ($ds, $drive) = @_;
2236 my $volid = $drive->{file
};
2239 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2241 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2242 if ($scfg->{disable
}) {
2244 } elsif (my $avail = $scfg->{nodes
}) {
2245 foreach my $node (keys %$nodehash) {
2246 delete $nodehash->{$node} if !$avail->{$node};
2248 } elsif (!$scfg->{shared
}) {
2249 foreach my $node (keys %$nodehash) {
2250 delete $nodehash->{$node} if $node ne $nodename
2262 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2266 my ($pidfile, $pid) = @_;
2268 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2272 return undef if !$line;
2273 my @param = split(/\0/, $line);
2275 my $cmd = $param[0];
2276 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2278 for (my $i = 0; $i < scalar (@param); $i++) {
2281 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2282 my $p = $param[$i+1];
2283 return 1 if $p && ($p eq $pidfile);
2292 my ($vmid, $nocheck, $node) = @_;
2294 my $filename = config_file
($vmid, $node);
2296 die "unable to find configuration file for VM $vmid - no such machine\n"
2297 if !$nocheck && ! -f
$filename;
2299 my $pidfile = pidfile_name
($vmid);
2301 if (my $fd = IO
::File-
>new("<$pidfile")) {
2306 my $mtime = $st->mtime;
2307 if ($mtime > time()) {
2308 warn "file '$filename' modified in future\n";
2311 if ($line =~ m/^(\d+)$/) {
2313 if (check_cmdline
($pidfile, $pid)) {
2314 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2326 my $vzlist = config_list
();
2328 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2330 while (defined(my $de = $fd->read)) {
2331 next if $de !~ m/^(\d+)\.pid$/;
2333 next if !defined($vzlist->{$vmid});
2334 if (my $pid = check_running
($vmid)) {
2335 $vzlist->{$vmid}->{pid
} = $pid;
2343 my ($storecfg, $conf) = @_;
2345 my $bootdisk = $conf->{bootdisk
};
2346 return undef if !$bootdisk;
2347 return undef if !valid_drivename
($bootdisk);
2349 return undef if !$conf->{$bootdisk};
2351 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2352 return undef if !defined($drive);
2354 return undef if drive_is_cdrom
($drive);
2356 my $volid = $drive->{file
};
2357 return undef if !$volid;
2359 return $drive->{size
};
2362 my $last_proc_pid_stat;
2364 # get VM status information
2365 # This must be fast and should not block ($full == false)
2366 # We only query KVM using QMP if $full == true (this can be slow)
2368 my ($opt_vmid, $full) = @_;
2372 my $storecfg = PVE
::Storage
::config
();
2374 my $list = vzlist
();
2375 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2377 my $cpucount = $cpuinfo->{cpus
} || 1;
2379 foreach my $vmid (keys %$list) {
2380 next if $opt_vmid && ($vmid ne $opt_vmid);
2382 my $cfspath = cfs_config_path
($vmid);
2383 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2386 $d->{pid
} = $list->{$vmid}->{pid
};
2388 # fixme: better status?
2389 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2391 my $size = disksize
($storecfg, $conf);
2392 if (defined($size)) {
2393 $d->{disk
} = 0; # no info available
2394 $d->{maxdisk
} = $size;
2400 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2401 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2403 $d->{name
} = $conf->{name
} || "VM $vmid";
2404 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2406 if ($conf->{balloon
}) {
2407 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2408 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2419 $d->{diskwrite
} = 0;
2421 $d->{template
} = is_template
($conf);
2426 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2427 foreach my $dev (keys %$netdev) {
2428 next if $dev !~ m/^tap([1-9]\d*)i/;
2430 my $d = $res->{$vmid};
2433 $d->{netout
} += $netdev->{$dev}->{receive
};
2434 $d->{netin
} += $netdev->{$dev}->{transmit
};
2437 my $ctime = gettimeofday
;
2439 foreach my $vmid (keys %$list) {
2441 my $d = $res->{$vmid};
2442 my $pid = $d->{pid
};
2445 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2446 next if !$pstat; # not running
2448 my $used = $pstat->{utime} + $pstat->{stime
};
2450 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2452 if ($pstat->{vsize
}) {
2453 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2456 my $old = $last_proc_pid_stat->{$pid};
2458 $last_proc_pid_stat->{$pid} = {
2466 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2468 if ($dtime > 1000) {
2469 my $dutime = $used - $old->{used
};
2471 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2472 $last_proc_pid_stat->{$pid} = {
2478 $d->{cpu
} = $old->{cpu
};
2482 return $res if !$full;
2484 my $qmpclient = PVE
::QMPClient-
>new();
2486 my $ballooncb = sub {
2487 my ($vmid, $resp) = @_;
2489 my $info = $resp->{'return'};
2490 return if !$info->{max_mem
};
2492 my $d = $res->{$vmid};
2494 # use memory assigned to VM
2495 $d->{maxmem
} = $info->{max_mem
};
2496 $d->{balloon
} = $info->{actual
};
2498 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2499 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2500 $d->{freemem
} = $info->{free_mem
};
2505 my $blockstatscb = sub {
2506 my ($vmid, $resp) = @_;
2507 my $data = $resp->{'return'} || [];
2508 my $totalrdbytes = 0;
2509 my $totalwrbytes = 0;
2510 for my $blockstat (@$data) {
2511 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2512 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2514 $res->{$vmid}->{diskread
} = $totalrdbytes;
2515 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2518 my $statuscb = sub {
2519 my ($vmid, $resp) = @_;
2521 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2522 # this fails if ballon driver is not loaded, so this must be
2523 # the last commnand (following command are aborted if this fails).
2524 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2526 my $status = 'unknown';
2527 if (!defined($status = $resp->{'return'}->{status
})) {
2528 warn "unable to get VM status\n";
2532 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2535 foreach my $vmid (keys %$list) {
2536 next if $opt_vmid && ($vmid ne $opt_vmid);
2537 next if !$res->{$vmid}->{pid
}; # not running
2538 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2541 $qmpclient->queue_execute(undef, 1);
2543 foreach my $vmid (keys %$list) {
2544 next if $opt_vmid && ($vmid ne $opt_vmid);
2545 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2552 my ($conf, $func) = @_;
2554 foreach my $ds (keys %$conf) {
2555 next if !valid_drivename
($ds);
2557 my $drive = parse_drive
($ds, $conf->{$ds});
2560 &$func($ds, $drive);
2565 my ($conf, $func) = @_;
2569 my $test_volid = sub {
2570 my ($volid, $is_cdrom) = @_;
2574 $volhash->{$volid} = $is_cdrom || 0;
2577 foreach_drive
($conf, sub {
2578 my ($ds, $drive) = @_;
2579 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2582 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2583 my $snap = $conf->{snapshots
}->{$snapname};
2584 &$test_volid($snap->{vmstate
}, 0);
2585 foreach_drive
($snap, sub {
2586 my ($ds, $drive) = @_;
2587 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2591 foreach my $volid (keys %$volhash) {
2592 &$func($volid, $volhash->{$volid});
2596 sub vga_conf_has_spice
{
2599 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2604 sub config_to_command
{
2605 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2608 my $globalFlags = [];
2609 my $machineFlags = [];
2615 my $kvmver = kvm_user_version
();
2616 my $vernum = 0; # unknown
2617 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2618 $vernum = $1*1000000+$2*1000;
2619 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2620 $vernum = $1*1000000+$2*1000+$3;
2623 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2625 my $have_ovz = -f
'/proc/vz/vestat';
2627 my $q35 = machine_type_is_q35
($conf);
2629 push @$cmd, '/usr/bin/kvm';
2631 push @$cmd, '-id', $vmid;
2635 my $qmpsocket = qmp_socket
($vmid);
2636 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2637 push @$cmd, '-mon', "chardev=qmp,mode=control";
2639 my $socket = vnc_socket
($vmid);
2640 push @$cmd, '-vnc', "unix:$socket,x509,password";
2642 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2644 push @$cmd, '-daemonize';
2646 if ($conf->{smbios1
}) {
2647 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2650 push @$cmd, '-object', "iothread,id=iothread0" if $conf->{iothread
};
2653 # the q35 chipset support native usb2, so we enable usb controller
2654 # by default for this machine type
2655 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2657 $pciaddr = print_pci_addr
("piix3", $bridges);
2658 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2661 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2662 next if !$conf->{"usb$i"};
2665 # include usb device config
2666 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2669 my $vga = $conf->{vga
};
2671 my $qxlnum = vga_conf_has_spice
($vga);
2672 $vga = 'qxl' if $qxlnum;
2675 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2676 $conf->{ostype
} eq 'win7' ||
2677 $conf->{ostype
} eq 'w2k8')) {
2684 # enable absolute mouse coordinates (needed by vnc)
2686 if (defined($conf->{tablet
})) {
2687 $tablet = $conf->{tablet
};
2689 $tablet = $defaults->{tablet
};
2690 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2691 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2694 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2697 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2698 my $d = parse_hostpci
($conf->{"hostpci$i"});
2701 my $pcie = $d->{pcie
};
2703 die "q35 machine model is not enabled" if !$q35;
2704 $pciaddr = print_pcie_addr
("hostpci$i");
2706 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2709 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2710 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2711 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2712 if ($xvga && $xvga ne '') {
2713 push @$cpuFlags, 'kvm=off';
2716 $driver = "vfio-pci" if $xvga ne '';
2717 my $pcidevices = $d->{pciid
};
2718 my $multifunction = 1 if @$pcidevices > 1;
2721 foreach my $pcidevice (@$pcidevices) {
2723 my $id = "hostpci$i";
2724 $id .= ".$j" if $multifunction;
2725 my $addr = $pciaddr;
2726 $addr .= ".$j" if $multifunction;
2727 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2730 $devicestr .= "$rombar$xvga";
2731 $devicestr .= ",multifunction=on" if $multifunction;
2734 push @$devices, '-device', $devicestr;
2740 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2741 my $d = parse_usb_device
($conf->{"usb$i"});
2743 if ($d->{vendorid
} && $d->{productid
}) {
2744 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2745 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2746 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2747 } elsif ($d->{spice
}) {
2748 # usb redir support for spice
2749 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2750 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2755 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2756 if (my $path = $conf->{"serial$i"}) {
2757 if ($path eq 'socket') {
2758 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2759 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2760 push @$devices, '-device', "isa-serial,chardev=serial$i";
2762 die "no such serial device\n" if ! -c
$path;
2763 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2764 push @$devices, '-device', "isa-serial,chardev=serial$i";
2770 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2771 if (my $path = $conf->{"parallel$i"}) {
2772 die "no such parallel device\n" if ! -c
$path;
2773 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2774 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2775 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2779 my $vmname = $conf->{name
} || "vm$vmid";
2781 push @$cmd, '-name', $vmname;
2784 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2785 $sockets = $conf->{sockets
} if $conf->{sockets
};
2787 my $cores = $conf->{cores
} || 1;
2789 my $maxcpus = $sockets * $cores;
2791 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2793 my $allowed_vcpus = $cpuinfo->{cpus
};
2795 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2796 if ($allowed_vcpus < $maxcpus);
2798 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2800 push @$cmd, '-nodefaults';
2802 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2804 my $bootindex_hash = {};
2806 foreach my $o (split(//, $bootorder)) {
2807 $bootindex_hash->{$o} = $i*100;
2811 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2813 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2815 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2817 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2820 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2822 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2823 my $useLocaltime = $conf->{localtime};
2825 if (my $ost = $conf->{ostype
}) {
2826 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2828 if ($ost =~ m/^w/) { # windows
2829 $useLocaltime = 1 if !defined($conf->{localtime});
2831 # use time drift fix when acpi is enabled
2832 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2833 $tdf = 1 if !defined($conf->{tdf
});
2837 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2839 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2840 push @$cmd, '-no-hpet';
2841 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2842 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2845 if ($ost eq 'win7' || $ost eq 'win8') {
2846 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2850 push @$rtcFlags, 'driftfix=slew' if $tdf;
2853 push @$machineFlags, 'accel=tcg';
2855 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2858 my $machine_type = $forcemachine || $conf->{machine
};
2859 if ($machine_type) {
2860 push @$machineFlags, "type=${machine_type}";
2863 if ($conf->{startdate
}) {
2864 push @$rtcFlags, "base=$conf->{startdate}";
2865 } elsif ($useLocaltime) {
2866 push @$rtcFlags, 'base=localtime';
2869 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2870 $cpu = $conf->{cpu
} if $conf->{cpu
};
2872 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2874 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2876 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2878 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2880 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2882 # Note: enforce needs kernel 3.10, so we do not use it for now
2883 # push @$cmd, '-cpu', "$cpu,enforce";
2884 push @$cmd, '-cpu', $cpu;
2886 my $memory = $conf->{memory
} || $defaults->{memory
};
2887 push @$cmd, '-m', $memory;
2889 if ($conf->{numa
}) {
2891 my $numa_totalmemory = undef;
2892 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2893 next if !$conf->{"numa$i"};
2894 my $numa = parse_numa
($conf->{"numa$i"});
2897 die "missing numa node$i memory value\n" if !$numa->{memory
};
2898 my $numa_memory = $numa->{memory
};
2899 $numa_totalmemory += $numa_memory;
2900 my $numa_object = "memory-backend-ram,id=ram-node$i,size=$numa_memory"."M";
2903 my $cpus_start = $numa->{cpus
}->{start
};
2904 die "missing numa node$i cpus\n" if !defined($cpus_start);
2905 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2906 my $cpus = $cpus_start;
2907 if (defined($cpus_end)) {
2908 $cpus .= "-$cpus_end";
2909 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2913 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2914 if (defined($hostnodes_start)) {
2915 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2916 my $hostnodes = $hostnodes_start;
2917 if (defined($hostnodes_end)) {
2918 $hostnodes .= "-$hostnodes_end";
2919 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2922 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2923 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2924 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2928 my $policy = $numa->{policy
};
2929 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2930 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2933 push @$cmd, '-object', $numa_object;
2934 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2937 die "total memory for NUMA nodes must be equal to vm memory\n"
2938 if $numa_totalmemory && $numa_totalmemory != $memory;
2940 #if no custom tology, we split memory and cores across numa nodes
2941 if(!$numa_totalmemory) {
2943 my $numa_memory = ($memory / $sockets) . "M";
2945 for (my $i = 0; $i < $sockets; $i++) {
2947 my $cpustart = ($cores * $i);
2948 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2949 my $cpus = $cpustart;
2950 $cpus .= "-$cpuend" if $cpuend;
2952 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2953 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2958 push @$cmd, '-S' if $conf->{freeze
};
2960 # set keyboard layout
2961 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2962 push @$cmd, '-k', $kb if $kb;
2965 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2966 #push @$cmd, '-soundhw', 'es1370';
2967 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2969 if($conf->{agent
}) {
2970 my $qgasocket = qmp_socket
($vmid, 1);
2971 my $pciaddr = print_pci_addr
("qga0", $bridges);
2972 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2973 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2974 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2981 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2982 for(my $i = 1; $i < $qxlnum; $i++){
2983 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2984 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2987 # assume other OS works like Linux
2988 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2989 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2993 my $pciaddr = print_pci_addr
("spice", $bridges);
2995 $spice_port = PVE
::Tools
::next_spice_port
();
2997 push @$devices, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2999 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3000 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3001 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3004 # enable balloon by default, unless explicitly disabled
3005 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3006 $pciaddr = print_pci_addr
("balloon0", $bridges);
3007 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3010 if ($conf->{watchdog
}) {
3011 my $wdopts = parse_watchdog
($conf->{watchdog
});
3012 $pciaddr = print_pci_addr
("watchdog", $bridges);
3013 my $watchdog = $wdopts->{model
} || 'i6300esb';
3014 push @$devices, '-device', "$watchdog$pciaddr";
3015 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3019 my $scsicontroller = {};
3020 my $ahcicontroller = {};
3021 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3023 # Add iscsi initiator name if available
3024 if (my $initiator = get_initiator_name
()) {
3025 push @$devices, '-iscsi', "initiator-name=$initiator";
3028 foreach_drive
($conf, sub {
3029 my ($ds, $drive) = @_;
3031 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3032 push @$vollist, $drive->{file
};
3035 $use_virtio = 1 if $ds =~ m/^virtio/;
3037 if (drive_is_cdrom
($drive)) {
3038 if ($bootindex_hash->{d
}) {
3039 $drive->{bootindex
} = $bootindex_hash->{d
};
3040 $bootindex_hash->{d
} += 1;
3043 if ($bootindex_hash->{c
}) {
3044 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3045 $bootindex_hash->{c
} += 1;
3049 if ($drive->{interface
} eq 'scsi') {
3051 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
3052 my $controller = int($drive->{index} / $maxdev);
3053 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
3054 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
3055 $scsicontroller->{$controller}=1;
3058 if ($drive->{interface
} eq 'sata') {
3059 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3060 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3061 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3062 $ahcicontroller->{$controller}=1;
3065 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3066 push @$devices, '-drive',$drive_cmd;
3067 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3070 for (my $i = 0; $i < $MAX_NETS; $i++) {
3071 next if !$conf->{"net$i"};
3072 my $d = parse_net
($conf->{"net$i"});
3075 $use_virtio = 1 if $d->{model
} eq 'virtio';
3077 if ($bootindex_hash->{n
}) {
3078 $d->{bootindex
} = $bootindex_hash->{n
};
3079 $bootindex_hash->{n
} += 1;
3082 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3083 push @$devices, '-netdev', $netdevfull;
3085 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3086 push @$devices, '-device', $netdevicefull;
3091 while (my ($k, $v) = each %$bridges) {
3092 $pciaddr = print_pci_addr
("pci.$k");
3093 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3097 # hack: virtio with fairsched is unreliable, so we do not use fairsched
3098 # when the VM uses virtio devices.
3099 if (!$use_virtio && $have_ovz) {
3101 my $cpuunits = defined($conf->{cpuunits
}) ?
3102 $conf->{cpuunits
} : $defaults->{cpuunits
};
3104 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
3106 # fixme: cpulimit is currently ignored
3107 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
3111 if ($conf->{args
}) {
3112 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3116 push @$cmd, @$devices;
3117 push @$cmd, '-rtc', join(',', @$rtcFlags)
3118 if scalar(@$rtcFlags);
3119 push @$cmd, '-machine', join(',', @$machineFlags)
3120 if scalar(@$machineFlags);
3121 push @$cmd, '-global', join(',', @$globalFlags)
3122 if scalar(@$globalFlags);
3124 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3129 return "${var_run_tmpdir}/$vmid.vnc";
3135 my $res = vm_mon_cmd
($vmid, 'query-spice');
3137 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3141 my ($vmid, $qga) = @_;
3142 my $sockettype = $qga ?
'qga' : 'qmp';
3143 return "${var_run_tmpdir}/$vmid.$sockettype";
3148 return "${var_run_tmpdir}/$vmid.pid";
3151 sub vm_devices_list
{
3154 my $res = vm_mon_cmd
($vmid, 'query-pci');
3156 foreach my $pcibus (@$res) {
3157 foreach my $device (@{$pcibus->{devices
}}) {
3158 next if !$device->{'qdev_id'};
3159 $devices->{$device->{'qdev_id'}} = 1;
3163 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3164 foreach my $block (@$resblock) {
3165 if($block->{device
} =~ m/^drive-(\S+)/){
3170 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3171 foreach my $mice (@$resmice) {
3172 if ($mice->{name
} eq 'QEMU HID Tablet') {
3173 $devices->{tablet
} = 1;
3182 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3184 my $q35 = machine_type_is_q35
($conf);
3186 my $devices_list = vm_devices_list
($vmid);
3187 return 1 if defined($devices_list->{$deviceid});
3189 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3191 if ($deviceid eq 'tablet') {
3193 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3195 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3197 qemu_driveadd
($storecfg, $vmid, $device);
3198 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3200 qemu_deviceadd
($vmid, $devicefull);
3201 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3203 eval { qemu_drivedel
($vmid, $deviceid); };
3208 } elsif ($deviceid =~ m/^(scsihw)(\d+)$/) {
3210 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3211 my $pciaddr = print_pci_addr
($deviceid);
3212 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
3214 qemu_deviceadd
($vmid, $devicefull);
3215 qemu_deviceaddverify
($vmid, $deviceid);
3217 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3219 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3220 qemu_driveadd
($storecfg, $vmid, $device);
3222 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3223 eval { qemu_deviceadd
($vmid, $devicefull); };
3225 eval { qemu_drivedel
($vmid, $deviceid); };
3230 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3232 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3233 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3234 qemu_deviceadd
($vmid, $netdevicefull);
3235 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3237 eval { qemu_netdevdel
($vmid, $deviceid); };
3242 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3245 my $pciaddr = print_pci_addr
($deviceid);
3246 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3248 qemu_deviceadd
($vmid, $devicefull);
3249 qemu_deviceaddverify
($vmid, $deviceid);
3252 die "can't hotplug device '$deviceid'\n";
3258 # fixme: this should raise exceptions on error!
3259 sub vm_deviceunplug
{
3260 my ($vmid, $conf, $deviceid) = @_;
3262 my $devices_list = vm_devices_list
($vmid);
3263 return 1 if !defined($devices_list->{$deviceid});
3265 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3267 if ($deviceid eq 'tablet') {
3269 qemu_devicedel
($vmid, $deviceid);
3271 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3273 qemu_devicedel
($vmid, $deviceid);
3274 qemu_devicedelverify
($vmid, $deviceid);
3275 qemu_drivedel
($vmid, $deviceid);
3277 } elsif ($deviceid =~ m/^(lsi)(\d+)$/) {
3279 qemu_devicedel
($vmid, $deviceid);
3281 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3283 qemu_devicedel
($vmid, $deviceid);
3284 qemu_drivedel
($vmid, $deviceid);
3286 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3288 qemu_devicedel
($vmid, $deviceid);
3289 qemu_devicedelverify
($vmid, $deviceid);
3290 qemu_netdevdel
($vmid, $deviceid);
3293 die "can't unplug device '$deviceid'\n";
3299 sub qemu_deviceadd
{
3300 my ($vmid, $devicefull) = @_;
3302 $devicefull = "driver=".$devicefull;
3303 my %options = split(/[=,]/, $devicefull);
3305 vm_mon_cmd
($vmid, "device_add" , %options);
3308 sub qemu_devicedel
{
3309 my ($vmid, $deviceid) = @_;
3311 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3315 my ($storecfg, $vmid, $device) = @_;
3317 my $drive = print_drive_full
($storecfg, $vmid, $device);
3318 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
3320 # If the command succeeds qemu prints: "OK"
3321 return 1 if $ret =~ m/OK/s;
3323 die "adding drive failed: $ret\n";
3327 my($vmid, $deviceid) = @_;
3329 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
3332 return 1 if $ret eq "";
3334 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3335 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3337 die "deleting drive $deviceid failed : $ret\n";
3340 sub qemu_deviceaddverify
{
3341 my ($vmid, $deviceid) = @_;
3343 for (my $i = 0; $i <= 5; $i++) {
3344 my $devices_list = vm_devices_list
($vmid);
3345 return 1 if defined($devices_list->{$deviceid});
3349 die "error on hotplug device '$deviceid'\n";
3353 sub qemu_devicedelverify
{
3354 my ($vmid, $deviceid) = @_;
3356 # need to verify that the device is correctly removed as device_del
3357 # is async and empty return is not reliable
3359 for (my $i = 0; $i <= 5; $i++) {
3360 my $devices_list = vm_devices_list
($vmid);
3361 return 1 if !defined($devices_list->{$deviceid});
3365 die "error on hot-unplugging device '$deviceid'\n";
3368 sub qemu_findorcreatescsihw
{
3369 my ($storecfg, $conf, $vmid, $device) = @_;
3371 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
3372 my $controller = int($device->{index} / $maxdev);
3373 my $scsihwid="scsihw$controller";
3374 my $devices_list = vm_devices_list
($vmid);
3376 if(!defined($devices_list->{$scsihwid})) {
3377 vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
3383 sub qemu_add_pci_bridge
{
3384 my ($storecfg, $conf, $vmid, $device) = @_;
3390 print_pci_addr
($device, $bridges);
3392 while (my ($k, $v) = each %$bridges) {
3395 return 1 if !defined($bridgeid) || $bridgeid < 1;
3397 my $bridge = "pci.$bridgeid";
3398 my $devices_list = vm_devices_list
($vmid);
3400 if (!defined($devices_list->{$bridge})) {
3401 vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
3407 sub qemu_set_link_status
{
3408 my ($vmid, $device, $up) = @_;
3410 vm_mon_cmd
($vmid, "set_link", name
=> $device,
3411 up
=> $up ? JSON
::true
: JSON
::false
);
3414 sub qemu_netdevadd
{
3415 my ($vmid, $conf, $device, $deviceid) = @_;
3417 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
3418 my %options = split(/[=,]/, $netdev);
3420 vm_mon_cmd
($vmid, "netdev_add", %options);
3424 sub qemu_netdevdel
{
3425 my ($vmid, $deviceid) = @_;
3427 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
3430 sub qemu_cpu_hotplug
{
3431 my ($vmid, $conf, $vcpus) = @_;
3434 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3435 $sockets = $conf->{sockets
} if $conf->{sockets
};
3436 my $cores = $conf->{cores
} || 1;
3437 my $maxcpus = $sockets * $cores;
3439 $vcpus = $maxcpus if !$vcpus;
3441 die "you can't add more vcpus than maxcpus\n"
3442 if $vcpus > $maxcpus;
3444 my $currentvcpus = $conf->{vcpus
} || $maxcpus;
3445 die "online cpu unplug is not yet possible\n"
3446 if $vcpus < $currentvcpus;
3448 my $currentrunningvcpus = vm_mon_cmd
($vmid, "query-cpus");
3449 die "vcpus in running vm is different than configuration\n"
3450 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3452 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3453 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
3457 sub qemu_block_set_io_throttle
{
3458 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3460 return if !check_running
($vmid) ;
3462 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));
3466 # old code, only used to shutdown old VM after update
3468 my ($fh, $timeout) = @_;
3470 my $sel = new IO
::Select
;
3477 while (scalar (@ready = $sel->can_read($timeout))) {
3479 if ($count = $fh->sysread($buf, 8192)) {
3480 if ($buf =~ /^(.*)\(qemu\) $/s) {
3487 if (!defined($count)) {
3494 die "monitor read timeout\n" if !scalar(@ready);
3499 # old code, only used to shutdown old VM after update
3500 sub vm_monitor_command
{
3501 my ($vmid, $cmdstr, $nocheck) = @_;
3506 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3508 my $sname = "${var_run_tmpdir}/$vmid.mon";
3510 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3511 die "unable to connect to VM $vmid socket - $!\n";
3515 # hack: migrate sometime blocks the monitor (when migrate_downtime
3517 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3518 $timeout = 60*60; # 1 hour
3522 my $data = __read_avail
($sock, $timeout);
3524 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3525 die "got unexpected qemu monitor banner\n";
3528 my $sel = new IO
::Select
;
3531 if (!scalar(my @ready = $sel->can_write($timeout))) {
3532 die "monitor write error - timeout";
3535 my $fullcmd = "$cmdstr\r";
3537 # syslog('info', "VM $vmid monitor command: $cmdstr");
3540 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3541 die "monitor write error - $!";
3544 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3548 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3549 $timeout = 60*60; # 1 hour
3550 } elsif ($cmdstr =~ m/^(eject|change)/) {
3551 $timeout = 60; # note: cdrom mount command is slow
3553 if ($res = __read_avail
($sock, $timeout)) {
3555 my @lines = split("\r?\n", $res);
3557 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3559 $res = join("\n", @lines);
3567 syslog
("err", "VM $vmid monitor command failed - $err");
3574 sub qemu_block_resize
{
3575 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3577 my $running = check_running
($vmid);
3579 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3581 return if !$running;
3583 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3587 sub qemu_volume_snapshot
{
3588 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3590 my $running = check_running
($vmid);
3592 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3594 return if !$running;
3596 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3600 sub qemu_volume_snapshot_delete
{
3601 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3603 my $running = check_running
($vmid);
3605 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3607 return if !$running;
3609 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3612 sub set_migration_caps
{
3618 "auto-converge" => 1,
3620 "x-rdma-pin-all" => 0,
3624 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3626 for my $supported_capability (@$supported_capabilities) {
3628 capability
=> $supported_capability->{capability
},
3629 state => $enabled_cap->{$supported_capability->{capability
}} ? JSON
::true
: JSON
::false
,
3633 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3636 my $fast_plug_option = {
3644 # hotplug changes in [PENDING]
3645 # $selection hash can be used to only apply specified options, for
3646 # example: { cores => 1 } (only apply changed 'cores')
3647 # $errors ref is used to return error messages
3648 sub vmconfig_hotplug_pending
{
3649 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3651 my $defaults = load_defaults
();
3653 # commit values which do not have any impact on running VM first
3654 # Note: those option cannot raise errors, we we do not care about
3655 # $selection and always apply them.
3657 my $add_error = sub {
3658 my ($opt, $msg) = @_;
3659 $errors->{$opt} = "hotplug problem - $msg";
3663 foreach my $opt (keys %{$conf->{pending
}}) { # add/change
3664 if ($fast_plug_option->{$opt}) {
3665 $conf->{$opt} = $conf->{pending
}->{$opt};
3666 delete $conf->{pending
}->{$opt};
3672 update_config_nolock
($vmid, $conf, 1);
3673 $conf = load_config
($vmid); # update/reload
3676 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
3678 my @delete = PVE
::Tools
::split_list
($conf->{pending
}->{delete});
3679 foreach my $opt (@delete) {
3680 next if $selection && !$selection->{$opt};
3682 if ($opt eq 'tablet') {
3683 die "skip\n" if !$hotplug_features->{usb
};
3684 if ($defaults->{tablet
}) {
3685 vm_deviceplug
($storecfg, $conf, $vmid, $opt);
3687 vm_deviceunplug
($vmid, $conf, $opt);
3689 } elsif ($opt eq 'vcpus') {
3690 die "skip\n" if !$hotplug_features->{cpu
};
3691 qemu_cpu_hotplug
($vmid, $conf, undef);
3692 } elsif ($opt eq 'balloon') {
3693 # enable balloon device is not hotpluggable
3694 die "skip\n" if !defined($conf->{balloon
}) || $conf->{balloon
};
3695 } elsif ($fast_plug_option->{$opt}) {
3697 } elsif ($opt =~ m/^net(\d+)$/) {
3698 die "skip\n" if !$hotplug_features->{network
};
3699 vm_deviceunplug
($vmid, $conf, $opt);
3700 } elsif (valid_drivename
($opt)) {
3701 die "skip\n" if !$hotplug_features->{disk
} || $opt =~ m/(ide|sata)(\d+)/;
3702 vm_deviceunplug
($vmid, $conf, $opt);
3703 vmconfig_register_unused_drive
($storecfg, $vmid, $conf, parse_drive
($opt, $conf->{$opt}));
3709 &$add_error($opt, $err) if $err ne "skip\n";
3711 # save new config if hotplug was successful
3712 delete $conf->{$opt};
3713 vmconfig_undelete_pending_option
($conf, $opt);
3714 update_config_nolock
($vmid, $conf, 1);
3715 $conf = load_config
($vmid); # update/reload
3719 foreach my $opt (keys %{$conf->{pending
}}) {
3720 next if $selection && !$selection->{$opt};
3721 my $value = $conf->{pending
}->{$opt};
3723 if ($opt eq 'tablet') {
3724 die "skip\n" if !$hotplug_features->{usb
};
3726 vm_deviceplug
($storecfg, $conf, $vmid, $opt);
3727 } elsif ($value == 0) {
3728 vm_deviceunplug
($vmid, $conf, $opt);
3730 } elsif ($opt eq 'vcpus') {
3731 die "skip\n" if !$hotplug_features->{cpu
};
3732 qemu_cpu_hotplug
($vmid, $conf, $value);
3733 } elsif ($opt eq 'balloon') {
3734 # enable/disable balloning device is not hotpluggable
3735 my $old_balloon_enabled = !!(!defined($conf->{balloon
}) || $conf->{balloon
});
3736 my $new_balloon_enabled = !!(!defined($conf->{pending
}->{balloon
}) || $conf->{pending
}->{balloon
});
3737 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
3739 # allow manual ballooning if shares is set to zero
3740 if (!(defined($conf->{shares
}) && ($conf->{shares
} == 0))) {
3741 my $balloon = $conf->{pending
}->{balloon
} || $conf->{memory
} || $defaults->{memory
};
3742 vm_mon_cmd
($vmid, "balloon", value
=> $balloon*1024*1024);
3744 } elsif ($opt =~ m/^net(\d+)$/) {
3745 # some changes can be done without hotplug
3746 vmconfig_update_net
($storecfg, $conf, $hotplug_features->{network
},
3747 $vmid, $opt, $value);
3748 } elsif (valid_drivename
($opt)) {
3749 # some changes can be done without hotplug
3750 vmconfig_update_disk
($storecfg, $conf, $hotplug_features->{disk
},
3751 $vmid, $opt, $value, 1);
3753 die "skip\n"; # skip non-hot-pluggable options
3757 &$add_error($opt, $err) if $err ne "skip\n";
3759 # save new config if hotplug was successful
3760 $conf->{$opt} = $value;
3761 delete $conf->{pending
}->{$opt};
3762 update_config_nolock
($vmid, $conf, 1);
3763 $conf = load_config
($vmid); # update/reload
3768 sub vmconfig_apply_pending
{
3769 my ($vmid, $conf, $storecfg) = @_;
3773 my @delete = PVE
::Tools
::split_list
($conf->{pending
}->{delete});
3774 foreach my $opt (@delete) { # delete
3775 die "internal error" if $opt =~ m/^unused/;
3776 $conf = load_config
($vmid); # update/reload
3777 if (!defined($conf->{$opt})) {
3778 vmconfig_undelete_pending_option
($conf, $opt);
3779 update_config_nolock
($vmid, $conf, 1);
3780 } elsif (valid_drivename
($opt)) {
3781 vmconfig_register_unused_drive
($storecfg, $vmid, $conf, parse_drive
($opt, $conf->{$opt}));
3782 vmconfig_undelete_pending_option
($conf, $opt);
3783 delete $conf->{$opt};
3784 update_config_nolock
($vmid, $conf, 1);
3786 vmconfig_undelete_pending_option
($conf, $opt);
3787 delete $conf->{$opt};
3788 update_config_nolock
($vmid, $conf, 1);
3792 $conf = load_config
($vmid); # update/reload
3794 foreach my $opt (keys %{$conf->{pending
}}) { # add/change
3795 $conf = load_config
($vmid); # update/reload
3797 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending
}->{$opt})) {
3798 # skip if nothing changed
3799 } elsif (valid_drivename
($opt)) {
3800 vmconfig_register_unused_drive
($storecfg, $vmid, $conf, parse_drive
($opt, $conf->{$opt}))
3801 if defined($conf->{$opt});
3802 $conf->{$opt} = $conf->{pending
}->{$opt};
3804 $conf->{$opt} = $conf->{pending
}->{$opt};
3807 delete $conf->{pending
}->{$opt};
3808 update_config_nolock
($vmid, $conf, 1);
3812 my $safe_num_ne = sub {
3815 return 0 if !defined($a) && !defined($b);
3816 return 1 if !defined($a);
3817 return 1 if !defined($b);
3822 my $safe_string_ne = sub {
3825 return 0 if !defined($a) && !defined($b);
3826 return 1 if !defined($a);
3827 return 1 if !defined($b);
3832 sub vmconfig_update_net
{
3833 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
3835 my $newnet = parse_net
($value);
3837 if ($conf->{$opt}) {
3838 my $oldnet = parse_net
($conf->{$opt});
3840 if (&$safe_string_ne($oldnet->{model
}, $newnet->{model
}) ||
3841 &$safe_string_ne($oldnet->{macaddr
}, $newnet->{macaddr
}) ||
3842 &$safe_num_ne($oldnet->{queues
}, $newnet->{queues
}) ||
3843 !($newnet->{bridge
} && $oldnet->{bridge
})) { # bridge/nat mode change
3845 # for non online change, we try to hot-unplug
3846 die "skip\n" if !$hotplug;
3847 vm_deviceunplug
($vmid, $conf, $opt);
3850 die "internal error" if $opt !~ m/net(\d+)/;
3851 my $iface = "tap${vmid}i$1";
3853 if (&$safe_num_ne($oldnet->{rate
}, $newnet->{rate
})) {
3854 PVE
::Network
::tap_rate_limit
($iface, $newnet->{rate
});
3857 if (&$safe_string_ne($oldnet->{bridge
}, $newnet->{bridge
}) ||
3858 &$safe_num_ne($oldnet->{tag
}, $newnet->{tag
}) ||
3859 &$safe_num_ne($oldnet->{firewall
}, $newnet->{firewall
})) {
3860 PVE
::Network
::tap_unplug
($iface);
3861 PVE
::Network
::tap_plug
($iface, $newnet->{bridge
}, $newnet->{tag
}, $newnet->{firewall
});
3864 if (&$safe_string_ne($oldnet->{link_down
}, $newnet->{link_down
})) {
3865 qemu_set_link_status
($vmid, $opt, !$newnet->{link_down
});
3873 vm_deviceplug
($storecfg, $conf, $vmid, $opt, $newnet);
3879 sub vmconfig_update_disk
{
3880 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
3882 # fixme: do we need force?
3884 my $drive = parse_drive
($opt, $value);
3886 if ($conf->{$opt}) {
3888 if (my $old_drive = parse_drive
($opt, $conf->{$opt})) {
3890 my $media = $drive->{media
} || 'disk';
3891 my $oldmedia = $old_drive->{media
} || 'disk';
3892 die "unable to change media type\n" if $media ne $oldmedia;
3894 if (!drive_is_cdrom
($old_drive)) {
3896 if ($drive->{file
} ne $old_drive->{file
}) {
3898 die "skip\n" if !$hotplug;
3900 # unplug and register as unused
3901 vm_deviceunplug
($vmid, $conf, $opt);
3902 vmconfig_register_unused_drive
($storecfg, $vmid, $conf, $old_drive)
3905 # update existing disk
3907 # skip non hotpluggable value
3908 if (&$safe_num_ne($drive->{discard
}, $old_drive->{discard
}) ||
3909 &$safe_string_ne($drive->{cache
}, $old_drive->{cache
})) {
3914 if (&$safe_num_ne($drive->{mbps
}, $old_drive->{mbps
}) ||
3915 &$safe_num_ne($drive->{mbps_rd
}, $old_drive->{mbps_rd
}) ||
3916 &$safe_num_ne($drive->{mbps_wr
}, $old_drive->{mbps_wr
}) ||
3917 &$safe_num_ne($drive->{iops
}, $old_drive->{iops
}) ||
3918 &$safe_num_ne($drive->{iops_rd
}, $old_drive->{iops_rd
}) ||
3919 &$safe_num_ne($drive->{iops_wr
}, $old_drive->{iops_wr
}) ||
3920 &$safe_num_ne($drive->{mbps_max
}, $old_drive->{mbps_max
}) ||
3921 &$safe_num_ne($drive->{mbps_rd_max
}, $old_drive->{mbps_rd_max
}) ||
3922 &$safe_num_ne($drive->{mbps_wr_max
}, $old_drive->{mbps_wr_max
}) ||
3923 &$safe_num_ne($drive->{iops_max
}, $old_drive->{iops_max
}) ||
3924 &$safe_num_ne($drive->{iops_rd_max
}, $old_drive->{iops_rd_max
}) ||
3925 &$safe_num_ne($drive->{iops_wr_max
}, $old_drive->{iops_wr_max
})) {
3927 qemu_block_set_io_throttle
($vmid,"drive-$opt",
3928 ($drive->{mbps
} || 0)*1024*1024,
3929 ($drive->{mbps_rd
} || 0)*1024*1024,
3930 ($drive->{mbps_wr
} || 0)*1024*1024,
3931 $drive->{iops
} || 0,
3932 $drive->{iops_rd
} || 0,
3933 $drive->{iops_wr
} || 0,
3934 ($drive->{mbps_max
} || 0)*1024*1024,
3935 ($drive->{mbps_rd_max
} || 0)*1024*1024,
3936 ($drive->{mbps_wr_max
} || 0)*1024*1024,
3937 $drive->{iops_max
} || 0,
3938 $drive->{iops_rd_max
} || 0,
3939 $drive->{iops_wr_max
} || 0);
3949 if (drive_is_cdrom
($drive)) { # cdrom
3951 if ($drive->{file
} eq 'none') {
3952 vm_mon_cmd
($vmid, "eject",force
=> JSON
::true
,device
=> "drive-$opt");
3954 my $path = get_iso_path
($storecfg, $vmid, $drive->{file
});
3955 vm_mon_cmd
($vmid, "eject", force
=> JSON
::true
,device
=> "drive-$opt"); # force eject if locked
3956 vm_mon_cmd
($vmid, "change", device
=> "drive-$opt",target
=> "$path") if $path;
3960 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
3962 vm_deviceplug
($storecfg, $conf, $vmid, $opt, $drive);
3967 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3969 lock_config
($vmid, sub {
3970 my $conf = load_config
($vmid, $migratedfrom);
3972 die "you can't start a vm if it's a template\n" if is_template
($conf);
3974 check_lock
($conf) if !$skiplock;
3976 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3978 if (!$statefile && scalar(keys %{$conf->{pending
}})) {
3979 vmconfig_apply_pending
($vmid, $conf, $storecfg);
3980 $conf = load_config
($vmid); # update/reload
3983 my $defaults = load_defaults
();
3985 # set environment variable useful inside network script
3986 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3988 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3990 my $migrate_port = 0;
3993 if ($statefile eq 'tcp') {
3994 my $localip = "localhost";
3995 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3996 if ($datacenterconf->{migration_unsecure
}) {
3997 my $nodename = PVE
::INotify
::nodename
();
3998 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
4000 $migrate_port = PVE
::Tools
::next_migrate_port
();
4001 $migrate_uri = "tcp:${localip}:${migrate_port}";
4002 push @$cmd, '-incoming', $migrate_uri;
4005 push @$cmd, '-loadstate', $statefile;
4012 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4013 my $d = parse_hostpci
($conf->{"hostpci$i"});
4015 my $pcidevices = $d->{pciid
};
4016 foreach my $pcidevice (@$pcidevices) {
4017 my $pciid = $pcidevice->{id
}.".".$pcidevice->{function
};
4019 my $info = pci_device_info
("0000:$pciid");
4020 die "IOMMU not present\n" if !check_iommu_support
();
4021 die "no pci device info for device '$pciid'\n" if !$info;
4023 if ($d->{driver
} && $d->{driver
} eq "vfio") {
4024 die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio
($pciid);
4026 die "can't unbind/bind to stub pci device '$pciid'\n" if !pci_dev_bind_to_stub
($info);
4029 die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset
} and !pci_dev_reset
($info);
4033 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
4035 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
4038 die "start failed: $err" if $err;
4040 print "migration listens on $migrate_uri\n" if $migrate_uri;
4042 if ($statefile && $statefile ne 'tcp') {
4043 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
4047 if ($migratedfrom) {
4050 set_migration_caps
($vmid);
4055 print "spice listens on port $spice_port\n";
4056 if ($spice_ticket) {
4057 vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
4058 vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
4064 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
4065 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
4066 if $conf->{balloon
};
4067 vm_mon_cmd_nocheck
($vmid, 'qom-set',
4068 path
=> "machine/peripheral/balloon0",
4069 property
=> "guest-stats-polling-interval",
4073 foreach my $opt (keys %$conf) {
4074 next if $opt !~ m/^net\d+$/;
4075 my $nicconf = parse_net
($conf->{$opt});
4076 qemu_set_link_status
($vmid, $opt, 0) if $nicconf->{link_down
};
4083 my ($vmid, $execute, %params) = @_;
4085 my $cmd = { execute
=> $execute, arguments
=> \
%params };
4086 vm_qmp_command
($vmid, $cmd);
4089 sub vm_mon_cmd_nocheck
{
4090 my ($vmid, $execute, %params) = @_;
4092 my $cmd = { execute
=> $execute, arguments
=> \
%params };
4093 vm_qmp_command
($vmid, $cmd, 1);
4096 sub vm_qmp_command
{
4097 my ($vmid, $cmd, $nocheck) = @_;
4102 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
4103 $timeout = $cmd->{arguments
}->{timeout
};
4104 delete $cmd->{arguments
}->{timeout
};
4108 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
4109 my $sname = qmp_socket
($vmid);
4110 if (-e
$sname) { # test if VM is reasonambe new and supports qmp/qga
4111 my $qmpclient = PVE
::QMPClient-
>new();
4113 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4114 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
4115 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4116 if scalar(%{$cmd->{arguments
}});
4117 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
4119 die "unable to open monitor socket\n";
4123 syslog
("err", "VM $vmid qmp command failed - $err");
4130 sub vm_human_monitor_command
{
4131 my ($vmid, $cmdline) = @_;
4136 execute
=> 'human-monitor-command',
4137 arguments
=> { 'command-line' => $cmdline},
4140 return vm_qmp_command
($vmid, $cmd);
4143 sub vm_commandline
{
4144 my ($storecfg, $vmid) = @_;
4146 my $conf = load_config
($vmid);
4148 my $defaults = load_defaults
();
4150 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
4152 return join(' ', @$cmd);
4156 my ($vmid, $skiplock) = @_;
4158 lock_config
($vmid, sub {
4160 my $conf = load_config
($vmid);
4162 check_lock
($conf) if !$skiplock;
4164 vm_mon_cmd
($vmid, "system_reset");
4168 sub get_vm_volumes
{
4172 foreach_volid
($conf, sub {
4173 my ($volid, $is_cdrom) = @_;
4175 return if $volid =~ m
|^/|;
4177 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4180 push @$vollist, $volid;
4186 sub vm_stop_cleanup
{
4187 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4190 fairsched_rmnod
($vmid); # try to destroy group
4193 my $vollist = get_vm_volumes
($conf);
4194 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
4197 foreach my $ext (qw(mon qmp pid vnc qga)) {
4198 unlink "/var/run/qemu-server/${vmid}.$ext";
4201 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4203 warn $@ if $@; # avoid errors - just warn
4206 # Note: use $nockeck to skip tests if VM configuration file exists.
4207 # We need that when migration VMs to other nodes (files already moved)
4208 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4210 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4212 $force = 1 if !defined($force) && !$shutdown;
4215 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4216 kill 15, $pid if $pid;
4217 my $conf = load_config
($vmid, $migratedfrom);
4218 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4222 lock_config
($vmid, sub {
4224 my $pid = check_running
($vmid, $nocheck);
4229 $conf = load_config
($vmid);
4230 check_lock
($conf) if !$skiplock;
4231 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4232 my $opts = parse_startup
($conf->{startup
});
4233 $timeout = $opts->{down
} if $opts->{down
};
4237 $timeout = 60 if !defined($timeout);
4241 if (defined($conf) && $conf->{agent
}) {
4242 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4244 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4247 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4254 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4259 if ($count >= $timeout) {
4261 warn "VM still running - terminating now with SIGTERM\n";
4264 die "VM quit/powerdown failed - got timeout\n";
4267 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4272 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4275 die "VM quit/powerdown failed\n";
4283 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4288 if ($count >= $timeout) {
4289 warn "VM still running - terminating now with SIGKILL\n";
4294 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4299 my ($vmid, $skiplock) = @_;
4301 lock_config
($vmid, sub {
4303 my $conf = load_config
($vmid);
4305 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4307 vm_mon_cmd
($vmid, "stop");
4312 my ($vmid, $skiplock) = @_;
4314 lock_config
($vmid, sub {
4316 my $conf = load_config
($vmid);
4318 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4320 vm_mon_cmd
($vmid, "cont");
4325 my ($vmid, $skiplock, $key) = @_;
4327 lock_config
($vmid, sub {
4329 my $conf = load_config
($vmid);
4331 # there is no qmp command, so we use the human monitor command
4332 vm_human_monitor_command
($vmid, "sendkey $key");
4337 my ($storecfg, $vmid, $skiplock) = @_;
4339 lock_config
($vmid, sub {
4341 my $conf = load_config
($vmid);
4343 check_lock
($conf) if !$skiplock;
4345 if (!check_running
($vmid)) {
4346 fairsched_rmnod
($vmid); # try to destroy group
4347 destroy_vm
($storecfg, $vmid);
4349 die "VM $vmid is running - destroy failed\n";
4357 my ($filename, $buf) = @_;
4359 my $fh = IO
::File-
>new($filename, "w");
4360 return undef if !$fh;
4362 my $res = print $fh $buf;
4369 sub pci_device_info
{
4374 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4375 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4377 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4378 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4380 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4381 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4383 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4384 return undef if !defined($product) || $product !~ s/^0x//;
4389 product
=> $product,
4395 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4404 my $name = $dev->{name
};
4406 my $fn = "$pcisysfs/devices/$name/reset";
4408 return file_write
($fn, "1");
4411 sub pci_dev_bind_to_stub
{
4414 my $name = $dev->{name
};
4416 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4417 return 1 if -d
$testdir;
4419 my $data = "$dev->{vendor} $dev->{product}";
4420 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4422 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4423 if (!file_write
($fn, $name)) {
4424 return undef if -f
$fn;
4427 $fn = "$pcisysfs/drivers/pci-stub/bind";
4428 if (! -d
$testdir) {
4429 return undef if !file_write
($fn, $name);
4435 sub pci_dev_bind_to_vfio
{
4438 my $name = $dev->{name
};
4440 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4442 if (!-d
$vfio_basedir) {
4443 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4445 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4447 my $testdir = "$vfio_basedir/$name";
4448 return 1 if -d
$testdir;
4450 my $data = "$dev->{vendor} $dev->{product}";
4451 return undef if !file_write
("$vfio_basedir/new_id", $data);
4453 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4454 if (!file_write
($fn, $name)) {
4455 return undef if -f
$fn;
4458 $fn = "$vfio_basedir/bind";
4459 if (! -d
$testdir) {
4460 return undef if !file_write
($fn, $name);
4466 sub pci_dev_group_bind_to_vfio
{
4469 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4471 if (!-d
$vfio_basedir) {
4472 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4474 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4476 # get IOMMU group devices
4477 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4478 my @devs = grep /^0000:/, readdir($D);
4481 foreach my $pciid (@devs) {
4482 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4483 my $info = pci_device_info
($1);
4484 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4490 sub print_pci_addr
{
4491 my ($id, $bridges) = @_;
4495 piix3
=> { bus
=> 0, addr
=> 1 },
4496 #addr2 : first videocard
4497 balloon0
=> { bus
=> 0, addr
=> 3 },
4498 watchdog
=> { bus
=> 0, addr
=> 4 },
4499 scsihw0
=> { bus
=> 0, addr
=> 5 },
4500 scsihw1
=> { bus
=> 0, addr
=> 6 },
4501 ahci0
=> { bus
=> 0, addr
=> 7 },
4502 qga0
=> { bus
=> 0, addr
=> 8 },
4503 spice
=> { bus
=> 0, addr
=> 9 },
4504 virtio0
=> { bus
=> 0, addr
=> 10 },
4505 virtio1
=> { bus
=> 0, addr
=> 11 },
4506 virtio2
=> { bus
=> 0, addr
=> 12 },
4507 virtio3
=> { bus
=> 0, addr
=> 13 },
4508 virtio4
=> { bus
=> 0, addr
=> 14 },
4509 virtio5
=> { bus
=> 0, addr
=> 15 },
4510 hostpci0
=> { bus
=> 0, addr
=> 16 },
4511 hostpci1
=> { bus
=> 0, addr
=> 17 },
4512 net0
=> { bus
=> 0, addr
=> 18 },
4513 net1
=> { bus
=> 0, addr
=> 19 },
4514 net2
=> { bus
=> 0, addr
=> 20 },
4515 net3
=> { bus
=> 0, addr
=> 21 },
4516 net4
=> { bus
=> 0, addr
=> 22 },
4517 net5
=> { bus
=> 0, addr
=> 23 },
4518 vga1
=> { bus
=> 0, addr
=> 24 },
4519 vga2
=> { bus
=> 0, addr
=> 25 },
4520 vga3
=> { bus
=> 0, addr
=> 26 },
4521 hostpci2
=> { bus
=> 0, addr
=> 27 },
4522 hostpci3
=> { bus
=> 0, addr
=> 28 },
4523 #addr29 : usb-host (pve-usb.cfg)
4524 'pci.1' => { bus
=> 0, addr
=> 30 },
4525 'pci.2' => { bus
=> 0, addr
=> 31 },
4526 'net6' => { bus
=> 1, addr
=> 1 },
4527 'net7' => { bus
=> 1, addr
=> 2 },
4528 'net8' => { bus
=> 1, addr
=> 3 },
4529 'net9' => { bus
=> 1, addr
=> 4 },
4530 'net10' => { bus
=> 1, addr
=> 5 },
4531 'net11' => { bus
=> 1, addr
=> 6 },
4532 'net12' => { bus
=> 1, addr
=> 7 },
4533 'net13' => { bus
=> 1, addr
=> 8 },
4534 'net14' => { bus
=> 1, addr
=> 9 },
4535 'net15' => { bus
=> 1, addr
=> 10 },
4536 'net16' => { bus
=> 1, addr
=> 11 },
4537 'net17' => { bus
=> 1, addr
=> 12 },
4538 'net18' => { bus
=> 1, addr
=> 13 },
4539 'net19' => { bus
=> 1, addr
=> 14 },
4540 'net20' => { bus
=> 1, addr
=> 15 },
4541 'net21' => { bus
=> 1, addr
=> 16 },
4542 'net22' => { bus
=> 1, addr
=> 17 },
4543 'net23' => { bus
=> 1, addr
=> 18 },
4544 'net24' => { bus
=> 1, addr
=> 19 },
4545 'net25' => { bus
=> 1, addr
=> 20 },
4546 'net26' => { bus
=> 1, addr
=> 21 },
4547 'net27' => { bus
=> 1, addr
=> 22 },
4548 'net28' => { bus
=> 1, addr
=> 23 },
4549 'net29' => { bus
=> 1, addr
=> 24 },
4550 'net30' => { bus
=> 1, addr
=> 25 },
4551 'net31' => { bus
=> 1, addr
=> 26 },
4552 'virtio6' => { bus
=> 2, addr
=> 1 },
4553 'virtio7' => { bus
=> 2, addr
=> 2 },
4554 'virtio8' => { bus
=> 2, addr
=> 3 },
4555 'virtio9' => { bus
=> 2, addr
=> 4 },
4556 'virtio10' => { bus
=> 2, addr
=> 5 },
4557 'virtio11' => { bus
=> 2, addr
=> 6 },
4558 'virtio12' => { bus
=> 2, addr
=> 7 },
4559 'virtio13' => { bus
=> 2, addr
=> 8 },
4560 'virtio14' => { bus
=> 2, addr
=> 9 },
4561 'virtio15' => { bus
=> 2, addr
=> 10 },
4564 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4565 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4566 my $bus = $devices->{$id}->{bus
};
4567 $res = ",bus=pci.$bus,addr=$addr";
4568 $bridges->{$bus} = 1 if $bridges;
4574 sub print_pcie_addr
{
4579 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4580 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4581 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4582 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4585 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4586 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4587 my $bus = $devices->{$id}->{bus
};
4588 $res = ",bus=$bus,addr=$addr";
4594 # vzdump restore implementaion
4596 sub tar_archive_read_firstfile
{
4597 my $archive = shift;
4599 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4601 # try to detect archive type first
4602 my $pid = open (TMP
, "tar tf '$archive'|") ||
4603 die "unable to open file '$archive'\n";
4604 my $firstfile = <TMP
>;
4608 die "ERROR: archive contaions no data\n" if !$firstfile;
4614 sub tar_restore_cleanup
{
4615 my ($storecfg, $statfile) = @_;
4617 print STDERR
"starting cleanup\n";
4619 if (my $fd = IO
::File-
>new($statfile, "r")) {
4620 while (defined(my $line = <$fd>)) {
4621 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4624 if ($volid =~ m
|^/|) {
4625 unlink $volid || die 'unlink failed\n';
4627 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4629 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4631 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4633 print STDERR
"unable to parse line in statfile - $line";
4640 sub restore_archive
{
4641 my ($archive, $vmid, $user, $opts) = @_;
4643 my $format = $opts->{format
};
4646 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4647 $format = 'tar' if !$format;
4649 } elsif ($archive =~ m/\.tar$/) {
4650 $format = 'tar' if !$format;
4651 } elsif ($archive =~ m/.tar.lzo$/) {
4652 $format = 'tar' if !$format;
4654 } elsif ($archive =~ m/\.vma$/) {
4655 $format = 'vma' if !$format;
4656 } elsif ($archive =~ m/\.vma\.gz$/) {
4657 $format = 'vma' if !$format;
4659 } elsif ($archive =~ m/\.vma\.lzo$/) {
4660 $format = 'vma' if !$format;
4663 $format = 'vma' if !$format; # default
4666 # try to detect archive format
4667 if ($format eq 'tar') {
4668 return restore_tar_archive
($archive, $vmid, $user, $opts);
4670 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4674 sub restore_update_config_line
{
4675 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4677 return if $line =~ m/^\#qmdump\#/;
4678 return if $line =~ m/^\#vzdump\#/;
4679 return if $line =~ m/^lock:/;
4680 return if $line =~ m/^unused\d+:/;
4681 return if $line =~ m/^parent:/;
4682 return if $line =~ m/^template:/; # restored VM is never a template
4684 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4685 # try to convert old 1.X settings
4686 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4687 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4688 my ($model, $macaddr) = split(/\=/, $devconfig);
4689 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4692 bridge
=> "vmbr$ind",
4693 macaddr
=> $macaddr,
4695 my $netstr = print_net
($net);
4697 print $outfd "net$cookie->{netcount}: $netstr\n";
4698 $cookie->{netcount
}++;
4700 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4701 my ($id, $netstr) = ($1, $2);
4702 my $net = parse_net
($netstr);
4703 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4704 $netstr = print_net
($net);
4705 print $outfd "$id: $netstr\n";
4706 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4709 if ($line =~ m/backup=no/) {
4710 print $outfd "#$line";
4711 } elsif ($virtdev && $map->{$virtdev}) {
4712 my $di = parse_drive
($virtdev, $value);
4713 delete $di->{format
}; # format can change on restore
4714 $di->{file
} = $map->{$virtdev};
4715 $value = print_drive
($vmid, $di);
4716 print $outfd "$virtdev: $value\n";
4726 my ($cfg, $vmid) = @_;
4728 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4730 my $volid_hash = {};
4731 foreach my $storeid (keys %$info) {
4732 foreach my $item (@{$info->{$storeid}}) {
4733 next if !($item->{volid
} && $item->{size
});
4734 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4735 $volid_hash->{$item->{volid
}} = $item;
4742 sub get_used_paths
{
4743 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
4747 my $scan_config = sub {
4748 my ($cref, $snapname) = @_;
4750 foreach my $key (keys %$cref) {
4751 my $value = $cref->{$key};
4752 if (valid_drivename
($key)) {
4753 next if $skip_drive && $key eq $skip_drive;
4754 my $drive = parse_drive
($key, $value);
4755 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
4756 if ($drive->{file
} =~ m!^/!) {
4757 $used_path->{$drive->{file
}}++; # = 1;
4759 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
4761 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
4763 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
4764 $used_path->{$path}++; # = 1;
4770 &$scan_config($conf);
4774 if ($scan_snapshots) {
4775 foreach my $snapname (keys %{$conf->{snapshots
}}) {
4776 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
4783 sub update_disksize
{
4784 my ($vmid, $conf, $volid_hash) = @_;
4790 # Note: it is allowed to define multiple storages with same path (alias), so
4791 # we need to check both 'volid' and real 'path' (two different volid can point
4792 # to the same path).
4797 foreach my $opt (keys %$conf) {
4798 if (valid_drivename
($opt)) {
4799 my $drive = parse_drive
($opt, $conf->{$opt});
4800 my $volid = $drive->{file
};
4803 $used->{$volid} = 1;
4804 if ($volid_hash->{$volid} &&
4805 (my $path = $volid_hash->{$volid}->{path
})) {
4806 $usedpath->{$path} = 1;
4809 next if drive_is_cdrom
($drive);
4810 next if !$volid_hash->{$volid};
4812 $drive->{size
} = $volid_hash->{$volid}->{size
};
4813 my $new = print_drive
($vmid, $drive);
4814 if ($new ne $conf->{$opt}) {
4816 $conf->{$opt} = $new;
4821 # remove 'unusedX' entry if volume is used
4822 foreach my $opt (keys %$conf) {
4823 next if $opt !~ m/^unused\d+$/;
4824 my $volid = $conf->{$opt};
4825 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
4826 if ($used->{$volid} || ($path && $usedpath->{$path})) {
4828 delete $conf->{$opt};
4832 foreach my $volid (sort keys %$volid_hash) {
4833 next if $volid =~ m/vm-$vmid-state-/;
4834 next if $used->{$volid};
4835 my $path = $volid_hash->{$volid}->{path
};
4836 next if !$path; # just to be sure
4837 next if $usedpath->{$path};
4839 add_unused_volume
($conf, $volid);
4840 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
4847 my ($vmid, $nolock) = @_;
4849 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
4851 my $volid_hash = scan_volids
($cfg, $vmid);
4853 my $updatefn = sub {
4856 my $conf = load_config
($vmid);
4861 foreach my $volid (keys %$volid_hash) {
4862 my $info = $volid_hash->{$volid};
4863 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
4866 my $changes = update_disksize
($vmid, $conf, $vm_volids);
4868 update_config_nolock
($vmid, $conf, 1) if $changes;
4871 if (defined($vmid)) {
4875 lock_config
($vmid, $updatefn, $vmid);
4878 my $vmlist = config_list
();
4879 foreach my $vmid (keys %$vmlist) {
4883 lock_config
($vmid, $updatefn, $vmid);
4889 sub restore_vma_archive
{
4890 my ($archive, $vmid, $user, $opts, $comp) = @_;
4892 my $input = $archive eq '-' ?
"<&STDIN" : undef;
4893 my $readfrom = $archive;
4898 my $qarchive = PVE
::Tools
::shellquote
($archive);
4899 if ($comp eq 'gzip') {
4900 $uncomp = "zcat $qarchive|";
4901 } elsif ($comp eq 'lzop') {
4902 $uncomp = "lzop -d -c $qarchive|";
4904 die "unknown compression method '$comp'\n";
4909 my $tmpdir = "/var/tmp/vzdumptmp$$";
4912 # disable interrupts (always do cleanups)
4913 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4914 warn "got interrupt - ignored\n";
4917 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4918 POSIX
::mkfifo
($mapfifo, 0600);
4921 my $openfifo = sub {
4922 open($fifofh, '>', $mapfifo) || die $!;
4925 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4932 my $rpcenv = PVE
::RPCEnvironment
::get
();
4934 my $conffile = config_file
($vmid);
4935 my $tmpfn = "$conffile.$$.tmp";
4937 # Note: $oldconf is undef if VM does not exists
4938 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4940 my $print_devmap = sub {
4941 my $virtdev_hash = {};
4943 my $cfgfn = "$tmpdir/qemu-server.conf";
4945 # we can read the config - that is already extracted
4946 my $fh = IO
::File-
>new($cfgfn, "r") ||
4947 "unable to read qemu-server.conf - $!\n";
4949 while (defined(my $line = <$fh>)) {
4950 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4951 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4952 die "archive does not contain data for drive '$virtdev'\n"
4953 if !$devinfo->{$devname};
4954 if (defined($opts->{storage
})) {
4955 $storeid = $opts->{storage
} || 'local';
4956 } elsif (!$storeid) {
4959 $format = 'raw' if !$format;
4960 $devinfo->{$devname}->{devname
} = $devname;
4961 $devinfo->{$devname}->{virtdev
} = $virtdev;
4962 $devinfo->{$devname}->{format
} = $format;
4963 $devinfo->{$devname}->{storeid
} = $storeid;
4965 # check permission on storage
4966 my $pool = $opts->{pool
}; # todo: do we need that?
4967 if ($user ne 'root@pam') {
4968 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4971 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4975 foreach my $devname (keys %$devinfo) {
4976 die "found no device mapping information for device '$devname'\n"
4977 if !$devinfo->{$devname}->{virtdev
};
4980 my $cfg = cfs_read_file
('storage.cfg');
4982 # create empty/temp config
4984 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4985 foreach_drive
($oldconf, sub {
4986 my ($ds, $drive) = @_;
4988 return if drive_is_cdrom
($drive);
4990 my $volid = $drive->{file
};
4992 return if !$volid || $volid =~ m
|^/|;
4994 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4995 return if !$path || !$owner || ($owner != $vmid);
4997 # Note: only delete disk we want to restore
4998 # other volumes will become unused
4999 if ($virtdev_hash->{$ds}) {
5000 PVE
::Storage
::vdisk_free
($cfg, $volid);
5006 foreach my $virtdev (sort keys %$virtdev_hash) {
5007 my $d = $virtdev_hash->{$virtdev};
5008 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5009 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5011 # test if requested format is supported
5012 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5013 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5014 $d->{format
} = $defFormat if !$supported;
5016 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5017 $d->{format
}, undef, $alloc_size);
5018 print STDERR
"new volume ID is '$volid'\n";
5019 $d->{volid
} = $volid;
5020 my $path = PVE
::Storage
::path
($cfg, $volid);
5022 my $write_zeros = 1;
5023 # fixme: what other storages types initialize volumes with zero?
5024 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5025 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5029 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5031 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5032 $map->{$virtdev} = $volid;
5035 $fh->seek(0, 0) || die "seek failed - $!\n";
5037 my $outfd = new IO
::File
($tmpfn, "w") ||
5038 die "unable to write config for VM $vmid\n";
5040 my $cookie = { netcount
=> 0 };
5041 while (defined(my $line = <$fh>)) {
5042 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5051 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5052 die "interrupted by signal\n";
5054 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5056 $oldtimeout = alarm($timeout);
5063 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5064 my ($dev_id, $size, $devname) = ($1, $2, $3);
5065 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5066 } elsif ($line =~ m/^CTIME: /) {
5067 # we correctly received the vma config, so we can disable
5068 # the timeout now for disk allocation (set to 10 minutes, so
5069 # that we always timeout if something goes wrong)
5072 print $fifofh "done\n";
5073 my $tmp = $oldtimeout || 0;
5074 $oldtimeout = undef;
5080 print "restore vma archive: $cmd\n";
5081 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5085 alarm($oldtimeout) if $oldtimeout;
5093 my $cfg = cfs_read_file
('storage.cfg');
5094 foreach my $devname (keys %$devinfo) {
5095 my $volid = $devinfo->{$devname}->{volid
};
5098 if ($volid =~ m
|^/|) {
5099 unlink $volid || die 'unlink failed\n';
5101 PVE
::Storage
::vdisk_free
($cfg, $volid);
5103 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5105 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5112 rename($tmpfn, $conffile) ||
5113 die "unable to commit configuration file '$conffile'\n";
5115 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5117 eval { rescan
($vmid, 1); };
5121 sub restore_tar_archive
{
5122 my ($archive, $vmid, $user, $opts) = @_;
5124 if ($archive ne '-') {
5125 my $firstfile = tar_archive_read_firstfile
($archive);
5126 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5127 if $firstfile ne 'qemu-server.conf';
5130 my $storecfg = cfs_read_file
('storage.cfg');
5132 # destroy existing data - keep empty config
5133 my $vmcfgfn = config_file
($vmid);
5134 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5136 my $tocmd = "/usr/lib/qemu-server/qmextract";
5138 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5139 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5140 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5141 $tocmd .= ' --info' if $opts->{info
};
5143 # tar option "xf" does not autodetect compression when read from STDIN,
5144 # so we pipe to zcat
5145 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5146 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5148 my $tmpdir = "/var/tmp/vzdumptmp$$";
5151 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5152 local $ENV{VZDUMP_VMID
} = $vmid;
5153 local $ENV{VZDUMP_USER
} = $user;
5155 my $conffile = config_file
($vmid);
5156 my $tmpfn = "$conffile.$$.tmp";
5158 # disable interrupts (always do cleanups)
5159 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5160 print STDERR
"got interrupt - ignored\n";
5165 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5166 die "interrupted by signal\n";
5169 if ($archive eq '-') {
5170 print "extracting archive from STDIN\n";
5171 run_command
($cmd, input
=> "<&STDIN");
5173 print "extracting archive '$archive'\n";
5177 return if $opts->{info
};
5181 my $statfile = "$tmpdir/qmrestore.stat";
5182 if (my $fd = IO
::File-
>new($statfile, "r")) {
5183 while (defined (my $line = <$fd>)) {
5184 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5185 $map->{$1} = $2 if $1;
5187 print STDERR
"unable to parse line in statfile - $line\n";
5193 my $confsrc = "$tmpdir/qemu-server.conf";
5195 my $srcfd = new IO
::File
($confsrc, "r") ||
5196 die "unable to open file '$confsrc'\n";
5198 my $outfd = new IO
::File
($tmpfn, "w") ||
5199 die "unable to write config for VM $vmid\n";
5201 my $cookie = { netcount
=> 0 };
5202 while (defined (my $line = <$srcfd>)) {
5203 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5215 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5222 rename $tmpfn, $conffile ||
5223 die "unable to commit configuration file '$conffile'\n";
5225 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5227 eval { rescan
($vmid, 1); };
5232 # Internal snapshots
5234 # NOTE: Snapshot create/delete involves several non-atomic
5235 # action, and can take a long time.
5236 # So we try to avoid locking the file and use 'lock' variable
5237 # inside the config file instead.
5239 my $snapshot_copy_config = sub {
5240 my ($source, $dest) = @_;
5242 foreach my $k (keys %$source) {
5243 next if $k eq 'snapshots';
5244 next if $k eq 'snapstate';
5245 next if $k eq 'snaptime';
5246 next if $k eq 'vmstate';
5247 next if $k eq 'lock';
5248 next if $k eq 'digest';
5249 next if $k eq 'description';
5250 next if $k =~ m/^unused\d+$/;
5252 $dest->{$k} = $source->{$k};
5256 my $snapshot_apply_config = sub {
5257 my ($conf, $snap) = @_;
5259 # copy snapshot list
5261 snapshots
=> $conf->{snapshots
},
5264 # keep description and list of unused disks
5265 foreach my $k (keys %$conf) {
5266 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5267 $newconf->{$k} = $conf->{$k};
5270 &$snapshot_copy_config($snap, $newconf);
5275 sub foreach_writable_storage
{
5276 my ($conf, $func) = @_;
5280 foreach my $ds (keys %$conf) {
5281 next if !valid_drivename
($ds);
5283 my $drive = parse_drive
($ds, $conf->{$ds});
5285 next if drive_is_cdrom
($drive);
5287 my $volid = $drive->{file
};
5289 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5290 $sidhash->{$sid} = $sid if $sid;
5293 foreach my $sid (sort keys %$sidhash) {
5298 my $alloc_vmstate_volid = sub {
5299 my ($storecfg, $vmid, $conf, $snapname) = @_;
5301 # Note: we try to be smart when selecting a $target storage
5305 # search shared storage first
5306 foreach_writable_storage
($conf, sub {
5308 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5309 return if !$scfg->{shared
};
5311 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5315 # now search local storage
5316 foreach_writable_storage
($conf, sub {
5318 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5319 return if $scfg->{shared
};
5321 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5325 $target = 'local' if !$target;
5327 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5328 # we abort live save after $conf->{memory}, so we need at max twice that space
5329 my $size = $conf->{memory
}*2 + $driver_state_size;
5331 my $name = "vm-$vmid-state-$snapname";
5332 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5333 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5334 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5339 my $snapshot_prepare = sub {
5340 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5344 my $updatefn = sub {
5346 my $conf = load_config
($vmid);
5348 die "you can't take a snapshot if it's a template\n"
5349 if is_template
($conf);
5353 $conf->{lock} = 'snapshot';
5355 die "snapshot name '$snapname' already used\n"
5356 if defined($conf->{snapshots
}->{$snapname});
5358 my $storecfg = PVE
::Storage
::config
();
5359 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5361 $snap = $conf->{snapshots
}->{$snapname} = {};
5363 if ($save_vmstate && check_running
($vmid)) {
5364 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5367 &$snapshot_copy_config($conf, $snap);
5369 $snap->{snapstate
} = "prepare";
5370 $snap->{snaptime
} = time();
5371 $snap->{description
} = $comment if $comment;
5373 # always overwrite machine if we save vmstate. This makes sure we
5374 # can restore it later using correct machine type
5375 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5377 update_config_nolock
($vmid, $conf, 1);
5380 lock_config
($vmid, $updatefn);
5385 my $snapshot_commit = sub {
5386 my ($vmid, $snapname) = @_;
5388 my $updatefn = sub {
5390 my $conf = load_config
($vmid);
5392 die "missing snapshot lock\n"
5393 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5395 my $has_machine_config = defined($conf->{machine
});
5397 my $snap = $conf->{snapshots
}->{$snapname};
5399 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5401 die "wrong snapshot state\n"
5402 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5404 delete $snap->{snapstate
};
5405 delete $conf->{lock};
5407 my $newconf = &$snapshot_apply_config($conf, $snap);
5409 delete $newconf->{machine
} if !$has_machine_config;
5411 $newconf->{parent
} = $snapname;
5413 update_config_nolock
($vmid, $newconf, 1);
5416 lock_config
($vmid, $updatefn);
5419 sub snapshot_rollback
{
5420 my ($vmid, $snapname) = @_;
5426 my $storecfg = PVE
::Storage
::config
();
5428 my $updatefn = sub {
5430 my $conf = load_config
($vmid);
5432 die "you can't rollback if vm is a template\n" if is_template
($conf);
5434 $snap = $conf->{snapshots
}->{$snapname};
5436 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5438 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5439 if $snap->{snapstate
};
5443 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5446 die "unable to rollback vm $vmid: vm is running\n"
5447 if check_running
($vmid);
5450 $conf->{lock} = 'rollback';
5452 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5453 delete $conf->{lock};
5459 my $has_machine_config = defined($conf->{machine
});
5461 # copy snapshot config to current config
5462 $conf = &$snapshot_apply_config($conf, $snap);
5463 $conf->{parent
} = $snapname;
5465 # Note: old code did not store 'machine', so we try to be smart
5466 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5467 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5468 # we remove the 'machine' configuration if not explicitly specified
5469 # in the original config.
5470 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5473 update_config_nolock
($vmid, $conf, 1);
5475 if (!$prepare && $snap->{vmstate
}) {
5476 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5477 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5481 lock_config
($vmid, $updatefn);
5483 foreach_drive
($snap, sub {
5484 my ($ds, $drive) = @_;
5486 return if drive_is_cdrom
($drive);
5488 my $volid = $drive->{file
};
5489 my $device = "drive-$ds";
5491 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5495 lock_config
($vmid, $updatefn);
5498 my $savevm_wait = sub {
5502 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5503 if (!$stat->{status
}) {
5504 die "savevm not active\n";
5505 } elsif ($stat->{status
} eq 'active') {
5508 } elsif ($stat->{status
} eq 'completed') {
5511 die "query-savevm returned status '$stat->{status}'\n";
5516 sub snapshot_create
{
5517 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5519 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5521 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5523 my $config = load_config
($vmid);
5525 my $running = check_running
($vmid);
5527 my $freezefs = $running && $config->{agent
};
5528 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5533 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5534 warn "guest-fsfreeze-freeze problems - $@" if $@;
5538 # create internal snapshots of all drives
5540 my $storecfg = PVE
::Storage
::config
();
5543 if ($snap->{vmstate
}) {
5544 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5545 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5546 &$savevm_wait($vmid);
5548 vm_mon_cmd
($vmid, "savevm-start");
5552 foreach_drive
($snap, sub {
5553 my ($ds, $drive) = @_;
5555 return if drive_is_cdrom
($drive);
5557 my $volid = $drive->{file
};
5558 my $device = "drive-$ds";
5560 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5561 $drivehash->{$ds} = 1;
5567 eval { vm_mon_cmd
($vmid, "savevm-end") };
5571 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5572 warn "guest-fsfreeze-thaw problems - $@" if $@;
5575 # savevm-end is async, we need to wait
5577 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5578 if (!$stat->{bytes
}) {
5581 print "savevm not yet finished\n";
5589 warn "snapshot create failed: starting cleanup\n";
5590 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5595 &$snapshot_commit($vmid, $snapname);
5598 # Note: $drivehash is only set when called from snapshot_create.
5599 sub snapshot_delete
{
5600 my ($vmid, $snapname, $force, $drivehash) = @_;
5607 my $unlink_parent = sub {
5608 my ($confref, $new_parent) = @_;
5610 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5612 $confref->{parent
} = $new_parent;
5614 delete $confref->{parent
};
5619 my $updatefn = sub {
5620 my ($remove_drive) = @_;
5622 my $conf = load_config
($vmid);
5626 die "you can't delete a snapshot if vm is a template\n"
5627 if is_template
($conf);
5630 $snap = $conf->{snapshots
}->{$snapname};
5632 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5634 # remove parent refs
5636 &$unlink_parent($conf, $snap->{parent
});
5637 foreach my $sn (keys %{$conf->{snapshots
}}) {
5638 next if $sn eq $snapname;
5639 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5643 if ($remove_drive) {
5644 if ($remove_drive eq 'vmstate') {
5645 delete $snap->{$remove_drive};
5647 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5648 my $volid = $drive->{file
};
5649 delete $snap->{$remove_drive};
5650 add_unused_volume
($conf, $volid);
5655 $snap->{snapstate
} = 'delete';
5657 delete $conf->{snapshots
}->{$snapname};
5658 delete $conf->{lock} if $drivehash;
5659 foreach my $volid (@$unused) {
5660 add_unused_volume
($conf, $volid);
5664 update_config_nolock
($vmid, $conf, 1);
5667 lock_config
($vmid, $updatefn);
5669 # now remove vmstate file
5671 my $storecfg = PVE
::Storage
::config
();
5673 if ($snap->{vmstate
}) {
5674 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5676 die $err if !$force;
5679 # save changes (remove vmstate from snapshot)
5680 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5683 # now remove all internal snapshots
5684 foreach_drive
($snap, sub {
5685 my ($ds, $drive) = @_;
5687 return if drive_is_cdrom
($drive);
5689 my $volid = $drive->{file
};
5690 my $device = "drive-$ds";
5692 if (!$drivehash || $drivehash->{$ds}) {
5693 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
5695 die $err if !$force;
5700 # save changes (remove drive fron snapshot)
5701 lock_config
($vmid, $updatefn, $ds) if !$force;
5702 push @$unused, $volid;
5705 # now cleanup config
5707 lock_config
($vmid, $updatefn);
5711 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
5714 foreach_drive
($conf, sub {
5715 my ($ds, $drive) = @_;
5717 return if drive_is_cdrom
($drive);
5718 my $volid = $drive->{file
};
5719 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
5722 return $err ?
0 : 1;
5725 sub template_create
{
5726 my ($vmid, $conf, $disk) = @_;
5728 my $storecfg = PVE
::Storage
::config
();
5730 foreach_drive
($conf, sub {
5731 my ($ds, $drive) = @_;
5733 return if drive_is_cdrom
($drive);
5734 return if $disk && $ds ne $disk;
5736 my $volid = $drive->{file
};
5737 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5739 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5740 $drive->{file
} = $voliddst;
5741 $conf->{$ds} = print_drive
($vmid, $drive);
5742 update_config_nolock
($vmid, $conf, 1);
5749 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
5752 sub qemu_img_convert
{
5753 my ($src_volid, $dst_volid, $size, $snapname) = @_;
5755 my $storecfg = PVE
::Storage
::config
();
5756 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5757 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5759 if ($src_storeid && $dst_storeid) {
5760 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5761 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5763 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5764 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5766 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5767 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5770 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5771 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5772 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
5776 if($line =~ m/\((\S+)\/100\
%\)/){
5778 my $transferred = int($size * $percent / 100);
5779 my $remaining = $size - $transferred;
5781 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5786 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5788 die "copy failed: $err" if $err;
5792 sub qemu_img_format
{
5793 my ($scfg, $volname) = @_;
5795 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
5797 } elsif ($scfg->{type
} eq 'iscsi') {
5798 return "host_device";
5804 sub qemu_drive_mirror
{
5805 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
5812 my $storecfg = PVE
::Storage
::config
();
5813 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5815 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5818 if ($dst_volname =~ m/\.(raw|qcow2)$/){
5822 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5824 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
5825 $opts->{format
} = $format if $format;
5827 #fixme : sometime drive-mirror timeout, but works fine after.
5828 # (I have see the problem with big volume > 200GB), so we need to eval
5829 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); };
5830 # ignore errors here
5834 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5835 my $stat = @$stats[0];
5836 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5837 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5839 my $busy = $stat->{busy
};
5841 if (my $total = $stat->{len
}) {
5842 my $transferred = $stat->{offset
} || 0;
5843 my $remaining = $total - $transferred;
5844 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5846 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy\n";
5849 if ($stat->{len
} == $stat->{offset
}) {
5850 if ($busy eq 'false') {
5852 last if $vmiddst != $vmid;
5854 # try to switch the disk if source and destination are on the same guest
5855 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5857 die $@ if $@ !~ m/cannot be completed/;
5860 if ($count > $maxwait) {
5861 # if too much writes to disk occurs at the end of migration
5862 #the disk needs to be freezed to be able to complete the migration
5863 vm_suspend
($vmid,1);
5868 $old_len = $stat->{offset
};
5872 vm_resume
($vmid, 1) if $frozen;
5877 my $cancel_job = sub {
5878 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5880 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5881 my $stat = @$stats[0];
5888 eval { &$cancel_job(); };
5889 die "mirroring error: $err";
5892 if ($vmiddst != $vmid) {
5893 # if we clone a disk for a new target vm, we don't switch the disk
5894 &$cancel_job(); # so we call block-job-cancel
5899 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5900 $newvmid, $storage, $format, $full, $newvollist) = @_;
5905 print "create linked clone of drive $drivename ($drive->{file})\n";
5906 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5907 push @$newvollist, $newvolid;
5909 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5910 $storeid = $storage if $storage;
5912 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5914 $format = $drive->{format
} || $defFormat;
5917 # test if requested format is supported - else use default
5918 my $supported = grep { $_ eq $format } @$validFormats;
5919 $format = $defFormat if !$supported;
5921 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5923 print "create full clone of drive $drivename ($drive->{file})\n";
5924 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5925 push @$newvollist, $newvolid;
5927 if (!$running || $snapname) {
5928 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
5930 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
5934 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5937 $disk->{format
} = undef;
5938 $disk->{file
} = $newvolid;
5939 $disk->{size
} = $size;
5944 # this only works if VM is running
5945 sub get_current_qemu_machine
{
5948 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5949 my $res = vm_qmp_command
($vmid, $cmd);
5951 my ($current, $default);
5952 foreach my $e (@$res) {
5953 $default = $e->{name
} if $e->{'is-default'};
5954 $current = $e->{name
} if $e->{'is-current'};
5957 # fallback to the default machine if current is not supported by qemu
5958 return $current || $default || 'pc';
5965 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5966 my (undef, $id, $function) = @_;
5967 my $res = { id
=> $id, function
=> $function};
5968 push @{$devices->{$id}}, $res;