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);
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
=> "Specifies whether a VM will be started during system bootup.",
164 description
=> "Automatic restart after crash (currently ignored).",
170 description
=> "Allow hotplug for disk and network device",
176 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
182 description
=> "Lock/unlock the VM.",
183 enum
=> [qw(migrate backup snapshot rollback)],
188 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.",
195 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.",
203 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
210 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
216 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",
224 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
225 enum
=> PVE
::Tools
::kvmkeymaplist
(),
230 type
=> 'string', format
=> 'dns-name',
231 description
=> "Set a name for the VM. Only used on the configuration web interface.",
236 description
=> "scsi controller model",
237 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)],
243 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
248 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
249 description
=> <<EODESC,
250 Used to enable special optimization/features for specific
253 other => unspecified OS
254 wxp => Microsoft Windows XP
255 w2k => Microsoft Windows 2000
256 w2k3 => Microsoft Windows 2003
257 w2k8 => Microsoft Windows 2008
258 wvista => Microsoft Windows Vista
259 win7 => Microsoft Windows 7
260 win8 => Microsoft Windows 8/2012
261 l24 => Linux 2.4 Kernel
262 l26 => Linux 2.6/3.X Kernel
263 solaris => solaris/opensolaris/openindiania kernel
265 other|l24|l26|solaris ... no special behaviour
266 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
272 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
273 pattern
=> '[acdn]{1,4}',
278 type
=> 'string', format
=> 'pve-qm-bootdisk',
279 description
=> "Enable booting from specified disk.",
280 pattern
=> '(ide|sata|scsi|virtio)\d+',
285 description
=> "The number of CPUs. Please use option -sockets instead.",
292 description
=> "The number of CPU sockets.",
299 description
=> "The number of cores per socket.",
306 description
=> "Maximum cpus for hotplug.",
313 description
=> "Enable/disable ACPI.",
319 description
=> "Enable/disable Qemu GuestAgent.",
325 description
=> "Enable/disable KVM hardware virtualization.",
331 description
=> "Enable/disable time drift fix.",
337 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
342 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
347 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.",
348 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
352 type
=> 'string', format
=> 'pve-qm-watchdog',
353 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
354 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)",
359 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
360 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'.",
361 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
366 type
=> 'string', format
=> 'pve-qm-startup',
367 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
368 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.",
373 description
=> "Enable/disable Template.",
379 description
=> <<EODESCR,
380 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
382 args: -no-reboot -no-hpet
389 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).",
394 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
398 migrate_downtime
=> {
401 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
407 type
=> 'string', format
=> 'pve-qm-drive',
408 typetext
=> 'volume',
409 description
=> "This is an alias for option -ide2",
413 description
=> "Emulated CPU type.",
415 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
418 parent
=> get_standard_option
('pve-snapshot-name', {
420 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
424 description
=> "Timestamp for snapshots.",
430 type
=> 'string', format
=> 'pve-volume-id',
431 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
434 description
=> "Specific the Qemu machine type.",
436 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
442 # what about other qemu settings ?
444 #machine => 'string',
457 ##soundhw => 'string',
459 while (my ($k, $v) = each %$confdesc) {
460 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
463 my $MAX_IDE_DISKS = 4;
464 my $MAX_SCSI_DISKS = 14;
465 my $MAX_VIRTIO_DISKS = 16;
466 my $MAX_SATA_DISKS = 6;
467 my $MAX_USB_DEVICES = 5;
469 my $MAX_UNUSED_DISKS = 8;
470 my $MAX_HOSTPCI_DEVICES = 2;
471 my $MAX_SERIAL_PORTS = 4;
472 my $MAX_PARALLEL_PORTS = 3;
474 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
475 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3'];
476 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
480 type
=> 'string', format
=> 'pve-qm-net',
481 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>][,tag=<vlanid>][,firewall=0|1]",
482 description
=> <<EODESCR,
483 Specify network devices.
485 MODEL is one of: $nic_model_list_txt
487 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
488 automatically generated if not specified.
490 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
492 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'.
494 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
500 The DHCP server assign addresses to the guest starting from 10.0.2.15.
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
506 for (my $i = 0; $i < $MAX_NETS; $i++) {
507 $confdesc->{"net$i"} = $netdesc;
514 type
=> 'string', format
=> 'pve-qm-drive',
515 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]',
516 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 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]',
524 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
530 type
=> 'string', format
=> 'pve-qm-drive',
531 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]',
532 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
534 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
538 type
=> 'string', format
=> 'pve-qm-drive',
539 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]',
540 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
542 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
546 type
=> 'string', format
=> 'pve-qm-usb-device',
547 typetext
=> 'host=HOSTUSBDEVICE|spice',
548 description
=> <<EODESCR,
549 Configure an USB device (n is 0 to 4). This can be used to
550 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
552 'bus-port(.port)*' (decimal numbers) or
553 'vendor_id:product_id' (hexadeciaml numbers)
555 You can use the 'lsusb -t' command to list existing usb devices.
557 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
559 The value 'spice' can be used to add a usb redirection devices for spice.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
567 type
=> 'string', format
=> 'pve-qm-hostpci',
568 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]",
569 description
=> <<EODESCR,
570 Map host pci devices. HOSTPCIDEVICE syntax is:
572 'bus:dev.func' (hexadecimal numbers)
574 You can us the 'lspci' command to list existing pci devices.
576 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
578 The 'driver' option is currently ignored.
580 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
582 Experimental: user reported problems with this option.
585 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
590 pattern
=> '(/dev/ttyS\d+|socket)',
591 description
=> <<EODESCR,
592 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
594 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
596 Experimental: user reported problems with this option.
603 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
604 description
=> <<EODESCR,
605 Map host parallel devices (n is 0 to 2).
607 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
609 Experimental: user reported problems with this option.
613 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
614 $confdesc->{"parallel$i"} = $paralleldesc;
617 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
618 $confdesc->{"serial$i"} = $serialdesc;
621 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
622 $confdesc->{"hostpci$i"} = $hostpcidesc;
625 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
626 $drivename_hash->{"ide$i"} = 1;
627 $confdesc->{"ide$i"} = $idedesc;
630 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
631 $drivename_hash->{"sata$i"} = 1;
632 $confdesc->{"sata$i"} = $satadesc;
635 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
636 $drivename_hash->{"scsi$i"} = 1;
637 $confdesc->{"scsi$i"} = $scsidesc ;
640 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
641 $drivename_hash->{"virtio$i"} = 1;
642 $confdesc->{"virtio$i"} = $virtiodesc;
645 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
646 $confdesc->{"usb$i"} = $usbdesc;
651 type
=> 'string', format
=> 'pve-volume-id',
652 description
=> "Reference to unused volumes.",
655 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
656 $confdesc->{"unused$i"} = $unuseddesc;
659 my $kvm_api_version = 0;
663 return $kvm_api_version if $kvm_api_version;
665 my $fh = IO
::File-
>new("</dev/kvm") ||
668 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
669 $kvm_api_version = $v;
674 return $kvm_api_version;
677 my $kvm_user_version;
679 sub kvm_user_version
{
681 return $kvm_user_version if $kvm_user_version;
683 $kvm_user_version = 'unknown';
685 my $tmp = `kvm -help 2>/dev/null`;
687 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
688 $kvm_user_version = $2;
691 return $kvm_user_version;
695 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
698 # order is important - used to autoselect boot disk
699 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
700 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
701 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
702 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
705 sub valid_drivename
{
708 return defined($drivename_hash->{$dev});
713 return defined($confdesc->{$key});
717 return $nic_model_list;
720 sub os_list_description
{
725 w2k
=> 'Windows 2000',
726 w2k3
=>, 'Windows 2003',
727 w2k8
=> 'Windows 2008',
728 wvista
=> 'Windows Vista',
730 win8
=> 'Windows 8/2012',
740 return $cdrom_path if $cdrom_path;
742 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
743 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
744 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
748 my ($storecfg, $vmid, $cdrom) = @_;
750 if ($cdrom eq 'cdrom') {
751 return get_cdrom_path
();
752 } elsif ($cdrom eq 'none') {
754 } elsif ($cdrom =~ m
|^/|) {
757 return PVE
::Storage
::path
($storecfg, $cdrom);
761 # try to convert old style file names to volume IDs
762 sub filename_to_volume_id
{
763 my ($vmid, $file, $media) = @_;
765 if (!($file eq 'none' || $file eq 'cdrom' ||
766 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
768 return undef if $file =~ m
|/|;
770 if ($media && $media eq 'cdrom') {
771 $file = "local:iso/$file";
773 $file = "local:$vmid/$file";
780 sub verify_media_type
{
781 my ($opt, $vtype, $media) = @_;
786 if ($media eq 'disk') {
788 } elsif ($media eq 'cdrom') {
791 die "internal error";
794 return if ($vtype eq $etype);
796 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
799 sub cleanup_drive_path
{
800 my ($opt, $storecfg, $drive) = @_;
802 # try to convert filesystem paths to volume IDs
804 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
805 ($drive->{file
} !~ m
|^/dev/.+|) &&
806 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
807 ($drive->{file
} !~ m/^\d+$/)) {
808 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
809 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
810 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
811 verify_media_type
($opt, $vtype, $drive->{media
});
812 $drive->{file
} = $volid;
815 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
818 sub create_conf_nolock
{
819 my ($vmid, $settings) = @_;
821 my $filename = config_file
($vmid);
823 die "configuration file '$filename' already exists\n" if -f
$filename;
825 my $defaults = load_defaults
();
827 $settings->{name
} = "vm$vmid" if !$settings->{name
};
828 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
831 foreach my $opt (keys %$settings) {
832 next if !$confdesc->{$opt};
834 my $value = $settings->{$opt};
837 $data .= "$opt: $value\n";
840 PVE
::Tools
::file_set_contents
($filename, $data);
843 my $parse_size = sub {
846 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
847 my ($size, $unit) = ($1, $3);
850 $size = $size * 1024;
851 } elsif ($unit eq 'M') {
852 $size = $size * 1024 * 1024;
853 } elsif ($unit eq 'G') {
854 $size = $size * 1024 * 1024 * 1024;
860 my $format_size = sub {
865 my $kb = int($size/1024);
866 return $size if $kb*1024 != $size;
868 my $mb = int($kb/1024);
869 return "${kb}K" if $mb*1024 != $kb;
871 my $gb = int($mb/1024);
872 return "${mb}M" if $gb*1024 != $mb;
877 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
878 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
879 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
880 # [,aio=native|threads][,discard=ignore|on]
883 my ($key, $data) = @_;
887 # $key may be undefined - used to verify JSON parameters
888 if (!defined($key)) {
889 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
891 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
892 $res->{interface
} = $1;
898 foreach my $p (split (/,/, $data)) {
899 next if $p =~ m/^\s*$/;
901 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)=(.+)$/) {
902 my ($k, $v) = ($1, $2);
904 $k = 'file' if $k eq 'volume';
906 return undef if defined $res->{$k};
908 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
909 return undef if !$v || $v !~ m/^\d+/;
911 $v = sprintf("%.3f", $v / (1024*1024));
915 if (!$res->{file
} && $p !~ m/=/) {
923 return undef if !$res->{file
};
925 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
929 return undef if $res->{cache
} &&
930 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
931 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
932 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
933 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
934 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
935 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
936 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
937 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
938 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
939 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
940 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
941 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
942 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
944 return undef if $res->{mbps_rd
} && $res->{mbps
};
945 return undef if $res->{mbps_wr
} && $res->{mbps
};
947 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
949 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
951 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{iops_rd
} && $res->{iops
};
955 return undef if $res->{iops_wr
} && $res->{iops
};
958 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
959 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
960 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
961 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
962 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
963 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
967 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
970 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
971 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
972 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
973 return undef if $res->{interface
} eq 'virtio';
976 # rerror does not work with scsi drives
977 if ($res->{rerror
}) {
978 return undef if $res->{interface
} eq 'scsi';
984 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);
987 my ($vmid, $drive) = @_;
990 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
991 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
994 if ($drive->{size
}) {
995 $opts .= ",size=" . &$format_size($drive->{size
});
998 return "$drive->{file}$opts";
1002 my($fh, $noerr) = @_;
1005 my $SG_GET_VERSION_NUM = 0x2282;
1007 my $versionbuf = "\x00" x
8;
1008 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1010 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1013 my $version = unpack("I", $versionbuf);
1014 if ($version < 30000) {
1015 die "scsi generic interface too old\n" if !$noerr;
1019 my $buf = "\x00" x
36;
1020 my $sensebuf = "\x00" x
8;
1021 my $cmd = pack("C x3 C x1", 0x12, 36);
1023 # see /usr/include/scsi/sg.h
1024 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";
1026 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1027 length($sensebuf), 0, length($buf), $buf,
1028 $cmd, $sensebuf, 6000);
1030 $ret = ioctl($fh, $SG_IO, $packet);
1032 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1036 my @res = unpack($sg_io_hdr_t, $packet);
1037 if ($res[17] || $res[18]) {
1038 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1043 (my $byte0, my $byte1, $res->{vendor
},
1044 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1046 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1047 $res->{type
} = $byte0 & 31;
1055 my $fh = IO
::File-
>new("+<$path") || return undef;
1056 my $res = scsi_inquiry
($fh, 1);
1062 sub machine_type_is_q35
{
1065 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1068 sub print_tabletdevice_full
{
1071 my $q35 = machine_type_is_q35
($conf);
1073 # we use uhci for old VMs because tablet driver was buggy in older qemu
1074 my $usbbus = $q35 ?
"ehci" : "uhci";
1076 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1079 sub print_drivedevice_full
{
1080 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1085 if ($drive->{interface
} eq 'virtio') {
1086 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1087 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1088 } elsif ($drive->{interface
} eq 'scsi') {
1089 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1090 my $controller = int($drive->{index} / $maxdev);
1091 my $unit = $drive->{index} % $maxdev;
1092 my $devicetype = 'hd';
1094 if (drive_is_cdrom
($drive)) {
1097 if ($drive->{file
} =~ m
|^/|) {
1098 $path = $drive->{file
};
1100 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1103 if($path =~ m/^iscsi\:\/\
//){
1104 $devicetype = 'generic';
1106 if (my $info = path_is_scsi
($path)) {
1107 if ($info->{type
} == 0) {
1108 $devicetype = 'block';
1109 } elsif ($info->{type
} == 1) { # tape
1110 $devicetype = 'generic';
1116 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1117 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 $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}";
1122 } elsif ($drive->{interface
} eq 'ide'){
1124 my $controller = int($drive->{index} / $maxdev);
1125 my $unit = $drive->{index} % $maxdev;
1126 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1128 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1129 } elsif ($drive->{interface
} eq 'sata'){
1130 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1131 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1132 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1133 } elsif ($drive->{interface
} eq 'usb') {
1135 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1137 die "unsupported interface type";
1140 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1145 sub get_initiator_name
{
1148 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1149 while (defined(my $line = <$fh>)) {
1150 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1159 sub print_drive_full
{
1160 my ($storecfg, $vmid, $drive) = @_;
1163 foreach my $o (@qemu_drive_options) {
1164 next if $o eq 'bootindex';
1165 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1168 foreach my $o (qw(bps bps_rd bps_wr)) {
1169 my $v = $drive->{"m$o"};
1170 $opts .= ",$o=" . int($v*1024*1024) if $v;
1173 # use linux-aio by default (qemu default is threads)
1174 $opts .= ",aio=native" if !$drive->{aio
};
1177 my $volid = $drive->{file
};
1178 if (drive_is_cdrom
($drive)) {
1179 $path = get_iso_path
($storecfg, $vmid, $volid);
1181 if ($volid =~ m
|^/|) {
1184 $path = PVE
::Storage
::path
($storecfg, $volid);
1188 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1190 my $pathinfo = $path ?
"file=$path," : '';
1192 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1195 sub print_netdevice_full
{
1196 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1198 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1200 my $device = $net->{model
};
1201 if ($net->{model
} eq 'virtio') {
1202 $device = 'virtio-net-pci';
1205 # qemu > 0.15 always try to boot from network - we disable that by
1206 # not loading the pxe rom file
1207 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1208 my $pciaddr = print_pci_addr
("$netid", $bridges);
1209 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1210 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1211 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1212 my $vectors = $net->{queues
} * 2 + 2;
1213 $tmpstr .= ",vectors=$vectors,mq=on";
1215 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1219 sub print_netdev_full
{
1220 my ($vmid, $conf, $net, $netid) = @_;
1223 if ($netid =~ m/^net(\d+)$/) {
1227 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1229 my $ifname = "tap${vmid}i$i";
1231 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1232 die "interface name '$ifname' is too long (max 15 character)\n"
1233 if length($ifname) >= 16;
1235 my $vhostparam = '';
1236 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1238 my $vmname = $conf->{name
} || "vm$vmid";
1242 if ($net->{bridge
}) {
1243 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1245 $netdev = "type=user,id=$netid,hostname=$vmname";
1248 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1253 sub drive_is_cdrom
{
1256 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1263 return undef if !$value;
1266 my @list = split(/,/, $value);
1270 foreach my $kv (@list) {
1272 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) {
1275 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1276 $res->{driver
} = $1;
1277 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1278 $res->{rombar
} = $1;
1280 warn "unknown hostpci setting '$kv'\n";
1284 return undef if !$found;
1289 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1295 foreach my $kvp (split(/,/, $data)) {
1297 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1299 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1300 $res->{model
} = $model;
1301 $res->{macaddr
} = $mac;
1302 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1303 $res->{bridge
} = $1;
1304 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1305 $res->{queues
} = $1;
1306 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1308 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1310 } elsif ($kvp =~ m/^firewall=(\d+)$/) {
1311 $res->{firewall
} = $1;
1318 return undef if !$res->{model
};
1326 my $res = "$net->{model}";
1327 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1328 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1329 $res .= ",rate=$net->{rate}" if $net->{rate
};
1330 $res .= ",tag=$net->{tag}" if $net->{tag
};
1331 $res .= ",firewall=$net->{firewall}" if $net->{firewall
};
1336 sub add_random_macs
{
1337 my ($settings) = @_;
1339 foreach my $opt (keys %$settings) {
1340 next if $opt !~ m/^net(\d+)$/;
1341 my $net = parse_net
($settings->{$opt});
1343 $settings->{$opt} = print_net
($net);
1347 sub add_unused_volume
{
1348 my ($config, $volid) = @_;
1351 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1352 my $test = "unused$ind";
1353 if (my $vid = $config->{$test}) {
1354 return if $vid eq $volid; # do not add duplicates
1360 die "To many unused volume - please delete them first.\n" if !$key;
1362 $config->{$key} = $volid;
1367 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1368 sub verify_bootdisk
{
1369 my ($value, $noerr) = @_;
1371 return $value if valid_drivename
($value);
1373 return undef if $noerr;
1375 die "invalid boot disk '$value'\n";
1378 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1380 my ($value, $noerr) = @_;
1382 return $value if parse_net
($value);
1384 return undef if $noerr;
1386 die "unable to parse network options\n";
1389 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1391 my ($value, $noerr) = @_;
1393 return $value if parse_drive
(undef, $value);
1395 return undef if $noerr;
1397 die "unable to parse drive options\n";
1400 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1401 sub verify_hostpci
{
1402 my ($value, $noerr) = @_;
1404 return $value if parse_hostpci
($value);
1406 return undef if $noerr;
1408 die "unable to parse pci id\n";
1411 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1412 sub verify_watchdog
{
1413 my ($value, $noerr) = @_;
1415 return $value if parse_watchdog
($value);
1417 return undef if $noerr;
1419 die "unable to parse watchdog options\n";
1422 sub parse_watchdog
{
1425 return undef if !$value;
1429 foreach my $p (split(/,/, $value)) {
1430 next if $p =~ m/^\s*$/;
1432 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1434 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1435 $res->{action
} = $2;
1444 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1445 sub verify_startup
{
1446 my ($value, $noerr) = @_;
1448 return $value if parse_startup
($value);
1450 return undef if $noerr;
1452 die "unable to parse startup options\n";
1458 return undef if !$value;
1462 foreach my $p (split(/,/, $value)) {
1463 next if $p =~ m/^\s*$/;
1465 if ($p =~ m/^(order=)?(\d+)$/) {
1467 } elsif ($p =~ m/^up=(\d+)$/) {
1469 } elsif ($p =~ m/^down=(\d+)$/) {
1479 sub parse_usb_device
{
1482 return undef if !$value;
1484 my @dl = split(/,/, $value);
1488 foreach my $v (@dl) {
1489 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1491 $res->{vendorid
} = $2;
1492 $res->{productid
} = $4;
1493 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1495 $res->{hostbus
} = $1;
1496 $res->{hostport
} = $2;
1497 } elsif ($v =~ m/^spice$/) {
1504 return undef if !$found;
1509 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1510 sub verify_usb_device
{
1511 my ($value, $noerr) = @_;
1513 return $value if parse_usb_device
($value);
1515 return undef if $noerr;
1517 die "unable to parse usb device\n";
1520 # add JSON properties for create and set function
1521 sub json_config_properties
{
1524 foreach my $opt (keys %$confdesc) {
1525 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1526 $prop->{$opt} = $confdesc->{$opt};
1533 my ($key, $value) = @_;
1535 die "unknown setting '$key'\n" if !$confdesc->{$key};
1537 my $type = $confdesc->{$key}->{type
};
1539 if (!defined($value)) {
1540 die "got undefined value\n";
1543 if ($value =~ m/[\n\r]/) {
1544 die "property contains a line feed\n";
1547 if ($type eq 'boolean') {
1548 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1549 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1550 die "type check ('boolean') failed - got '$value'\n";
1551 } elsif ($type eq 'integer') {
1552 return int($1) if $value =~ m/^(\d+)$/;
1553 die "type check ('integer') failed - got '$value'\n";
1554 } elsif ($type eq 'number') {
1555 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1556 die "type check ('number') failed - got '$value'\n";
1557 } elsif ($type eq 'string') {
1558 if (my $fmt = $confdesc->{$key}->{format
}) {
1559 if ($fmt eq 'pve-qm-drive') {
1560 # special case - we need to pass $key to parse_drive()
1561 my $drive = parse_drive
($key, $value);
1562 return $value if $drive;
1563 die "unable to parse drive options\n";
1565 PVE
::JSONSchema
::check_format
($fmt, $value);
1568 $value =~ s/^\"(.*)\"$/$1/;
1571 die "internal error"
1575 sub lock_config_full
{
1576 my ($vmid, $timeout, $code, @param) = @_;
1578 my $filename = config_file_lock
($vmid);
1580 my $res = lock_file
($filename, $timeout, $code, @param);
1587 sub lock_config_mode
{
1588 my ($vmid, $timeout, $shared, $code, @param) = @_;
1590 my $filename = config_file_lock
($vmid);
1592 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1600 my ($vmid, $code, @param) = @_;
1602 return lock_config_full
($vmid, 10, $code, @param);
1605 sub cfs_config_path
{
1606 my ($vmid, $node) = @_;
1608 $node = $nodename if !$node;
1609 return "nodes/$node/qemu-server/$vmid.conf";
1612 sub check_iommu_support
{
1613 #fixme : need to check IOMMU support
1614 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1622 my ($vmid, $node) = @_;
1624 my $cfspath = cfs_config_path
($vmid, $node);
1625 return "/etc/pve/$cfspath";
1628 sub config_file_lock
{
1631 return "$lock_dir/lock-$vmid.conf";
1637 my $conf = config_file
($vmid);
1638 utime undef, undef, $conf;
1642 my ($storecfg, $vmid, $keep_empty_config) = @_;
1644 my $conffile = config_file
($vmid);
1646 my $conf = load_config
($vmid);
1650 # only remove disks owned by this VM
1651 foreach_drive
($conf, sub {
1652 my ($ds, $drive) = @_;
1654 return if drive_is_cdrom
($drive);
1656 my $volid = $drive->{file
};
1658 return if !$volid || $volid =~ m
|^/|;
1660 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1661 return if !$path || !$owner || ($owner != $vmid);
1663 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1666 if ($keep_empty_config) {
1667 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1672 # also remove unused disk
1674 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1677 PVE
::Storage
::foreach_volid
($dl, sub {
1678 my ($volid, $sid, $volname, $d) = @_;
1679 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1689 my ($vmid, $node) = @_;
1691 my $cfspath = cfs_config_path
($vmid, $node);
1693 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1695 die "no such VM ('$vmid')\n" if !defined($conf);
1700 sub parse_vm_config
{
1701 my ($filename, $raw) = @_;
1703 return undef if !defined($raw);
1706 digest
=> Digest
::SHA
::sha1_hex
($raw),
1710 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1711 || die "got strange filename '$filename'";
1718 my @lines = split(/\n/, $raw);
1719 foreach my $line (@lines) {
1720 next if $line =~ m/^\s*$/;
1722 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1724 $conf->{description
} = $descr if $descr;
1726 $conf = $res->{snapshots
}->{$snapname} = {};
1730 if ($line =~ m/^\#(.*)\s*$/) {
1731 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1735 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1736 $descr .= PVE
::Tools
::decode_text
($2);
1737 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1738 $conf->{snapstate
} = $1;
1739 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1742 $conf->{$key} = $value;
1743 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1746 eval { $value = check_type
($key, $value); };
1748 warn "vm $vmid - unable to parse value of '$key' - $@";
1750 my $fmt = $confdesc->{$key}->{format
};
1751 if ($fmt && $fmt eq 'pve-qm-drive') {
1752 my $v = parse_drive
($key, $value);
1753 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1754 $v->{file
} = $volid;
1755 $value = print_drive
($vmid, $v);
1757 warn "vm $vmid - unable to parse value of '$key'\n";
1762 if ($key eq 'cdrom') {
1763 $conf->{ide2
} = $value;
1765 $conf->{$key} = $value;
1771 $conf->{description
} = $descr if $descr;
1773 delete $res->{snapstate
}; # just to be sure
1778 sub write_vm_config
{
1779 my ($filename, $conf) = @_;
1781 delete $conf->{snapstate
}; # just to be sure
1783 if ($conf->{cdrom
}) {
1784 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1785 $conf->{ide2
} = $conf->{cdrom
};
1786 delete $conf->{cdrom
};
1789 # we do not use 'smp' any longer
1790 if ($conf->{sockets
}) {
1791 delete $conf->{smp
};
1792 } elsif ($conf->{smp
}) {
1793 $conf->{sockets
} = $conf->{smp
};
1794 delete $conf->{cores
};
1795 delete $conf->{smp
};
1798 if ($conf->{maxcpus
} && $conf->{sockets
}) {
1799 delete $conf->{sockets
};
1802 my $used_volids = {};
1804 my $cleanup_config = sub {
1805 my ($cref, $snapname) = @_;
1807 foreach my $key (keys %$cref) {
1808 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1809 $key eq 'snapstate';
1810 my $value = $cref->{$key};
1811 eval { $value = check_type
($key, $value); };
1812 die "unable to parse value of '$key' - $@" if $@;
1814 $cref->{$key} = $value;
1816 if (!$snapname && valid_drivename
($key)) {
1817 my $drive = parse_drive
($key, $value);
1818 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1823 &$cleanup_config($conf);
1824 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1825 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1828 # remove 'unusedX' settings if we re-add a volume
1829 foreach my $key (keys %$conf) {
1830 my $value = $conf->{$key};
1831 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1832 delete $conf->{$key};
1836 my $generate_raw_config = sub {
1841 # add description as comment to top of file
1842 my $descr = $conf->{description
} || '';
1843 foreach my $cl (split(/\n/, $descr)) {
1844 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1847 foreach my $key (sort keys %$conf) {
1848 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1849 $raw .= "$key: $conf->{$key}\n";
1854 my $raw = &$generate_raw_config($conf);
1855 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1856 $raw .= "\n[$snapname]\n";
1857 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1863 sub update_config_nolock
{
1864 my ($vmid, $conf, $skiplock) = @_;
1866 check_lock
($conf) if !$skiplock;
1868 my $cfspath = cfs_config_path
($vmid);
1870 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1874 my ($vmid, $conf, $skiplock) = @_;
1876 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1883 # we use static defaults from our JSON schema configuration
1884 foreach my $key (keys %$confdesc) {
1885 if (defined(my $default = $confdesc->{$key}->{default})) {
1886 $res->{$key} = $default;
1890 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1891 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1897 my $vmlist = PVE
::Cluster
::get_vmlist
();
1899 return $res if !$vmlist || !$vmlist->{ids
};
1900 my $ids = $vmlist->{ids
};
1902 foreach my $vmid (keys %$ids) {
1903 my $d = $ids->{$vmid};
1904 next if !$d->{node
} || $d->{node
} ne $nodename;
1905 next if !$d->{type
} || $d->{type
} ne 'qemu';
1906 $res->{$vmid}->{exists} = 1;
1911 # test if VM uses local resources (to prevent migration)
1912 sub check_local_resources
{
1913 my ($conf, $noerr) = @_;
1917 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1918 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1920 foreach my $k (keys %$conf) {
1921 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1922 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1925 die "VM uses local resources\n" if $loc_res && !$noerr;
1930 # check if used storages are available on all nodes (use by migrate)
1931 sub check_storage_availability
{
1932 my ($storecfg, $conf, $node) = @_;
1934 foreach_drive
($conf, sub {
1935 my ($ds, $drive) = @_;
1937 my $volid = $drive->{file
};
1940 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1943 # check if storage is available on both nodes
1944 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1945 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1949 # list nodes where all VM images are available (used by has_feature API)
1951 my ($conf, $storecfg) = @_;
1953 my $nodelist = PVE
::Cluster
::get_nodelist
();
1954 my $nodehash = { map { $_ => 1 } @$nodelist };
1955 my $nodename = PVE
::INotify
::nodename
();
1957 foreach_drive
($conf, sub {
1958 my ($ds, $drive) = @_;
1960 my $volid = $drive->{file
};
1963 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1965 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1966 if ($scfg->{disable
}) {
1968 } elsif (my $avail = $scfg->{nodes
}) {
1969 foreach my $node (keys %$nodehash) {
1970 delete $nodehash->{$node} if !$avail->{$node};
1972 } elsif (!$scfg->{shared
}) {
1973 foreach my $node (keys %$nodehash) {
1974 delete $nodehash->{$node} if $node ne $nodename
1986 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1990 my ($pidfile, $pid) = @_;
1992 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1996 return undef if !$line;
1997 my @param = split(/\0/, $line);
1999 my $cmd = $param[0];
2000 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2002 for (my $i = 0; $i < scalar (@param); $i++) {
2005 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2006 my $p = $param[$i+1];
2007 return 1 if $p && ($p eq $pidfile);
2016 my ($vmid, $nocheck, $node) = @_;
2018 my $filename = config_file
($vmid, $node);
2020 die "unable to find configuration file for VM $vmid - no such machine\n"
2021 if !$nocheck && ! -f
$filename;
2023 my $pidfile = pidfile_name
($vmid);
2025 if (my $fd = IO
::File-
>new("<$pidfile")) {
2030 my $mtime = $st->mtime;
2031 if ($mtime > time()) {
2032 warn "file '$filename' modified in future\n";
2035 if ($line =~ m/^(\d+)$/) {
2037 if (check_cmdline
($pidfile, $pid)) {
2038 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2050 my $vzlist = config_list
();
2052 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2054 while (defined(my $de = $fd->read)) {
2055 next if $de !~ m/^(\d+)\.pid$/;
2057 next if !defined($vzlist->{$vmid});
2058 if (my $pid = check_running
($vmid)) {
2059 $vzlist->{$vmid}->{pid
} = $pid;
2067 my ($storecfg, $conf) = @_;
2069 my $bootdisk = $conf->{bootdisk
};
2070 return undef if !$bootdisk;
2071 return undef if !valid_drivename
($bootdisk);
2073 return undef if !$conf->{$bootdisk};
2075 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2076 return undef if !defined($drive);
2078 return undef if drive_is_cdrom
($drive);
2080 my $volid = $drive->{file
};
2081 return undef if !$volid;
2083 return $drive->{size
};
2086 my $last_proc_pid_stat;
2088 # get VM status information
2089 # This must be fast and should not block ($full == false)
2090 # We only query KVM using QMP if $full == true (this can be slow)
2092 my ($opt_vmid, $full) = @_;
2096 my $storecfg = PVE
::Storage
::config
();
2098 my $list = vzlist
();
2099 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2101 my $cpucount = $cpuinfo->{cpus
} || 1;
2103 foreach my $vmid (keys %$list) {
2104 next if $opt_vmid && ($vmid ne $opt_vmid);
2106 my $cfspath = cfs_config_path
($vmid);
2107 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2110 $d->{pid
} = $list->{$vmid}->{pid
};
2112 # fixme: better status?
2113 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2115 my $size = disksize
($storecfg, $conf);
2116 if (defined($size)) {
2117 $d->{disk
} = 0; # no info available
2118 $d->{maxdisk
} = $size;
2124 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2125 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2127 $d->{name
} = $conf->{name
} || "VM $vmid";
2128 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2130 if ($conf->{balloon
}) {
2131 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2132 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2143 $d->{diskwrite
} = 0;
2145 $d->{template
} = is_template
($conf);
2150 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2151 foreach my $dev (keys %$netdev) {
2152 next if $dev !~ m/^tap([1-9]\d*)i/;
2154 my $d = $res->{$vmid};
2157 $d->{netout
} += $netdev->{$dev}->{receive
};
2158 $d->{netin
} += $netdev->{$dev}->{transmit
};
2161 my $ctime = gettimeofday
;
2163 foreach my $vmid (keys %$list) {
2165 my $d = $res->{$vmid};
2166 my $pid = $d->{pid
};
2169 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2170 next if !$pstat; # not running
2172 my $used = $pstat->{utime} + $pstat->{stime
};
2174 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2176 if ($pstat->{vsize
}) {
2177 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2180 my $old = $last_proc_pid_stat->{$pid};
2182 $last_proc_pid_stat->{$pid} = {
2190 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2192 if ($dtime > 1000) {
2193 my $dutime = $used - $old->{used
};
2195 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2196 $last_proc_pid_stat->{$pid} = {
2202 $d->{cpu
} = $old->{cpu
};
2206 return $res if !$full;
2208 my $qmpclient = PVE
::QMPClient-
>new();
2210 my $ballooncb = sub {
2211 my ($vmid, $resp) = @_;
2213 my $info = $resp->{'return'};
2214 return if !$info->{max_mem
};
2216 my $d = $res->{$vmid};
2218 # use memory assigned to VM
2219 $d->{maxmem
} = $info->{max_mem
};
2220 $d->{balloon
} = $info->{actual
};
2222 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2223 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2224 $d->{freemem
} = $info->{free_mem
};
2229 my $blockstatscb = sub {
2230 my ($vmid, $resp) = @_;
2231 my $data = $resp->{'return'} || [];
2232 my $totalrdbytes = 0;
2233 my $totalwrbytes = 0;
2234 for my $blockstat (@$data) {
2235 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2236 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2238 $res->{$vmid}->{diskread
} = $totalrdbytes;
2239 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2242 my $statuscb = sub {
2243 my ($vmid, $resp) = @_;
2245 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2246 # this fails if ballon driver is not loaded, so this must be
2247 # the last commnand (following command are aborted if this fails).
2248 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2250 my $status = 'unknown';
2251 if (!defined($status = $resp->{'return'}->{status
})) {
2252 warn "unable to get VM status\n";
2256 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2259 foreach my $vmid (keys %$list) {
2260 next if $opt_vmid && ($vmid ne $opt_vmid);
2261 next if !$res->{$vmid}->{pid
}; # not running
2262 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2265 $qmpclient->queue_execute();
2267 foreach my $vmid (keys %$list) {
2268 next if $opt_vmid && ($vmid ne $opt_vmid);
2269 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2276 my ($conf, $func) = @_;
2278 foreach my $ds (keys %$conf) {
2279 next if !valid_drivename
($ds);
2281 my $drive = parse_drive
($ds, $conf->{$ds});
2284 &$func($ds, $drive);
2289 my ($conf, $func) = @_;
2293 my $test_volid = sub {
2294 my ($volid, $is_cdrom) = @_;
2298 $volhash->{$volid} = $is_cdrom || 0;
2301 foreach_drive
($conf, sub {
2302 my ($ds, $drive) = @_;
2303 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2306 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2307 my $snap = $conf->{snapshots
}->{$snapname};
2308 &$test_volid($snap->{vmstate
}, 0);
2309 foreach_drive
($snap, sub {
2310 my ($ds, $drive) = @_;
2311 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2315 foreach my $volid (keys %$volhash) {
2316 &$func($volid, $volhash->{$volid});
2320 sub vga_conf_has_spice
{
2323 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2328 sub config_to_command
{
2329 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2332 my $globalFlags = [];
2333 my $machineFlags = [];
2339 my $kvmver = kvm_user_version
();
2340 my $vernum = 0; # unknown
2341 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2342 $vernum = $1*1000000+$2*1000;
2343 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2344 $vernum = $1*1000000+$2*1000+$3;
2347 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2349 my $have_ovz = -f
'/proc/vz/vestat';
2351 my $q35 = machine_type_is_q35
($conf);
2353 push @$cmd, '/usr/bin/kvm';
2355 push @$cmd, '-id', $vmid;
2359 my $qmpsocket = qmp_socket
($vmid);
2360 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2361 push @$cmd, '-mon', "chardev=qmp,mode=control";
2363 my $socket = vnc_socket
($vmid);
2364 push @$cmd, '-vnc', "unix:$socket,x509,password";
2366 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2368 push @$cmd, '-daemonize';
2371 # the q35 chipset support native usb2, so we enable usb controller
2372 # by default for this machine type
2373 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2375 $pciaddr = print_pci_addr
("piix3", $bridges);
2376 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2379 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2380 next if !$conf->{"usb$i"};
2383 # include usb device config
2384 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2387 my $vga = $conf->{vga
};
2389 my $qxlnum = vga_conf_has_spice
($vga);
2390 $vga = 'qxl' if $qxlnum;
2393 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2394 $conf->{ostype
} eq 'win7' ||
2395 $conf->{ostype
} eq 'w2k8')) {
2402 # enable absolute mouse coordinates (needed by vnc)
2404 if (defined($conf->{tablet
})) {
2405 $tablet = $conf->{tablet
};
2407 $tablet = $defaults->{tablet
};
2408 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2409 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2412 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2415 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2416 my $d = parse_hostpci
($conf->{"hostpci$i"});
2418 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2419 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2420 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar";
2424 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2425 my $d = parse_usb_device
($conf->{"usb$i"});
2427 if ($d->{vendorid
} && $d->{productid
}) {
2428 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2429 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2430 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2431 } elsif ($d->{spice
}) {
2432 # usb redir support for spice
2433 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2434 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2439 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2440 if (my $path = $conf->{"serial$i"}) {
2441 if ($path eq 'socket') {
2442 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2443 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2444 push @$devices, '-device', "isa-serial,chardev=serial$i";
2446 die "no such serial device\n" if ! -c
$path;
2447 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2448 push @$devices, '-device', "isa-serial,chardev=serial$i";
2454 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2455 if (my $path = $conf->{"parallel$i"}) {
2456 die "no such parallel device\n" if ! -c
$path;
2457 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2458 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2459 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2463 my $vmname = $conf->{name
} || "vm$vmid";
2465 push @$cmd, '-name', $vmname;
2468 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2469 $sockets = $conf->{sockets
} if $conf->{sockets
};
2471 my $cores = $conf->{cores
} || 1;
2472 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2475 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2477 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2480 push @$cmd, '-nodefaults';
2482 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2484 my $bootindex_hash = {};
2486 foreach my $o (split(//, $bootorder)) {
2487 $bootindex_hash->{$o} = $i*100;
2491 push @$cmd, '-boot', "menu=on";
2493 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2495 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2497 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2500 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2502 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2503 my $useLocaltime = $conf->{localtime};
2505 if (my $ost = $conf->{ostype
}) {
2506 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2508 if ($ost =~ m/^w/) { # windows
2509 $useLocaltime = 1 if !defined($conf->{localtime});
2511 # use time drift fix when acpi is enabled
2512 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2513 $tdf = 1 if !defined($conf->{tdf
});
2517 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2519 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2520 push @$cmd, '-no-hpet';
2521 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2522 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2525 if ($ost eq 'win7' || $ost eq 'win8') {
2526 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2530 push @$rtcFlags, 'driftfix=slew' if $tdf;
2533 push @$machineFlags, 'accel=tcg';
2535 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2538 my $machine_type = $forcemachine || $conf->{machine
};
2539 if ($machine_type) {
2540 push @$machineFlags, "type=${machine_type}";
2543 if ($conf->{startdate
}) {
2544 push @$rtcFlags, "base=$conf->{startdate}";
2545 } elsif ($useLocaltime) {
2546 push @$rtcFlags, 'base=localtime';
2549 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2550 $cpu = $conf->{cpu
} if $conf->{cpu
};
2552 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2554 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2556 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2558 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2560 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2562 # Note: enforce needs kernel 3.10, so we do not use it for now
2563 # push @$cmd, '-cpu', "$cpu,enforce";
2564 push @$cmd, '-cpu', $cpu;
2566 push @$cmd, '-S' if $conf->{freeze
};
2568 # set keyboard layout
2569 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2570 push @$cmd, '-k', $kb if $kb;
2573 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2574 #push @$cmd, '-soundhw', 'es1370';
2575 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2577 if($conf->{agent
}) {
2578 my $qgasocket = qga_socket
($vmid);
2579 my $pciaddr = print_pci_addr
("qga0", $bridges);
2580 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2581 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2582 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2589 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2590 for(my $i = 1; $i < $qxlnum; $i++){
2591 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2592 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2595 # assume other OS works like Linux
2596 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2597 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2601 my $pciaddr = print_pci_addr
("spice", $bridges);
2603 $spice_port = PVE
::Tools
::next_spice_port
();
2605 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2607 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2608 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2609 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2612 # enable balloon by default, unless explicitly disabled
2613 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2614 $pciaddr = print_pci_addr
("balloon0", $bridges);
2615 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2618 if ($conf->{watchdog
}) {
2619 my $wdopts = parse_watchdog
($conf->{watchdog
});
2620 $pciaddr = print_pci_addr
("watchdog", $bridges);
2621 my $watchdog = $wdopts->{model
} || 'i6300esb';
2622 push @$devices, '-device', "$watchdog$pciaddr";
2623 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2627 my $scsicontroller = {};
2628 my $ahcicontroller = {};
2629 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2631 # Add iscsi initiator name if available
2632 if (my $initiator = get_initiator_name
()) {
2633 push @$devices, '-iscsi', "initiator-name=$initiator";
2636 foreach_drive
($conf, sub {
2637 my ($ds, $drive) = @_;
2639 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2640 push @$vollist, $drive->{file
};
2643 $use_virtio = 1 if $ds =~ m/^virtio/;
2645 if (drive_is_cdrom
($drive)) {
2646 if ($bootindex_hash->{d
}) {
2647 $drive->{bootindex
} = $bootindex_hash->{d
};
2648 $bootindex_hash->{d
} += 1;
2651 if ($bootindex_hash->{c
}) {
2652 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2653 $bootindex_hash->{c
} += 1;
2657 if ($drive->{interface
} eq 'scsi') {
2659 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2660 my $controller = int($drive->{index} / $maxdev);
2661 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2662 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2663 $scsicontroller->{$controller}=1;
2666 if ($drive->{interface
} eq 'sata') {
2667 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2668 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2669 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2670 $ahcicontroller->{$controller}=1;
2673 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
2674 push @$devices, '-drive',$drive_cmd;
2675 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2678 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2680 for (my $i = 0; $i < $MAX_NETS; $i++) {
2681 next if !$conf->{"net$i"};
2682 my $d = parse_net
($conf->{"net$i"});
2685 $use_virtio = 1 if $d->{model
} eq 'virtio';
2687 if ($bootindex_hash->{n
}) {
2688 $d->{bootindex
} = $bootindex_hash->{n
};
2689 $bootindex_hash->{n
} += 1;
2692 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2693 push @$devices, '-netdev', $netdevfull;
2695 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2696 push @$devices, '-device', $netdevicefull;
2701 while (my ($k, $v) = each %$bridges) {
2702 $pciaddr = print_pci_addr
("pci.$k");
2703 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2707 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2708 # when the VM uses virtio devices.
2709 if (!$use_virtio && $have_ovz) {
2711 my $cpuunits = defined($conf->{cpuunits
}) ?
2712 $conf->{cpuunits
} : $defaults->{cpuunits
};
2714 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2716 # fixme: cpulimit is currently ignored
2717 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2721 if ($conf->{args
}) {
2722 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2726 push @$cmd, @$devices;
2727 push @$cmd, '-rtc', join(',', @$rtcFlags)
2728 if scalar(@$rtcFlags);
2729 push @$cmd, '-machine', join(',', @$machineFlags)
2730 if scalar(@$machineFlags);
2731 push @$cmd, '-global', join(',', @$globalFlags)
2732 if scalar(@$globalFlags);
2734 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2739 return "${var_run_tmpdir}/$vmid.vnc";
2745 my $res = vm_mon_cmd
($vmid, 'query-spice');
2747 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2752 return "${var_run_tmpdir}/$vmid.qmp";
2757 return "${var_run_tmpdir}/$vmid.qga";
2762 return "${var_run_tmpdir}/$vmid.pid";
2765 sub vm_devices_list
{
2768 my $res = vm_mon_cmd
($vmid, 'query-pci');
2771 foreach my $pcibus (@$res) {
2772 foreach my $device (@{$pcibus->{devices
}}) {
2773 next if !$device->{'qdev_id'};
2774 $devices->{$device->{'qdev_id'}} = $device;
2782 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2784 return 1 if !check_running
($vmid);
2786 my $q35 = machine_type_is_q35
($conf);
2788 if ($deviceid eq 'tablet') {
2789 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
2793 return 1 if !$conf->{hotplug
};
2795 my $devices_list = vm_devices_list
($vmid);
2796 return 1 if defined($devices_list->{$deviceid});
2798 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2800 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2801 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2802 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2803 qemu_deviceadd
($vmid, $devicefull);
2804 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2805 qemu_drivedel
($vmid, $deviceid);
2810 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2811 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2812 my $pciaddr = print_pci_addr
($deviceid);
2813 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2814 qemu_deviceadd
($vmid, $devicefull);
2815 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2818 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2819 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2820 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2821 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2822 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2823 if(!qemu_deviceadd
($vmid, $devicefull)) {
2824 qemu_drivedel
($vmid, $deviceid);
2829 if ($deviceid =~ m/^(net)(\d+)$/) {
2830 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2831 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2832 qemu_deviceadd
($vmid, $netdevicefull);
2833 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2834 qemu_netdevdel
($vmid, $deviceid);
2840 if (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
2842 my $pciaddr = print_pci_addr
($deviceid);
2843 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2844 qemu_deviceadd
($vmid, $devicefull);
2845 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2851 sub vm_deviceunplug
{
2852 my ($vmid, $conf, $deviceid) = @_;
2854 return 1 if !check_running
($vmid);
2856 if ($deviceid eq 'tablet') {
2857 qemu_devicedel
($vmid, $deviceid);
2861 return 1 if !$conf->{hotplug
};
2863 my $devices_list = vm_devices_list
($vmid);
2864 return 1 if !defined($devices_list->{$deviceid});
2866 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2868 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2869 qemu_devicedel
($vmid, $deviceid);
2870 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2871 return undef if !qemu_drivedel
($vmid, $deviceid);
2874 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2875 return undef if !qemu_devicedel
($vmid, $deviceid);
2878 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2879 return undef if !qemu_devicedel
($vmid, $deviceid);
2880 return undef if !qemu_drivedel
($vmid, $deviceid);
2883 if ($deviceid =~ m/^(net)(\d+)$/) {
2884 qemu_devicedel
($vmid, $deviceid);
2885 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2886 return undef if !qemu_netdevdel
($vmid, $deviceid);
2892 sub qemu_deviceadd
{
2893 my ($vmid, $devicefull) = @_;
2895 $devicefull = "driver=".$devicefull;
2896 my %options = split(/[=,]/, $devicefull);
2898 vm_mon_cmd
($vmid, "device_add" , %options);
2902 sub qemu_devicedel
{
2903 my($vmid, $deviceid) = @_;
2904 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2909 my($storecfg, $vmid, $device) = @_;
2911 my $drive = print_drive_full
($storecfg, $vmid, $device);
2912 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2913 # If the command succeeds qemu prints: "OK"
2914 if ($ret !~ m/OK/s) {
2915 syslog
("err", "adding drive failed: $ret");
2922 my($vmid, $deviceid) = @_;
2924 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2926 if ($ret =~ m/Device \'.*?\' not found/s) {
2927 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2929 elsif ($ret ne "") {
2930 syslog
("err", "deleting drive $deviceid failed : $ret");
2936 sub qemu_deviceaddverify
{
2937 my ($vmid,$deviceid) = @_;
2939 for (my $i = 0; $i <= 5; $i++) {
2940 my $devices_list = vm_devices_list
($vmid);
2941 return 1 if defined($devices_list->{$deviceid});
2944 syslog
("err", "error on hotplug device $deviceid");
2949 sub qemu_devicedelverify
{
2950 my ($vmid,$deviceid) = @_;
2952 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2953 for (my $i = 0; $i <= 5; $i++) {
2954 my $devices_list = vm_devices_list
($vmid);
2955 return 1 if !defined($devices_list->{$deviceid});
2958 syslog
("err", "error on hot-unplugging device $deviceid");
2962 sub qemu_findorcreatescsihw
{
2963 my ($storecfg, $conf, $vmid, $device) = @_;
2965 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2966 my $controller = int($device->{index} / $maxdev);
2967 my $scsihwid="scsihw$controller";
2968 my $devices_list = vm_devices_list
($vmid);
2970 if(!defined($devices_list->{$scsihwid})) {
2971 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2976 sub qemu_bridgeadd
{
2977 my ($storecfg, $conf, $vmid, $device) = @_;
2980 my $bridgeid = undef;
2981 print_pci_addr
($device, $bridges);
2983 while (my ($k, $v) = each %$bridges) {
2986 return if !$bridgeid || $bridgeid < 1;
2987 my $bridge = "pci.$bridgeid";
2988 my $devices_list = vm_devices_list
($vmid);
2990 if(!defined($devices_list->{$bridge})) {
2991 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2996 sub qemu_netdevadd
{
2997 my ($vmid, $conf, $device, $deviceid) = @_;
2999 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
3000 my %options = split(/[=,]/, $netdev);
3002 vm_mon_cmd
($vmid, "netdev_add", %options);
3006 sub qemu_netdevdel
{
3007 my ($vmid, $deviceid) = @_;
3009 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
3013 sub qemu_cpu_hotplug
{
3014 my ($vmid, $conf, $cores) = @_;
3016 die "new cores config is not defined" if !$cores;
3017 die "you can't add more cores than maxcpus"
3018 if $conf->{maxcpus
} && ($cores > $conf->{maxcpus
});
3019 return if !check_running
($vmid);
3021 my $currentcores = $conf->{cores
} if $conf->{cores
};
3022 die "current cores is not defined" if !$currentcores;
3023 die "maxcpus is not defined" if !$conf->{maxcpus
};
3024 raise_param_exc
({ 'cores' => "online cpu unplug is not yet possible" })
3025 if($cores < $currentcores);
3027 my $currentrunningcores = vm_mon_cmd
($vmid, "query-cpus");
3028 raise_param_exc
({ 'cores' => "cores number if running vm is different than configuration" })
3029 if scalar (@{$currentrunningcores}) != $currentcores;
3031 for(my $i = $currentcores; $i < $cores; $i++) {
3032 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
3036 sub qemu_block_set_io_throttle
{
3037 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3039 return if !check_running
($vmid) ;
3041 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));
3045 # old code, only used to shutdown old VM after update
3047 my ($fh, $timeout) = @_;
3049 my $sel = new IO
::Select
;
3056 while (scalar (@ready = $sel->can_read($timeout))) {
3058 if ($count = $fh->sysread($buf, 8192)) {
3059 if ($buf =~ /^(.*)\(qemu\) $/s) {
3066 if (!defined($count)) {
3073 die "monitor read timeout\n" if !scalar(@ready);
3078 # old code, only used to shutdown old VM after update
3079 sub vm_monitor_command
{
3080 my ($vmid, $cmdstr, $nocheck) = @_;
3085 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3087 my $sname = "${var_run_tmpdir}/$vmid.mon";
3089 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3090 die "unable to connect to VM $vmid socket - $!\n";
3094 # hack: migrate sometime blocks the monitor (when migrate_downtime
3096 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3097 $timeout = 60*60; # 1 hour
3101 my $data = __read_avail
($sock, $timeout);
3103 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3104 die "got unexpected qemu monitor banner\n";
3107 my $sel = new IO
::Select
;
3110 if (!scalar(my @ready = $sel->can_write($timeout))) {
3111 die "monitor write error - timeout";
3114 my $fullcmd = "$cmdstr\r";
3116 # syslog('info', "VM $vmid monitor command: $cmdstr");
3119 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3120 die "monitor write error - $!";
3123 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3127 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3128 $timeout = 60*60; # 1 hour
3129 } elsif ($cmdstr =~ m/^(eject|change)/) {
3130 $timeout = 60; # note: cdrom mount command is slow
3132 if ($res = __read_avail
($sock, $timeout)) {
3134 my @lines = split("\r?\n", $res);
3136 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3138 $res = join("\n", @lines);
3146 syslog
("err", "VM $vmid monitor command failed - $err");
3153 sub qemu_block_resize
{
3154 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3156 my $running = check_running
($vmid);
3158 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3160 return if !$running;
3162 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3166 sub qemu_volume_snapshot
{
3167 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3169 my $running = check_running
($vmid);
3171 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3173 return if !$running;
3175 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3179 sub qemu_volume_snapshot_delete
{
3180 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3182 my $running = check_running
($vmid);
3184 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3186 return if !$running;
3188 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3194 #need to impplement call to qemu-ga
3197 sub qga_unfreezefs
{
3200 #need to impplement call to qemu-ga
3203 sub set_migration_caps
{
3209 "auto-converge" => 1,
3211 "x-rdma-pin-all" => 0,
3215 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3217 for my $supported_capability (@$supported_capabilities) {
3219 capability
=> $supported_capability->{capability
},
3220 state => $enabled_cap->{$supported_capability->{capability
}} ? JSON
::true
: JSON
::false
,
3224 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3228 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3230 lock_config
($vmid, sub {
3231 my $conf = load_config
($vmid, $migratedfrom);
3233 die "you can't start a vm if it's a template\n" if is_template
($conf);
3235 check_lock
($conf) if !$skiplock;
3237 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3239 my $defaults = load_defaults
();
3241 # set environment variable useful inside network script
3242 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3244 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3246 my $migrate_port = 0;
3249 if ($statefile eq 'tcp') {
3250 my $localip = "localhost";
3251 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3252 if ($datacenterconf->{migration_unsecure
}) {
3253 my $nodename = PVE
::INotify
::nodename
();
3254 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3256 $migrate_port = PVE
::Tools
::next_migrate_port
();
3257 $migrate_uri = "tcp:${localip}:${migrate_port}";
3258 push @$cmd, '-incoming', $migrate_uri;
3261 push @$cmd, '-loadstate', $statefile;
3268 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3269 my $d = parse_hostpci
($conf->{"hostpci$i"});
3271 my $info = pci_device_info
("0000:$d->{pciid}");
3272 die "IOMMU not present\n" if !check_iommu_support
();
3273 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3274 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3275 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3278 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3280 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3283 die "start failed: $err" if $err;
3285 print "migration listens on $migrate_uri\n" if $migrate_uri;
3287 if ($statefile && $statefile ne 'tcp') {
3288 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3292 if ($migratedfrom) {
3295 PVE
::QemuServer
::set_migration_caps
($vmid);
3300 print "spice listens on port $spice_port\n";
3301 if ($spice_ticket) {
3302 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3303 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3309 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3310 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3311 if $conf->{balloon
};
3312 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3313 path
=> "machine/peripheral/balloon0",
3314 property
=> "guest-stats-polling-interval",
3322 my ($vmid, $execute, %params) = @_;
3324 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3325 vm_qmp_command
($vmid, $cmd);
3328 sub vm_mon_cmd_nocheck
{
3329 my ($vmid, $execute, %params) = @_;
3331 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3332 vm_qmp_command
($vmid, $cmd, 1);
3335 sub vm_qmp_command
{
3336 my ($vmid, $cmd, $nocheck) = @_;
3341 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3342 $timeout = $cmd->{arguments
}->{timeout
};
3343 delete $cmd->{arguments
}->{timeout
};
3347 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3348 my $sname = qmp_socket
($vmid);
3350 my $qmpclient = PVE
::QMPClient-
>new();
3352 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3353 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3354 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3355 if scalar(%{$cmd->{arguments
}});
3356 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3358 die "unable to open monitor socket\n";
3362 syslog
("err", "VM $vmid qmp command failed - $err");
3369 sub vm_human_monitor_command
{
3370 my ($vmid, $cmdline) = @_;
3375 execute
=> 'human-monitor-command',
3376 arguments
=> { 'command-line' => $cmdline},
3379 return vm_qmp_command
($vmid, $cmd);
3382 sub vm_commandline
{
3383 my ($storecfg, $vmid) = @_;
3385 my $conf = load_config
($vmid);
3387 my $defaults = load_defaults
();
3389 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3391 return join(' ', @$cmd);
3395 my ($vmid, $skiplock) = @_;
3397 lock_config
($vmid, sub {
3399 my $conf = load_config
($vmid);
3401 check_lock
($conf) if !$skiplock;
3403 vm_mon_cmd
($vmid, "system_reset");
3407 sub get_vm_volumes
{
3411 foreach_volid
($conf, sub {
3412 my ($volid, $is_cdrom) = @_;
3414 return if $volid =~ m
|^/|;
3416 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3419 push @$vollist, $volid;
3425 sub vm_stop_cleanup
{
3426 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3429 fairsched_rmnod
($vmid); # try to destroy group
3432 my $vollist = get_vm_volumes
($conf);
3433 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3436 foreach my $ext (qw(mon qmp pid vnc qga)) {
3437 unlink "/var/run/qemu-server/${vmid}.$ext";
3440 warn $@ if $@; # avoid errors - just warn
3443 # Note: use $nockeck to skip tests if VM configuration file exists.
3444 # We need that when migration VMs to other nodes (files already moved)
3445 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3447 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3449 $force = 1 if !defined($force) && !$shutdown;
3452 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3453 kill 15, $pid if $pid;
3454 my $conf = load_config
($vmid, $migratedfrom);
3455 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3459 lock_config
($vmid, sub {
3461 my $pid = check_running
($vmid, $nocheck);
3466 $conf = load_config
($vmid);
3467 check_lock
($conf) if !$skiplock;
3468 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3469 my $opts = parse_startup
($conf->{startup
});
3470 $timeout = $opts->{down
} if $opts->{down
};
3474 $timeout = 60 if !defined($timeout);
3478 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3481 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3488 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3493 if ($count >= $timeout) {
3495 warn "VM still running - terminating now with SIGTERM\n";
3498 die "VM quit/powerdown failed - got timeout\n";
3501 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3506 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3509 die "VM quit/powerdown failed\n";
3517 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3522 if ($count >= $timeout) {
3523 warn "VM still running - terminating now with SIGKILL\n";
3528 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3533 my ($vmid, $skiplock) = @_;
3535 lock_config
($vmid, sub {
3537 my $conf = load_config
($vmid);
3539 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3541 vm_mon_cmd
($vmid, "stop");
3546 my ($vmid, $skiplock) = @_;
3548 lock_config
($vmid, sub {
3550 my $conf = load_config
($vmid);
3552 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3554 vm_mon_cmd
($vmid, "cont");
3559 my ($vmid, $skiplock, $key) = @_;
3561 lock_config
($vmid, sub {
3563 my $conf = load_config
($vmid);
3565 # there is no qmp command, so we use the human monitor command
3566 vm_human_monitor_command
($vmid, "sendkey $key");
3571 my ($storecfg, $vmid, $skiplock) = @_;
3573 lock_config
($vmid, sub {
3575 my $conf = load_config
($vmid);
3577 check_lock
($conf) if !$skiplock;
3579 if (!check_running
($vmid)) {
3580 fairsched_rmnod
($vmid); # try to destroy group
3581 destroy_vm
($storecfg, $vmid);
3583 die "VM $vmid is running - destroy failed\n";
3591 my ($filename, $buf) = @_;
3593 my $fh = IO
::File-
>new($filename, "w");
3594 return undef if !$fh;
3596 my $res = print $fh $buf;
3603 sub pci_device_info
{
3608 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3609 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3611 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3612 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3614 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3615 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3617 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3618 return undef if !defined($product) || $product !~ s/^0x//;
3623 product
=> $product,
3629 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3638 my $name = $dev->{name
};
3640 my $fn = "$pcisysfs/devices/$name/reset";
3642 return file_write
($fn, "1");
3645 sub pci_dev_bind_to_stub
{
3648 my $name = $dev->{name
};
3650 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3651 return 1 if -d
$testdir;
3653 my $data = "$dev->{vendor} $dev->{product}";
3654 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3656 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3657 if (!file_write
($fn, $name)) {
3658 return undef if -f
$fn;
3661 $fn = "$pcisysfs/drivers/pci-stub/bind";
3662 if (! -d
$testdir) {
3663 return undef if !file_write
($fn, $name);
3669 sub print_pci_addr
{
3670 my ($id, $bridges) = @_;
3674 piix3
=> { bus
=> 0, addr
=> 1 },
3675 #addr2 : first videocard
3676 balloon0
=> { bus
=> 0, addr
=> 3 },
3677 watchdog
=> { bus
=> 0, addr
=> 4 },
3678 scsihw0
=> { bus
=> 0, addr
=> 5 },
3679 scsihw1
=> { bus
=> 0, addr
=> 6 },
3680 ahci0
=> { bus
=> 0, addr
=> 7 },
3681 qga0
=> { bus
=> 0, addr
=> 8 },
3682 spice
=> { bus
=> 0, addr
=> 9 },
3683 virtio0
=> { bus
=> 0, addr
=> 10 },
3684 virtio1
=> { bus
=> 0, addr
=> 11 },
3685 virtio2
=> { bus
=> 0, addr
=> 12 },
3686 virtio3
=> { bus
=> 0, addr
=> 13 },
3687 virtio4
=> { bus
=> 0, addr
=> 14 },
3688 virtio5
=> { bus
=> 0, addr
=> 15 },
3689 hostpci0
=> { bus
=> 0, addr
=> 16 },
3690 hostpci1
=> { bus
=> 0, addr
=> 17 },
3691 net0
=> { bus
=> 0, addr
=> 18 },
3692 net1
=> { bus
=> 0, addr
=> 19 },
3693 net2
=> { bus
=> 0, addr
=> 20 },
3694 net3
=> { bus
=> 0, addr
=> 21 },
3695 net4
=> { bus
=> 0, addr
=> 22 },
3696 net5
=> { bus
=> 0, addr
=> 23 },
3697 vga1
=> { bus
=> 0, addr
=> 24 },
3698 vga2
=> { bus
=> 0, addr
=> 25 },
3699 vga3
=> { bus
=> 0, addr
=> 26 },
3700 #addr29 : usb-host (pve-usb.cfg)
3701 'pci.1' => { bus
=> 0, addr
=> 30 },
3702 'pci.2' => { bus
=> 0, addr
=> 31 },
3703 'net6' => { bus
=> 1, addr
=> 1 },
3704 'net7' => { bus
=> 1, addr
=> 2 },
3705 'net8' => { bus
=> 1, addr
=> 3 },
3706 'net9' => { bus
=> 1, addr
=> 4 },
3707 'net10' => { bus
=> 1, addr
=> 5 },
3708 'net11' => { bus
=> 1, addr
=> 6 },
3709 'net12' => { bus
=> 1, addr
=> 7 },
3710 'net13' => { bus
=> 1, addr
=> 8 },
3711 'net14' => { bus
=> 1, addr
=> 9 },
3712 'net15' => { bus
=> 1, addr
=> 10 },
3713 'net16' => { bus
=> 1, addr
=> 11 },
3714 'net17' => { bus
=> 1, addr
=> 12 },
3715 'net18' => { bus
=> 1, addr
=> 13 },
3716 'net19' => { bus
=> 1, addr
=> 14 },
3717 'net20' => { bus
=> 1, addr
=> 15 },
3718 'net21' => { bus
=> 1, addr
=> 16 },
3719 'net22' => { bus
=> 1, addr
=> 17 },
3720 'net23' => { bus
=> 1, addr
=> 18 },
3721 'net24' => { bus
=> 1, addr
=> 19 },
3722 'net25' => { bus
=> 1, addr
=> 20 },
3723 'net26' => { bus
=> 1, addr
=> 21 },
3724 'net27' => { bus
=> 1, addr
=> 22 },
3725 'net28' => { bus
=> 1, addr
=> 23 },
3726 'net29' => { bus
=> 1, addr
=> 24 },
3727 'net30' => { bus
=> 1, addr
=> 25 },
3728 'net31' => { bus
=> 1, addr
=> 26 },
3729 'virtio6' => { bus
=> 2, addr
=> 1 },
3730 'virtio7' => { bus
=> 2, addr
=> 2 },
3731 'virtio8' => { bus
=> 2, addr
=> 3 },
3732 'virtio9' => { bus
=> 2, addr
=> 4 },
3733 'virtio10' => { bus
=> 2, addr
=> 5 },
3734 'virtio11' => { bus
=> 2, addr
=> 6 },
3735 'virtio12' => { bus
=> 2, addr
=> 7 },
3736 'virtio13' => { bus
=> 2, addr
=> 8 },
3737 'virtio14' => { bus
=> 2, addr
=> 9 },
3738 'virtio15' => { bus
=> 2, addr
=> 10 },
3741 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3742 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3743 my $bus = $devices->{$id}->{bus
};
3744 $res = ",bus=pci.$bus,addr=$addr";
3745 $bridges->{$bus} = 1 if $bridges;
3751 # vzdump restore implementaion
3753 sub tar_archive_read_firstfile
{
3754 my $archive = shift;
3756 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3758 # try to detect archive type first
3759 my $pid = open (TMP
, "tar tf '$archive'|") ||
3760 die "unable to open file '$archive'\n";
3761 my $firstfile = <TMP
>;
3765 die "ERROR: archive contaions no data\n" if !$firstfile;
3771 sub tar_restore_cleanup
{
3772 my ($storecfg, $statfile) = @_;
3774 print STDERR
"starting cleanup\n";
3776 if (my $fd = IO
::File-
>new($statfile, "r")) {
3777 while (defined(my $line = <$fd>)) {
3778 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3781 if ($volid =~ m
|^/|) {
3782 unlink $volid || die 'unlink failed\n';
3784 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3786 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3788 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3790 print STDERR
"unable to parse line in statfile - $line";
3797 sub restore_archive
{
3798 my ($archive, $vmid, $user, $opts) = @_;
3800 my $format = $opts->{format
};
3803 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3804 $format = 'tar' if !$format;
3806 } elsif ($archive =~ m/\.tar$/) {
3807 $format = 'tar' if !$format;
3808 } elsif ($archive =~ m/.tar.lzo$/) {
3809 $format = 'tar' if !$format;
3811 } elsif ($archive =~ m/\.vma$/) {
3812 $format = 'vma' if !$format;
3813 } elsif ($archive =~ m/\.vma\.gz$/) {
3814 $format = 'vma' if !$format;
3816 } elsif ($archive =~ m/\.vma\.lzo$/) {
3817 $format = 'vma' if !$format;
3820 $format = 'vma' if !$format; # default
3823 # try to detect archive format
3824 if ($format eq 'tar') {
3825 return restore_tar_archive
($archive, $vmid, $user, $opts);
3827 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3831 sub restore_update_config_line
{
3832 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3834 return if $line =~ m/^\#qmdump\#/;
3835 return if $line =~ m/^\#vzdump\#/;
3836 return if $line =~ m/^lock:/;
3837 return if $line =~ m/^unused\d+:/;
3838 return if $line =~ m/^parent:/;
3839 return if $line =~ m/^template:/; # restored VM is never a template
3841 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3842 # try to convert old 1.X settings
3843 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3844 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3845 my ($model, $macaddr) = split(/\=/, $devconfig);
3846 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3849 bridge
=> "vmbr$ind",
3850 macaddr
=> $macaddr,
3852 my $netstr = print_net
($net);
3854 print $outfd "net$cookie->{netcount}: $netstr\n";
3855 $cookie->{netcount
}++;
3857 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3858 my ($id, $netstr) = ($1, $2);
3859 my $net = parse_net
($netstr);
3860 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3861 $netstr = print_net
($net);
3862 print $outfd "$id: $netstr\n";
3863 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3866 if ($line =~ m/backup=no/) {
3867 print $outfd "#$line";
3868 } elsif ($virtdev && $map->{$virtdev}) {
3869 my $di = parse_drive
($virtdev, $value);
3870 delete $di->{format
}; # format can change on restore
3871 $di->{file
} = $map->{$virtdev};
3872 $value = print_drive
($vmid, $di);
3873 print $outfd "$virtdev: $value\n";
3883 my ($cfg, $vmid) = @_;
3885 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3887 my $volid_hash = {};
3888 foreach my $storeid (keys %$info) {
3889 foreach my $item (@{$info->{$storeid}}) {
3890 next if !($item->{volid
} && $item->{size
});
3891 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3892 $volid_hash->{$item->{volid
}} = $item;
3899 sub get_used_paths
{
3900 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3904 my $scan_config = sub {
3905 my ($cref, $snapname) = @_;
3907 foreach my $key (keys %$cref) {
3908 my $value = $cref->{$key};
3909 if (valid_drivename
($key)) {
3910 next if $skip_drive && $key eq $skip_drive;
3911 my $drive = parse_drive
($key, $value);
3912 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3913 if ($drive->{file
} =~ m!^/!) {
3914 $used_path->{$drive->{file
}}++; # = 1;
3916 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3918 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3920 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3921 $used_path->{$path}++; # = 1;
3927 &$scan_config($conf);
3931 if ($scan_snapshots) {
3932 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3933 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3940 sub update_disksize
{
3941 my ($vmid, $conf, $volid_hash) = @_;
3947 # Note: it is allowed to define multiple storages with same path (alias), so
3948 # we need to check both 'volid' and real 'path' (two different volid can point
3949 # to the same path).
3954 foreach my $opt (keys %$conf) {
3955 if (valid_drivename
($opt)) {
3956 my $drive = parse_drive
($opt, $conf->{$opt});
3957 my $volid = $drive->{file
};
3960 $used->{$volid} = 1;
3961 if ($volid_hash->{$volid} &&
3962 (my $path = $volid_hash->{$volid}->{path
})) {
3963 $usedpath->{$path} = 1;
3966 next if drive_is_cdrom
($drive);
3967 next if !$volid_hash->{$volid};
3969 $drive->{size
} = $volid_hash->{$volid}->{size
};
3970 my $new = print_drive
($vmid, $drive);
3971 if ($new ne $conf->{$opt}) {
3973 $conf->{$opt} = $new;
3978 # remove 'unusedX' entry if volume is used
3979 foreach my $opt (keys %$conf) {
3980 next if $opt !~ m/^unused\d+$/;
3981 my $volid = $conf->{$opt};
3982 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3983 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3985 delete $conf->{$opt};
3989 foreach my $volid (sort keys %$volid_hash) {
3990 next if $volid =~ m/vm-$vmid-state-/;
3991 next if $used->{$volid};
3992 my $path = $volid_hash->{$volid}->{path
};
3993 next if !$path; # just to be sure
3994 next if $usedpath->{$path};
3996 add_unused_volume
($conf, $volid);
3997 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
4004 my ($vmid, $nolock) = @_;
4006 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
4008 my $volid_hash = scan_volids
($cfg, $vmid);
4010 my $updatefn = sub {
4013 my $conf = load_config
($vmid);
4018 foreach my $volid (keys %$volid_hash) {
4019 my $info = $volid_hash->{$volid};
4020 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
4023 my $changes = update_disksize
($vmid, $conf, $vm_volids);
4025 update_config_nolock
($vmid, $conf, 1) if $changes;
4028 if (defined($vmid)) {
4032 lock_config
($vmid, $updatefn, $vmid);
4035 my $vmlist = config_list
();
4036 foreach my $vmid (keys %$vmlist) {
4040 lock_config
($vmid, $updatefn, $vmid);
4046 sub restore_vma_archive
{
4047 my ($archive, $vmid, $user, $opts, $comp) = @_;
4049 my $input = $archive eq '-' ?
"<&STDIN" : undef;
4050 my $readfrom = $archive;
4055 my $qarchive = PVE
::Tools
::shellquote
($archive);
4056 if ($comp eq 'gzip') {
4057 $uncomp = "zcat $qarchive|";
4058 } elsif ($comp eq 'lzop') {
4059 $uncomp = "lzop -d -c $qarchive|";
4061 die "unknown compression method '$comp'\n";
4066 my $tmpdir = "/var/tmp/vzdumptmp$$";
4069 # disable interrupts (always do cleanups)
4070 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4071 warn "got interrupt - ignored\n";
4074 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4075 POSIX
::mkfifo
($mapfifo, 0600);
4078 my $openfifo = sub {
4079 open($fifofh, '>', $mapfifo) || die $!;
4082 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4089 my $rpcenv = PVE
::RPCEnvironment
::get
();
4091 my $conffile = config_file
($vmid);
4092 my $tmpfn = "$conffile.$$.tmp";
4094 # Note: $oldconf is undef if VM does not exists
4095 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4097 my $print_devmap = sub {
4098 my $virtdev_hash = {};
4100 my $cfgfn = "$tmpdir/qemu-server.conf";
4102 # we can read the config - that is already extracted
4103 my $fh = IO
::File-
>new($cfgfn, "r") ||
4104 "unable to read qemu-server.conf - $!\n";
4106 while (defined(my $line = <$fh>)) {
4107 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4108 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4109 die "archive does not contain data for drive '$virtdev'\n"
4110 if !$devinfo->{$devname};
4111 if (defined($opts->{storage
})) {
4112 $storeid = $opts->{storage
} || 'local';
4113 } elsif (!$storeid) {
4116 $format = 'raw' if !$format;
4117 $devinfo->{$devname}->{devname
} = $devname;
4118 $devinfo->{$devname}->{virtdev
} = $virtdev;
4119 $devinfo->{$devname}->{format
} = $format;
4120 $devinfo->{$devname}->{storeid
} = $storeid;
4122 # check permission on storage
4123 my $pool = $opts->{pool
}; # todo: do we need that?
4124 if ($user ne 'root@pam') {
4125 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4128 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4132 foreach my $devname (keys %$devinfo) {
4133 die "found no device mapping information for device '$devname'\n"
4134 if !$devinfo->{$devname}->{virtdev
};
4137 my $cfg = cfs_read_file
('storage.cfg');
4139 # create empty/temp config
4141 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4142 foreach_drive
($oldconf, sub {
4143 my ($ds, $drive) = @_;
4145 return if drive_is_cdrom
($drive);
4147 my $volid = $drive->{file
};
4149 return if !$volid || $volid =~ m
|^/|;
4151 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4152 return if !$path || !$owner || ($owner != $vmid);
4154 # Note: only delete disk we want to restore
4155 # other volumes will become unused
4156 if ($virtdev_hash->{$ds}) {
4157 PVE
::Storage
::vdisk_free
($cfg, $volid);
4163 foreach my $virtdev (sort keys %$virtdev_hash) {
4164 my $d = $virtdev_hash->{$virtdev};
4165 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4166 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4168 # test if requested format is supported
4169 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4170 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4171 $d->{format
} = $defFormat if !$supported;
4173 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4174 $d->{format
}, undef, $alloc_size);
4175 print STDERR
"new volume ID is '$volid'\n";
4176 $d->{volid
} = $volid;
4177 my $path = PVE
::Storage
::path
($cfg, $volid);
4179 my $write_zeros = 1;
4180 # fixme: what other storages types initialize volumes with zero?
4181 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4182 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4186 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4188 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4189 $map->{$virtdev} = $volid;
4192 $fh->seek(0, 0) || die "seek failed - $!\n";
4194 my $outfd = new IO
::File
($tmpfn, "w") ||
4195 die "unable to write config for VM $vmid\n";
4197 my $cookie = { netcount
=> 0 };
4198 while (defined(my $line = <$fh>)) {
4199 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4208 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4209 die "interrupted by signal\n";
4211 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4213 $oldtimeout = alarm($timeout);
4220 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4221 my ($dev_id, $size, $devname) = ($1, $2, $3);
4222 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4223 } elsif ($line =~ m/^CTIME: /) {
4224 # we correctly received the vma config, so we can disable
4225 # the timeout now for disk allocation (set to 10 minutes, so
4226 # that we always timeout if something goes wrong)
4229 print $fifofh "done\n";
4230 my $tmp = $oldtimeout || 0;
4231 $oldtimeout = undef;
4237 print "restore vma archive: $cmd\n";
4238 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4242 alarm($oldtimeout) if $oldtimeout;
4250 my $cfg = cfs_read_file
('storage.cfg');
4251 foreach my $devname (keys %$devinfo) {
4252 my $volid = $devinfo->{$devname}->{volid
};
4255 if ($volid =~ m
|^/|) {
4256 unlink $volid || die 'unlink failed\n';
4258 PVE
::Storage
::vdisk_free
($cfg, $volid);
4260 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4262 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4269 rename($tmpfn, $conffile) ||
4270 die "unable to commit configuration file '$conffile'\n";
4272 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4274 eval { rescan
($vmid, 1); };
4278 sub restore_tar_archive
{
4279 my ($archive, $vmid, $user, $opts) = @_;
4281 if ($archive ne '-') {
4282 my $firstfile = tar_archive_read_firstfile
($archive);
4283 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4284 if $firstfile ne 'qemu-server.conf';
4287 my $storecfg = cfs_read_file
('storage.cfg');
4289 # destroy existing data - keep empty config
4290 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4291 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4293 my $tocmd = "/usr/lib/qemu-server/qmextract";
4295 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4296 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4297 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4298 $tocmd .= ' --info' if $opts->{info
};
4300 # tar option "xf" does not autodetect compression when read from STDIN,
4301 # so we pipe to zcat
4302 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4303 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4305 my $tmpdir = "/var/tmp/vzdumptmp$$";
4308 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4309 local $ENV{VZDUMP_VMID
} = $vmid;
4310 local $ENV{VZDUMP_USER
} = $user;
4312 my $conffile = config_file
($vmid);
4313 my $tmpfn = "$conffile.$$.tmp";
4315 # disable interrupts (always do cleanups)
4316 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4317 print STDERR
"got interrupt - ignored\n";
4322 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4323 die "interrupted by signal\n";
4326 if ($archive eq '-') {
4327 print "extracting archive from STDIN\n";
4328 run_command
($cmd, input
=> "<&STDIN");
4330 print "extracting archive '$archive'\n";
4334 return if $opts->{info
};
4338 my $statfile = "$tmpdir/qmrestore.stat";
4339 if (my $fd = IO
::File-
>new($statfile, "r")) {
4340 while (defined (my $line = <$fd>)) {
4341 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4342 $map->{$1} = $2 if $1;
4344 print STDERR
"unable to parse line in statfile - $line\n";
4350 my $confsrc = "$tmpdir/qemu-server.conf";
4352 my $srcfd = new IO
::File
($confsrc, "r") ||
4353 die "unable to open file '$confsrc'\n";
4355 my $outfd = new IO
::File
($tmpfn, "w") ||
4356 die "unable to write config for VM $vmid\n";
4358 my $cookie = { netcount
=> 0 };
4359 while (defined (my $line = <$srcfd>)) {
4360 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4372 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4379 rename $tmpfn, $conffile ||
4380 die "unable to commit configuration file '$conffile'\n";
4382 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4384 eval { rescan
($vmid, 1); };
4389 # Internal snapshots
4391 # NOTE: Snapshot create/delete involves several non-atomic
4392 # action, and can take a long time.
4393 # So we try to avoid locking the file and use 'lock' variable
4394 # inside the config file instead.
4396 my $snapshot_copy_config = sub {
4397 my ($source, $dest) = @_;
4399 foreach my $k (keys %$source) {
4400 next if $k eq 'snapshots';
4401 next if $k eq 'snapstate';
4402 next if $k eq 'snaptime';
4403 next if $k eq 'vmstate';
4404 next if $k eq 'lock';
4405 next if $k eq 'digest';
4406 next if $k eq 'description';
4407 next if $k =~ m/^unused\d+$/;
4409 $dest->{$k} = $source->{$k};
4413 my $snapshot_apply_config = sub {
4414 my ($conf, $snap) = @_;
4416 # copy snapshot list
4418 snapshots
=> $conf->{snapshots
},
4421 # keep description and list of unused disks
4422 foreach my $k (keys %$conf) {
4423 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4424 $newconf->{$k} = $conf->{$k};
4427 &$snapshot_copy_config($snap, $newconf);
4432 sub foreach_writable_storage
{
4433 my ($conf, $func) = @_;
4437 foreach my $ds (keys %$conf) {
4438 next if !valid_drivename
($ds);
4440 my $drive = parse_drive
($ds, $conf->{$ds});
4442 next if drive_is_cdrom
($drive);
4444 my $volid = $drive->{file
};
4446 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4447 $sidhash->{$sid} = $sid if $sid;
4450 foreach my $sid (sort keys %$sidhash) {
4455 my $alloc_vmstate_volid = sub {
4456 my ($storecfg, $vmid, $conf, $snapname) = @_;
4458 # Note: we try to be smart when selecting a $target storage
4462 # search shared storage first
4463 foreach_writable_storage
($conf, sub {
4465 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4466 return if !$scfg->{shared
};
4468 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4472 # now search local storage
4473 foreach_writable_storage
($conf, sub {
4475 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4476 return if $scfg->{shared
};
4478 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4482 $target = 'local' if !$target;
4484 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4485 # we abort live save after $conf->{memory}, so we need at max twice that space
4486 my $size = $conf->{memory
}*2 + $driver_state_size;
4488 my $name = "vm-$vmid-state-$snapname";
4489 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4490 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4491 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4496 my $snapshot_prepare = sub {
4497 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4501 my $updatefn = sub {
4503 my $conf = load_config
($vmid);
4505 die "you can't take a snapshot if it's a template\n"
4506 if is_template
($conf);
4510 $conf->{lock} = 'snapshot';
4512 die "snapshot name '$snapname' already used\n"
4513 if defined($conf->{snapshots
}->{$snapname});
4515 my $storecfg = PVE
::Storage
::config
();
4516 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4518 $snap = $conf->{snapshots
}->{$snapname} = {};
4520 if ($save_vmstate && check_running
($vmid)) {
4521 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4524 &$snapshot_copy_config($conf, $snap);
4526 $snap->{snapstate
} = "prepare";
4527 $snap->{snaptime
} = time();
4528 $snap->{description
} = $comment if $comment;
4530 # always overwrite machine if we save vmstate. This makes sure we
4531 # can restore it later using correct machine type
4532 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4534 update_config_nolock
($vmid, $conf, 1);
4537 lock_config
($vmid, $updatefn);
4542 my $snapshot_commit = sub {
4543 my ($vmid, $snapname) = @_;
4545 my $updatefn = sub {
4547 my $conf = load_config
($vmid);
4549 die "missing snapshot lock\n"
4550 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4552 my $snap = $conf->{snapshots
}->{$snapname};
4554 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4556 die "wrong snapshot state\n"
4557 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4559 delete $snap->{snapstate
};
4560 delete $conf->{lock};
4562 my $newconf = &$snapshot_apply_config($conf, $snap);
4564 $newconf->{parent
} = $snapname;
4566 update_config_nolock
($vmid, $newconf, 1);
4569 lock_config
($vmid, $updatefn);
4572 sub snapshot_rollback
{
4573 my ($vmid, $snapname) = @_;
4579 my $storecfg = PVE
::Storage
::config
();
4581 my $updatefn = sub {
4583 my $conf = load_config
($vmid);
4585 die "you can't rollback if vm is a template\n" if is_template
($conf);
4587 $snap = $conf->{snapshots
}->{$snapname};
4589 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4591 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4592 if $snap->{snapstate
};
4596 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4599 die "unable to rollback vm $vmid: vm is running\n"
4600 if check_running
($vmid);
4603 $conf->{lock} = 'rollback';
4605 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4606 delete $conf->{lock};
4612 my $has_machine_config = defined($conf->{machine
});
4614 # copy snapshot config to current config
4615 $conf = &$snapshot_apply_config($conf, $snap);
4616 $conf->{parent
} = $snapname;
4618 # Note: old code did not store 'machine', so we try to be smart
4619 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4620 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4621 # we remove the 'machine' configuration if not explicitly specified
4622 # in the original config.
4623 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4626 update_config_nolock
($vmid, $conf, 1);
4628 if (!$prepare && $snap->{vmstate
}) {
4629 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4630 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4634 lock_config
($vmid, $updatefn);
4636 foreach_drive
($snap, sub {
4637 my ($ds, $drive) = @_;
4639 return if drive_is_cdrom
($drive);
4641 my $volid = $drive->{file
};
4642 my $device = "drive-$ds";
4644 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4648 lock_config
($vmid, $updatefn);
4651 my $savevm_wait = sub {
4655 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4656 if (!$stat->{status
}) {
4657 die "savevm not active\n";
4658 } elsif ($stat->{status
} eq 'active') {
4661 } elsif ($stat->{status
} eq 'completed') {
4664 die "query-savevm returned status '$stat->{status}'\n";
4669 sub snapshot_create
{
4670 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4672 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4674 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4678 my $running = check_running
($vmid);
4681 # create internal snapshots of all drives
4683 my $storecfg = PVE
::Storage
::config
();
4686 if ($snap->{vmstate
}) {
4687 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4688 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4689 &$savevm_wait($vmid);
4691 vm_mon_cmd
($vmid, "savevm-start");
4695 qga_freezefs
($vmid) if $running && $freezefs;
4697 foreach_drive
($snap, sub {
4698 my ($ds, $drive) = @_;
4700 return if drive_is_cdrom
($drive);
4702 my $volid = $drive->{file
};
4703 my $device = "drive-$ds";
4705 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4706 $drivehash->{$ds} = 1;
4711 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4714 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4718 warn "snapshot create failed: starting cleanup\n";
4719 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4724 &$snapshot_commit($vmid, $snapname);
4727 # Note: $drivehash is only set when called from snapshot_create.
4728 sub snapshot_delete
{
4729 my ($vmid, $snapname, $force, $drivehash) = @_;
4736 my $unlink_parent = sub {
4737 my ($confref, $new_parent) = @_;
4739 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4741 $confref->{parent
} = $new_parent;
4743 delete $confref->{parent
};
4748 my $updatefn = sub {
4749 my ($remove_drive) = @_;
4751 my $conf = load_config
($vmid);
4755 die "you can't delete a snapshot if vm is a template\n"
4756 if is_template
($conf);
4759 $snap = $conf->{snapshots
}->{$snapname};
4761 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4763 # remove parent refs
4764 &$unlink_parent($conf, $snap->{parent
});
4765 foreach my $sn (keys %{$conf->{snapshots
}}) {
4766 next if $sn eq $snapname;
4767 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4770 if ($remove_drive) {
4771 if ($remove_drive eq 'vmstate') {
4772 delete $snap->{$remove_drive};
4774 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4775 my $volid = $drive->{file
};
4776 delete $snap->{$remove_drive};
4777 add_unused_volume
($conf, $volid);
4782 $snap->{snapstate
} = 'delete';
4784 delete $conf->{snapshots
}->{$snapname};
4785 delete $conf->{lock} if $drivehash;
4786 foreach my $volid (@$unused) {
4787 add_unused_volume
($conf, $volid);
4791 update_config_nolock
($vmid, $conf, 1);
4794 lock_config
($vmid, $updatefn);
4796 # now remove vmstate file
4798 my $storecfg = PVE
::Storage
::config
();
4800 if ($snap->{vmstate
}) {
4801 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4803 die $err if !$force;
4806 # save changes (remove vmstate from snapshot)
4807 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4810 # now remove all internal snapshots
4811 foreach_drive
($snap, sub {
4812 my ($ds, $drive) = @_;
4814 return if drive_is_cdrom
($drive);
4816 my $volid = $drive->{file
};
4817 my $device = "drive-$ds";
4819 if (!$drivehash || $drivehash->{$ds}) {
4820 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4822 die $err if !$force;
4827 # save changes (remove drive fron snapshot)
4828 lock_config
($vmid, $updatefn, $ds) if !$force;
4829 push @$unused, $volid;
4832 # now cleanup config
4834 lock_config
($vmid, $updatefn);
4838 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4841 foreach_drive
($conf, sub {
4842 my ($ds, $drive) = @_;
4844 return if drive_is_cdrom
($drive);
4845 my $volid = $drive->{file
};
4846 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4849 return $err ?
0 : 1;
4852 sub template_create
{
4853 my ($vmid, $conf, $disk) = @_;
4855 my $storecfg = PVE
::Storage
::config
();
4857 foreach_drive
($conf, sub {
4858 my ($ds, $drive) = @_;
4860 return if drive_is_cdrom
($drive);
4861 return if $disk && $ds ne $disk;
4863 my $volid = $drive->{file
};
4864 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4866 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4867 $drive->{file
} = $voliddst;
4868 $conf->{$ds} = print_drive
($vmid, $drive);
4869 update_config_nolock
($vmid, $conf, 1);
4876 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4879 sub qemu_img_convert
{
4880 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4882 my $storecfg = PVE
::Storage
::config
();
4883 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4884 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4886 if ($src_storeid && $dst_storeid) {
4887 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4888 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4890 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4891 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4893 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4894 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4897 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4898 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4899 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4903 if($line =~ m/\((\S+)\/100\
%\)/){
4905 my $transferred = int($size * $percent / 100);
4906 my $remaining = $size - $transferred;
4908 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4913 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4915 die "copy failed: $err" if $err;
4919 sub qemu_img_format
{
4920 my ($scfg, $volname) = @_;
4922 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4924 } elsif ($scfg->{type
} eq 'iscsi') {
4925 return "host_device";
4931 sub qemu_drive_mirror
{
4932 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4938 my $storecfg = PVE
::Storage
::config
();
4939 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4942 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4945 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4949 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4952 #fixme : sometime drive-mirror timeout, but works fine after.
4953 # (I have see the problem with big volume > 200GB), so we need to eval
4954 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4955 sync
=> "full", target
=> $dst_path, format
=> $format); };
4957 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4958 sync
=> "full", target
=> $dst_path); };
4963 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4964 my $stat = @$stats[0];
4965 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4966 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4968 my $transferred = $stat->{offset
};
4969 my $total = $stat->{len
};
4970 my $remaining = $total - $transferred;
4971 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4973 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4975 last if ($stat->{len
} == $stat->{offset
});
4976 if ($old_len == $stat->{offset
}) {
4977 if ($maxwait && $count > $maxwait) {
4978 # if writes to disk occurs the disk needs to be freezed
4979 # to be able to complete the migration
4980 vm_suspend
($vmid,1);
4984 $count++ unless $frozen;
4990 $old_len = $stat->{offset
};
4994 if ($vmiddst == $vmid) {
4995 # switch the disk if source and destination are on the same guest
4996 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
5000 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
5001 die "mirroring error: $err";
5004 if ($vmiddst != $vmid) {
5005 # if we clone a disk for a new target vm, we don't switch the disk
5006 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5012 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5013 $newvmid, $storage, $format, $full, $newvollist) = @_;
5018 print "create linked clone of drive $drivename ($drive->{file})\n";
5019 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
5020 push @$newvollist, $newvolid;
5022 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5023 $storeid = $storage if $storage;
5025 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5027 $format = $drive->{format
} || $defFormat;
5030 # test if requested format is supported - else use default
5031 my $supported = grep { $_ eq $format } @$validFormats;
5032 $format = $defFormat if !$supported;
5034 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5036 print "create full clone of drive $drivename ($drive->{file})\n";
5037 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5038 push @$newvollist, $newvolid;
5040 if (!$running || $snapname) {
5041 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
5043 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
5047 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5050 $disk->{format
} = undef;
5051 $disk->{file
} = $newvolid;
5052 $disk->{size
} = $size;
5057 # this only works if VM is running
5058 sub get_current_qemu_machine
{
5061 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5062 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
5064 my ($current, $default);
5065 foreach my $e (@$res) {
5066 $default = $e->{name
} if $e->{'is-default'};
5067 $current = $e->{name
} if $e->{'is-current'};
5070 # fallback to the default machine if current is not supported by qemu
5071 return $current || $default || 'pc';