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>][,rate=<mbps>][,tag=<vlanid>]",
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 print_drivedevice_full
{
1063 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1068 if ($drive->{interface
} eq 'virtio') {
1069 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1070 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1071 } elsif ($drive->{interface
} eq 'scsi') {
1072 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1073 my $controller = int($drive->{index} / $maxdev);
1074 my $unit = $drive->{index} % $maxdev;
1075 my $devicetype = 'hd';
1077 if (drive_is_cdrom
($drive)) {
1080 if ($drive->{file
} =~ m
|^/|) {
1081 $path = $drive->{file
};
1083 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1086 if($path =~ m/^iscsi\:\/\
//){
1087 $devicetype = 'generic';
1089 if (my $info = path_is_scsi
($path)) {
1090 if ($info->{type
} == 0) {
1091 $devicetype = 'block';
1092 } elsif ($info->{type
} == 1) { # tape
1093 $devicetype = 'generic';
1099 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1100 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1102 $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}";
1105 } elsif ($drive->{interface
} eq 'ide'){
1107 my $controller = int($drive->{index} / $maxdev);
1108 my $unit = $drive->{index} % $maxdev;
1109 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1111 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1112 } elsif ($drive->{interface
} eq 'sata'){
1113 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1114 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1115 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1116 } elsif ($drive->{interface
} eq 'usb') {
1118 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1120 die "unsupported interface type";
1123 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1128 sub print_drive_full
{
1129 my ($storecfg, $vmid, $drive) = @_;
1132 foreach my $o (@qemu_drive_options) {
1133 next if $o eq 'bootindex';
1134 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1137 foreach my $o (qw(bps bps_rd bps_wr)) {
1138 my $v = $drive->{"m$o"};
1139 $opts .= ",$o=" . int($v*1024*1024) if $v;
1142 # use linux-aio by default (qemu default is threads)
1143 $opts .= ",aio=native" if !$drive->{aio
};
1146 my $volid = $drive->{file
};
1147 if (drive_is_cdrom
($drive)) {
1148 $path = get_iso_path
($storecfg, $vmid, $volid);
1150 if ($volid =~ m
|^/|) {
1153 $path = PVE
::Storage
::path
($storecfg, $volid);
1157 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1159 my $pathinfo = $path ?
"file=$path," : '';
1161 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1164 sub print_netdevice_full
{
1165 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1167 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1169 my $device = $net->{model
};
1170 if ($net->{model
} eq 'virtio') {
1171 $device = 'virtio-net-pci';
1174 # qemu > 0.15 always try to boot from network - we disable that by
1175 # not loading the pxe rom file
1176 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1177 my $pciaddr = print_pci_addr
("$netid", $bridges);
1178 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1179 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1183 sub print_netdev_full
{
1184 my ($vmid, $conf, $net, $netid) = @_;
1187 if ($netid =~ m/^net(\d+)$/) {
1191 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1193 my $ifname = "tap${vmid}i$i";
1195 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1196 die "interface name '$ifname' is too long (max 15 character)\n"
1197 if length($ifname) >= 16;
1199 my $vhostparam = '';
1200 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1202 my $vmname = $conf->{name
} || "vm$vmid";
1204 if ($net->{bridge
}) {
1205 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1207 return "type=user,id=$netid,hostname=$vmname";
1211 sub drive_is_cdrom
{
1214 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1221 return undef if !$value;
1224 my @list = split(/,/, $value);
1228 foreach my $kv (@list) {
1230 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) {
1233 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1234 $res->{driver
} = $1;
1235 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1236 $res->{rombar
} = $1;
1238 warn "unknown hostpci setting '$kv'\n";
1242 return undef if !$found;
1247 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1253 foreach my $kvp (split(/,/, $data)) {
1255 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) {
1257 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1258 $res->{model
} = $model;
1259 $res->{macaddr
} = $mac;
1260 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1261 $res->{bridge
} = $1;
1262 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1264 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1272 return undef if !$res->{model
};
1280 my $res = "$net->{model}";
1281 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1282 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1283 $res .= ",rate=$net->{rate}" if $net->{rate
};
1284 $res .= ",tag=$net->{tag}" if $net->{tag
};
1289 sub add_random_macs
{
1290 my ($settings) = @_;
1292 foreach my $opt (keys %$settings) {
1293 next if $opt !~ m/^net(\d+)$/;
1294 my $net = parse_net
($settings->{$opt});
1296 $settings->{$opt} = print_net
($net);
1300 sub add_unused_volume
{
1301 my ($config, $volid) = @_;
1304 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1305 my $test = "unused$ind";
1306 if (my $vid = $config->{$test}) {
1307 return if $vid eq $volid; # do not add duplicates
1313 die "To many unused volume - please delete them first.\n" if !$key;
1315 $config->{$key} = $volid;
1320 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1321 sub verify_bootdisk
{
1322 my ($value, $noerr) = @_;
1324 return $value if valid_drivename
($value);
1326 return undef if $noerr;
1328 die "invalid boot disk '$value'\n";
1331 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1333 my ($value, $noerr) = @_;
1335 return $value if parse_net
($value);
1337 return undef if $noerr;
1339 die "unable to parse network options\n";
1342 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1344 my ($value, $noerr) = @_;
1346 return $value if parse_drive
(undef, $value);
1348 return undef if $noerr;
1350 die "unable to parse drive options\n";
1353 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1354 sub verify_hostpci
{
1355 my ($value, $noerr) = @_;
1357 return $value if parse_hostpci
($value);
1359 return undef if $noerr;
1361 die "unable to parse pci id\n";
1364 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1365 sub verify_watchdog
{
1366 my ($value, $noerr) = @_;
1368 return $value if parse_watchdog
($value);
1370 return undef if $noerr;
1372 die "unable to parse watchdog options\n";
1375 sub parse_watchdog
{
1378 return undef if !$value;
1382 foreach my $p (split(/,/, $value)) {
1383 next if $p =~ m/^\s*$/;
1385 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1387 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1388 $res->{action
} = $2;
1397 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1398 sub verify_startup
{
1399 my ($value, $noerr) = @_;
1401 return $value if parse_startup
($value);
1403 return undef if $noerr;
1405 die "unable to parse startup options\n";
1411 return undef if !$value;
1415 foreach my $p (split(/,/, $value)) {
1416 next if $p =~ m/^\s*$/;
1418 if ($p =~ m/^(order=)?(\d+)$/) {
1420 } elsif ($p =~ m/^up=(\d+)$/) {
1422 } elsif ($p =~ m/^down=(\d+)$/) {
1432 sub parse_usb_device
{
1435 return undef if !$value;
1437 my @dl = split(/,/, $value);
1441 foreach my $v (@dl) {
1442 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1444 $res->{vendorid
} = $2;
1445 $res->{productid
} = $4;
1446 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1448 $res->{hostbus
} = $1;
1449 $res->{hostport
} = $2;
1450 } elsif ($v =~ m/^spice$/) {
1457 return undef if !$found;
1462 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1463 sub verify_usb_device
{
1464 my ($value, $noerr) = @_;
1466 return $value if parse_usb_device
($value);
1468 return undef if $noerr;
1470 die "unable to parse usb device\n";
1473 # add JSON properties for create and set function
1474 sub json_config_properties
{
1477 foreach my $opt (keys %$confdesc) {
1478 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1479 $prop->{$opt} = $confdesc->{$opt};
1486 my ($key, $value) = @_;
1488 die "unknown setting '$key'\n" if !$confdesc->{$key};
1490 my $type = $confdesc->{$key}->{type
};
1492 if (!defined($value)) {
1493 die "got undefined value\n";
1496 if ($value =~ m/[\n\r]/) {
1497 die "property contains a line feed\n";
1500 if ($type eq 'boolean') {
1501 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1502 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1503 die "type check ('boolean') failed - got '$value'\n";
1504 } elsif ($type eq 'integer') {
1505 return int($1) if $value =~ m/^(\d+)$/;
1506 die "type check ('integer') failed - got '$value'\n";
1507 } elsif ($type eq 'number') {
1508 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1509 die "type check ('number') failed - got '$value'\n";
1510 } elsif ($type eq 'string') {
1511 if (my $fmt = $confdesc->{$key}->{format
}) {
1512 if ($fmt eq 'pve-qm-drive') {
1513 # special case - we need to pass $key to parse_drive()
1514 my $drive = parse_drive
($key, $value);
1515 return $value if $drive;
1516 die "unable to parse drive options\n";
1518 PVE
::JSONSchema
::check_format
($fmt, $value);
1521 $value =~ s/^\"(.*)\"$/$1/;
1524 die "internal error"
1528 sub lock_config_full
{
1529 my ($vmid, $timeout, $code, @param) = @_;
1531 my $filename = config_file_lock
($vmid);
1533 my $res = lock_file
($filename, $timeout, $code, @param);
1540 sub lock_config_mode
{
1541 my ($vmid, $timeout, $shared, $code, @param) = @_;
1543 my $filename = config_file_lock
($vmid);
1545 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1553 my ($vmid, $code, @param) = @_;
1555 return lock_config_full
($vmid, 10, $code, @param);
1558 sub cfs_config_path
{
1559 my ($vmid, $node) = @_;
1561 $node = $nodename if !$node;
1562 return "nodes/$node/qemu-server/$vmid.conf";
1565 sub check_iommu_support
{
1566 #fixme : need to check IOMMU support
1567 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1575 my ($vmid, $node) = @_;
1577 my $cfspath = cfs_config_path
($vmid, $node);
1578 return "/etc/pve/$cfspath";
1581 sub config_file_lock
{
1584 return "$lock_dir/lock-$vmid.conf";
1590 my $conf = config_file
($vmid);
1591 utime undef, undef, $conf;
1595 my ($storecfg, $vmid, $keep_empty_config) = @_;
1597 my $conffile = config_file
($vmid);
1599 my $conf = load_config
($vmid);
1603 # only remove disks owned by this VM
1604 foreach_drive
($conf, sub {
1605 my ($ds, $drive) = @_;
1607 return if drive_is_cdrom
($drive);
1609 my $volid = $drive->{file
};
1611 return if !$volid || $volid =~ m
|^/|;
1613 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1614 return if !$path || !$owner || ($owner != $vmid);
1616 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1619 if ($keep_empty_config) {
1620 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1625 # also remove unused disk
1627 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1630 PVE
::Storage
::foreach_volid
($dl, sub {
1631 my ($volid, $sid, $volname, $d) = @_;
1632 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1642 my ($vmid, $node) = @_;
1644 my $cfspath = cfs_config_path
($vmid, $node);
1646 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1648 die "no such VM ('$vmid')\n" if !defined($conf);
1653 sub parse_vm_config
{
1654 my ($filename, $raw) = @_;
1656 return undef if !defined($raw);
1659 digest
=> Digest
::SHA
::sha1_hex
($raw),
1663 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1664 || die "got strange filename '$filename'";
1671 my @lines = split(/\n/, $raw);
1672 foreach my $line (@lines) {
1673 next if $line =~ m/^\s*$/;
1675 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1677 $conf->{description
} = $descr if $descr;
1679 $conf = $res->{snapshots
}->{$snapname} = {};
1683 if ($line =~ m/^\#(.*)\s*$/) {
1684 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1688 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1689 $descr .= PVE
::Tools
::decode_text
($2);
1690 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1691 $conf->{snapstate
} = $1;
1692 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1695 $conf->{$key} = $value;
1696 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1699 eval { $value = check_type
($key, $value); };
1701 warn "vm $vmid - unable to parse value of '$key' - $@";
1703 my $fmt = $confdesc->{$key}->{format
};
1704 if ($fmt && $fmt eq 'pve-qm-drive') {
1705 my $v = parse_drive
($key, $value);
1706 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1707 $v->{file
} = $volid;
1708 $value = print_drive
($vmid, $v);
1710 warn "vm $vmid - unable to parse value of '$key'\n";
1715 if ($key eq 'cdrom') {
1716 $conf->{ide2
} = $value;
1718 $conf->{$key} = $value;
1724 $conf->{description
} = $descr if $descr;
1726 delete $res->{snapstate
}; # just to be sure
1731 sub write_vm_config
{
1732 my ($filename, $conf) = @_;
1734 delete $conf->{snapstate
}; # just to be sure
1736 if ($conf->{cdrom
}) {
1737 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1738 $conf->{ide2
} = $conf->{cdrom
};
1739 delete $conf->{cdrom
};
1742 # we do not use 'smp' any longer
1743 if ($conf->{sockets
}) {
1744 delete $conf->{smp
};
1745 } elsif ($conf->{smp
}) {
1746 $conf->{sockets
} = $conf->{smp
};
1747 delete $conf->{cores
};
1748 delete $conf->{smp
};
1751 if ($conf->{maxcpus
} && $conf->{sockets
}){
1752 delete $conf->{sockets
};
1754 my $used_volids = {};
1756 my $cleanup_config = sub {
1757 my ($cref, $snapname) = @_;
1759 foreach my $key (keys %$cref) {
1760 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1761 $key eq 'snapstate';
1762 my $value = $cref->{$key};
1763 eval { $value = check_type
($key, $value); };
1764 die "unable to parse value of '$key' - $@" if $@;
1766 $cref->{$key} = $value;
1768 if (!$snapname && valid_drivename
($key)) {
1769 my $drive = parse_drive
($key, $value);
1770 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1775 &$cleanup_config($conf);
1776 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1777 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1780 # remove 'unusedX' settings if we re-add a volume
1781 foreach my $key (keys %$conf) {
1782 my $value = $conf->{$key};
1783 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1784 delete $conf->{$key};
1788 my $generate_raw_config = sub {
1793 # add description as comment to top of file
1794 my $descr = $conf->{description
} || '';
1795 foreach my $cl (split(/\n/, $descr)) {
1796 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1799 foreach my $key (sort keys %$conf) {
1800 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1801 $raw .= "$key: $conf->{$key}\n";
1806 my $raw = &$generate_raw_config($conf);
1807 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1808 $raw .= "\n[$snapname]\n";
1809 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1815 sub update_config_nolock
{
1816 my ($vmid, $conf, $skiplock) = @_;
1818 check_lock
($conf) if !$skiplock;
1820 my $cfspath = cfs_config_path
($vmid);
1822 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1826 my ($vmid, $conf, $skiplock) = @_;
1828 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1835 # we use static defaults from our JSON schema configuration
1836 foreach my $key (keys %$confdesc) {
1837 if (defined(my $default = $confdesc->{$key}->{default})) {
1838 $res->{$key} = $default;
1842 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1843 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1849 my $vmlist = PVE
::Cluster
::get_vmlist
();
1851 return $res if !$vmlist || !$vmlist->{ids
};
1852 my $ids = $vmlist->{ids
};
1854 foreach my $vmid (keys %$ids) {
1855 my $d = $ids->{$vmid};
1856 next if !$d->{node
} || $d->{node
} ne $nodename;
1857 next if !$d->{type
} || $d->{type
} ne 'qemu';
1858 $res->{$vmid}->{exists} = 1;
1863 # test if VM uses local resources (to prevent migration)
1864 sub check_local_resources
{
1865 my ($conf, $noerr) = @_;
1869 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1870 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1872 foreach my $k (keys %$conf) {
1873 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1874 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1877 die "VM uses local resources\n" if $loc_res && !$noerr;
1882 # check if used storages are available on all nodes (use by migrate)
1883 sub check_storage_availability
{
1884 my ($storecfg, $conf, $node) = @_;
1886 foreach_drive
($conf, sub {
1887 my ($ds, $drive) = @_;
1889 my $volid = $drive->{file
};
1892 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1895 # check if storage is available on both nodes
1896 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1897 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1901 # list nodes where all VM images are available (used by has_feature API)
1903 my ($conf, $storecfg) = @_;
1905 my $nodelist = PVE
::Cluster
::get_nodelist
();
1906 my $nodehash = { map { $_ => 1 } @$nodelist };
1907 my $nodename = PVE
::INotify
::nodename
();
1909 foreach_drive
($conf, sub {
1910 my ($ds, $drive) = @_;
1912 my $volid = $drive->{file
};
1915 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1917 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1918 if ($scfg->{disable
}) {
1920 } elsif (my $avail = $scfg->{nodes
}) {
1921 foreach my $node (keys %$nodehash) {
1922 delete $nodehash->{$node} if !$avail->{$node};
1924 } elsif (!$scfg->{shared
}) {
1925 foreach my $node (keys %$nodehash) {
1926 delete $nodehash->{$node} if $node ne $nodename
1938 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1942 my ($pidfile, $pid) = @_;
1944 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1948 return undef if !$line;
1949 my @param = split(/\0/, $line);
1951 my $cmd = $param[0];
1952 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1954 for (my $i = 0; $i < scalar (@param); $i++) {
1957 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1958 my $p = $param[$i+1];
1959 return 1 if $p && ($p eq $pidfile);
1968 my ($vmid, $nocheck, $node) = @_;
1970 my $filename = config_file
($vmid, $node);
1972 die "unable to find configuration file for VM $vmid - no such machine\n"
1973 if !$nocheck && ! -f
$filename;
1975 my $pidfile = pidfile_name
($vmid);
1977 if (my $fd = IO
::File-
>new("<$pidfile")) {
1982 my $mtime = $st->mtime;
1983 if ($mtime > time()) {
1984 warn "file '$filename' modified in future\n";
1987 if ($line =~ m/^(\d+)$/) {
1989 if (check_cmdline
($pidfile, $pid)) {
1990 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2002 my $vzlist = config_list
();
2004 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2006 while (defined(my $de = $fd->read)) {
2007 next if $de !~ m/^(\d+)\.pid$/;
2009 next if !defined($vzlist->{$vmid});
2010 if (my $pid = check_running
($vmid)) {
2011 $vzlist->{$vmid}->{pid
} = $pid;
2019 my ($storecfg, $conf) = @_;
2021 my $bootdisk = $conf->{bootdisk
};
2022 return undef if !$bootdisk;
2023 return undef if !valid_drivename
($bootdisk);
2025 return undef if !$conf->{$bootdisk};
2027 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2028 return undef if !defined($drive);
2030 return undef if drive_is_cdrom
($drive);
2032 my $volid = $drive->{file
};
2033 return undef if !$volid;
2035 return $drive->{size
};
2038 my $last_proc_pid_stat;
2040 # get VM status information
2041 # This must be fast and should not block ($full == false)
2042 # We only query KVM using QMP if $full == true (this can be slow)
2044 my ($opt_vmid, $full) = @_;
2048 my $storecfg = PVE
::Storage
::config
();
2050 my $list = vzlist
();
2051 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2053 my $cpucount = $cpuinfo->{cpus
} || 1;
2055 foreach my $vmid (keys %$list) {
2056 next if $opt_vmid && ($vmid ne $opt_vmid);
2058 my $cfspath = cfs_config_path
($vmid);
2059 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2062 $d->{pid
} = $list->{$vmid}->{pid
};
2064 # fixme: better status?
2065 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2067 my $size = disksize
($storecfg, $conf);
2068 if (defined($size)) {
2069 $d->{disk
} = 0; # no info available
2070 $d->{maxdisk
} = $size;
2076 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2077 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2079 $d->{name
} = $conf->{name
} || "VM $vmid";
2080 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2082 if ($conf->{balloon
}) {
2083 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2084 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2095 $d->{diskwrite
} = 0;
2097 $d->{template
} = is_template
($conf);
2102 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2103 foreach my $dev (keys %$netdev) {
2104 next if $dev !~ m/^tap([1-9]\d*)i/;
2106 my $d = $res->{$vmid};
2109 $d->{netout
} += $netdev->{$dev}->{receive
};
2110 $d->{netin
} += $netdev->{$dev}->{transmit
};
2113 my $ctime = gettimeofday
;
2115 foreach my $vmid (keys %$list) {
2117 my $d = $res->{$vmid};
2118 my $pid = $d->{pid
};
2121 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2122 next if !$pstat; # not running
2124 my $used = $pstat->{utime} + $pstat->{stime
};
2126 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2128 if ($pstat->{vsize
}) {
2129 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2132 my $old = $last_proc_pid_stat->{$pid};
2134 $last_proc_pid_stat->{$pid} = {
2142 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2144 if ($dtime > 1000) {
2145 my $dutime = $used - $old->{used
};
2147 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2148 $last_proc_pid_stat->{$pid} = {
2154 $d->{cpu
} = $old->{cpu
};
2158 return $res if !$full;
2160 my $qmpclient = PVE
::QMPClient-
>new();
2162 my $ballooncb = sub {
2163 my ($vmid, $resp) = @_;
2165 my $info = $resp->{'return'};
2166 return if !$info->{max_mem
};
2168 my $d = $res->{$vmid};
2170 # use memory assigned to VM
2171 $d->{maxmem
} = $info->{max_mem
};
2172 $d->{balloon
} = $info->{actual
};
2174 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2175 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2176 $d->{freemem
} = $info->{free_mem
};
2181 my $blockstatscb = sub {
2182 my ($vmid, $resp) = @_;
2183 my $data = $resp->{'return'} || [];
2184 my $totalrdbytes = 0;
2185 my $totalwrbytes = 0;
2186 for my $blockstat (@$data) {
2187 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2188 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2190 $res->{$vmid}->{diskread
} = $totalrdbytes;
2191 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2194 my $statuscb = sub {
2195 my ($vmid, $resp) = @_;
2197 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2198 # this fails if ballon driver is not loaded, so this must be
2199 # the last commnand (following command are aborted if this fails).
2200 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2202 my $status = 'unknown';
2203 if (!defined($status = $resp->{'return'}->{status
})) {
2204 warn "unable to get VM status\n";
2208 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2211 foreach my $vmid (keys %$list) {
2212 next if $opt_vmid && ($vmid ne $opt_vmid);
2213 next if !$res->{$vmid}->{pid
}; # not running
2214 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2217 $qmpclient->queue_execute();
2219 foreach my $vmid (keys %$list) {
2220 next if $opt_vmid && ($vmid ne $opt_vmid);
2221 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2228 my ($conf, $func) = @_;
2230 foreach my $ds (keys %$conf) {
2231 next if !valid_drivename
($ds);
2233 my $drive = parse_drive
($ds, $conf->{$ds});
2236 &$func($ds, $drive);
2241 my ($conf, $func) = @_;
2245 my $test_volid = sub {
2246 my ($volid, $is_cdrom) = @_;
2250 $volhash->{$volid} = $is_cdrom || 0;
2253 foreach_drive
($conf, sub {
2254 my ($ds, $drive) = @_;
2255 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2258 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2259 my $snap = $conf->{snapshots
}->{$snapname};
2260 &$test_volid($snap->{vmstate
}, 0);
2261 foreach_drive
($snap, sub {
2262 my ($ds, $drive) = @_;
2263 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2267 foreach my $volid (keys %$volhash) {
2268 &$func($volid, $volhash->{$volid});
2272 sub vga_conf_has_spice
{
2275 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2280 sub config_to_command
{
2281 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2284 my $globalFlags = [];
2285 my $machineFlags = [];
2291 my $kvmver = kvm_user_version
();
2292 my $vernum = 0; # unknown
2293 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2294 $vernum = $1*1000000+$2*1000;
2295 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2296 $vernum = $1*1000000+$2*1000+$3;
2299 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2301 my $have_ovz = -f
'/proc/vz/vestat';
2303 push @$cmd, '/usr/bin/kvm';
2305 push @$cmd, '-id', $vmid;
2309 my $qmpsocket = qmp_socket
($vmid);
2310 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2311 push @$cmd, '-mon', "chardev=qmp,mode=control";
2313 my $socket = vnc_socket
($vmid);
2314 push @$cmd, '-vnc', "unix:$socket,x509,password";
2316 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2318 push @$cmd, '-daemonize';
2320 $pciaddr = print_pci_addr
("piix3", $bridges);
2321 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2324 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2325 next if !$conf->{"usb$i"};
2328 # include usb device config
2329 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2331 my $vga = $conf->{vga
};
2333 my $qxlnum = vga_conf_has_spice
($vga);
2334 $vga = 'qxl' if $qxlnum;
2337 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2338 $conf->{ostype
} eq 'win7' ||
2339 $conf->{ostype
} eq 'w2k8')) {
2346 # enable absolute mouse coordinates (needed by vnc)
2348 if (defined($conf->{tablet
})) {
2349 $tablet = $conf->{tablet
};
2351 $tablet = $defaults->{tablet
};
2352 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2353 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2356 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2359 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2360 my $d = parse_hostpci
($conf->{"hostpci$i"});
2362 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2363 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2364 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar";
2368 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2369 my $d = parse_usb_device
($conf->{"usb$i"});
2371 if ($d->{vendorid
} && $d->{productid
}) {
2372 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2373 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2374 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2375 } elsif ($d->{spice
}) {
2376 # usb redir support for spice
2377 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2378 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2383 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2384 if (my $path = $conf->{"serial$i"}) {
2385 if ($path eq 'socket') {
2386 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2387 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2388 push @$devices, '-device', "isa-serial,chardev=serial$i";
2390 die "no such serial device\n" if ! -c
$path;
2391 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2392 push @$devices, '-device', "isa-serial,chardev=serial$i";
2398 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2399 if (my $path = $conf->{"parallel$i"}) {
2400 die "no such parallel device\n" if ! -c
$path;
2401 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2402 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2403 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2407 my $vmname = $conf->{name
} || "vm$vmid";
2409 push @$cmd, '-name', $vmname;
2412 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2413 $sockets = $conf->{sockets
} if $conf->{sockets
};
2415 my $cores = $conf->{cores
} || 1;
2416 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2419 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2421 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2424 push @$cmd, '-nodefaults';
2426 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2428 my $bootindex_hash = {};
2430 foreach my $o (split(//, $bootorder)) {
2431 $bootindex_hash->{$o} = $i*100;
2435 push @$cmd, '-boot', "menu=on";
2437 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2439 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2441 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2444 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2446 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2447 my $useLocaltime = $conf->{localtime};
2449 if (my $ost = $conf->{ostype
}) {
2450 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2452 if ($ost =~ m/^w/) { # windows
2453 $useLocaltime = 1 if !defined($conf->{localtime});
2455 # use time drift fix when acpi is enabled
2456 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2457 $tdf = 1 if !defined($conf->{tdf
});
2461 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2463 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2464 push @$cmd, '-no-hpet';
2465 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2466 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2469 if ($ost eq 'win7' || $ost eq 'win8') {
2470 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2474 push @$rtcFlags, 'driftfix=slew' if $tdf;
2477 push @$machineFlags, 'accel=tcg';
2479 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2482 my $machine_type = $forcemachine || $conf->{machine
};
2483 if ($machine_type) {
2484 push @$machineFlags, "type=${machine_type}";
2487 if ($conf->{startdate
}) {
2488 push @$rtcFlags, "base=$conf->{startdate}";
2489 } elsif ($useLocaltime) {
2490 push @$rtcFlags, 'base=localtime';
2493 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2494 $cpu = $conf->{cpu
} if $conf->{cpu
};
2496 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2498 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2500 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2502 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2504 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2506 push @$cmd, '-cpu', $cpu;
2508 push @$cmd, '-S' if $conf->{freeze
};
2510 # set keyboard layout
2511 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2512 push @$cmd, '-k', $kb if $kb;
2515 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2516 #push @$cmd, '-soundhw', 'es1370';
2517 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2519 if($conf->{agent
}) {
2520 my $qgasocket = qga_socket
($vmid);
2521 my $pciaddr = print_pci_addr
("qga0", $bridges);
2522 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2523 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2524 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2531 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2532 for(my $i = 1; $i < $qxlnum; $i++){
2533 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2534 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2537 # assume other OS works like Linux
2538 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2539 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2543 my $pciaddr = print_pci_addr
("spice", $bridges);
2545 $spice_port = PVE
::Tools
::next_spice_port
();
2547 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2549 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2550 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2551 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2554 # enable balloon by default, unless explicitly disabled
2555 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2556 $pciaddr = print_pci_addr
("balloon0", $bridges);
2557 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2560 if ($conf->{watchdog
}) {
2561 my $wdopts = parse_watchdog
($conf->{watchdog
});
2562 $pciaddr = print_pci_addr
("watchdog", $bridges);
2563 my $watchdog = $wdopts->{model
} || 'i6300esb';
2564 push @$devices, '-device', "$watchdog$pciaddr";
2565 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2569 my $scsicontroller = {};
2570 my $ahcicontroller = {};
2571 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2573 foreach_drive
($conf, sub {
2574 my ($ds, $drive) = @_;
2576 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2577 push @$vollist, $drive->{file
};
2580 $use_virtio = 1 if $ds =~ m/^virtio/;
2582 if (drive_is_cdrom
($drive)) {
2583 if ($bootindex_hash->{d
}) {
2584 $drive->{bootindex
} = $bootindex_hash->{d
};
2585 $bootindex_hash->{d
} += 1;
2588 if ($bootindex_hash->{c
}) {
2589 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2590 $bootindex_hash->{c
} += 1;
2594 if ($drive->{interface
} eq 'scsi') {
2596 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2597 my $controller = int($drive->{index} / $maxdev);
2598 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2599 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2600 $scsicontroller->{$controller}=1;
2603 if ($drive->{interface
} eq 'sata') {
2604 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2605 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2606 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2607 $ahcicontroller->{$controller}=1;
2610 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2611 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2614 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2616 for (my $i = 0; $i < $MAX_NETS; $i++) {
2617 next if !$conf->{"net$i"};
2618 my $d = parse_net
($conf->{"net$i"});
2621 $use_virtio = 1 if $d->{model
} eq 'virtio';
2623 if ($bootindex_hash->{n
}) {
2624 $d->{bootindex
} = $bootindex_hash->{n
};
2625 $bootindex_hash->{n
} += 1;
2628 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2629 push @$devices, '-netdev', $netdevfull;
2631 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2632 push @$devices, '-device', $netdevicefull;
2636 while (my ($k, $v) = each %$bridges) {
2637 $pciaddr = print_pci_addr
("pci.$k");
2638 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2642 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2643 # when the VM uses virtio devices.
2644 if (!$use_virtio && $have_ovz) {
2646 my $cpuunits = defined($conf->{cpuunits
}) ?
2647 $conf->{cpuunits
} : $defaults->{cpuunits
};
2649 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2651 # fixme: cpulimit is currently ignored
2652 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2656 if ($conf->{args
}) {
2657 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2661 push @$cmd, @$devices;
2662 push @$cmd, '-rtc', join(',', @$rtcFlags)
2663 if scalar(@$rtcFlags);
2664 push @$cmd, '-machine', join(',', @$machineFlags)
2665 if scalar(@$machineFlags);
2666 push @$cmd, '-global', join(',', @$globalFlags)
2667 if scalar(@$globalFlags);
2669 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2674 return "${var_run_tmpdir}/$vmid.vnc";
2680 my $res = vm_mon_cmd
($vmid, 'query-spice');
2682 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2687 return "${var_run_tmpdir}/$vmid.qmp";
2692 return "${var_run_tmpdir}/$vmid.qga";
2697 return "${var_run_tmpdir}/$vmid.pid";
2700 sub vm_devices_list
{
2703 my $res = vm_mon_cmd
($vmid, 'query-pci');
2706 foreach my $pcibus (@$res) {
2707 foreach my $device (@{$pcibus->{devices
}}) {
2708 next if !$device->{'qdev_id'};
2709 $devices->{$device->{'qdev_id'}} = $device;
2717 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2719 return 1 if !check_running
($vmid);
2721 if ($deviceid eq 'tablet') {
2722 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2723 qemu_deviceadd
($vmid, $devicefull);
2727 return 1 if !$conf->{hotplug
};
2729 my $devices_list = vm_devices_list
($vmid);
2730 return 1 if defined($devices_list->{$deviceid});
2732 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2734 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2735 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2736 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2737 qemu_deviceadd
($vmid, $devicefull);
2738 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2739 qemu_drivedel
($vmid, $deviceid);
2744 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2745 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2746 my $pciaddr = print_pci_addr
($deviceid);
2747 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2748 qemu_deviceadd
($vmid, $devicefull);
2749 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2752 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2753 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2754 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2755 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2756 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2757 if(!qemu_deviceadd
($vmid, $devicefull)) {
2758 qemu_drivedel
($vmid, $deviceid);
2763 if ($deviceid =~ m/^(net)(\d+)$/) {
2764 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2765 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2766 qemu_deviceadd
($vmid, $netdevicefull);
2767 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2768 qemu_netdevdel
($vmid, $deviceid);
2773 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2775 my $pciaddr = print_pci_addr
($deviceid);
2776 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2777 qemu_deviceadd
($vmid, $devicefull);
2778 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2784 sub vm_deviceunplug
{
2785 my ($vmid, $conf, $deviceid) = @_;
2787 return 1 if !check_running
($vmid);
2789 if ($deviceid eq 'tablet') {
2790 qemu_devicedel
($vmid, $deviceid);
2794 return 1 if !$conf->{hotplug
};
2796 my $devices_list = vm_devices_list
($vmid);
2797 return 1 if !defined($devices_list->{$deviceid});
2799 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2801 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2802 qemu_devicedel
($vmid, $deviceid);
2803 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2804 return undef if !qemu_drivedel
($vmid, $deviceid);
2807 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2808 return undef if !qemu_devicedel
($vmid, $deviceid);
2811 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2812 return undef if !qemu_devicedel
($vmid, $deviceid);
2813 return undef if !qemu_drivedel
($vmid, $deviceid);
2816 if ($deviceid =~ m/^(net)(\d+)$/) {
2817 qemu_devicedel
($vmid, $deviceid);
2818 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2819 return undef if !qemu_netdevdel
($vmid, $deviceid);
2825 sub qemu_deviceadd
{
2826 my ($vmid, $devicefull) = @_;
2828 $devicefull = "driver=".$devicefull;
2829 my %options = split(/[=,]/, $devicefull);
2831 vm_mon_cmd
($vmid, "device_add" , %options);
2835 sub qemu_devicedel
{
2836 my($vmid, $deviceid) = @_;
2837 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2842 my($storecfg, $vmid, $device) = @_;
2844 my $drive = print_drive_full
($storecfg, $vmid, $device);
2845 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2846 # If the command succeeds qemu prints: "OK"
2847 if ($ret !~ m/OK/s) {
2848 syslog
("err", "adding drive failed: $ret");
2855 my($vmid, $deviceid) = @_;
2857 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2859 if ($ret =~ m/Device \'.*?\' not found/s) {
2860 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2862 elsif ($ret ne "") {
2863 syslog
("err", "deleting drive $deviceid failed : $ret");
2869 sub qemu_deviceaddverify
{
2870 my ($vmid,$deviceid) = @_;
2872 for (my $i = 0; $i <= 5; $i++) {
2873 my $devices_list = vm_devices_list
($vmid);
2874 return 1 if defined($devices_list->{$deviceid});
2877 syslog
("err", "error on hotplug device $deviceid");
2882 sub qemu_devicedelverify
{
2883 my ($vmid,$deviceid) = @_;
2885 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2886 for (my $i = 0; $i <= 5; $i++) {
2887 my $devices_list = vm_devices_list
($vmid);
2888 return 1 if !defined($devices_list->{$deviceid});
2891 syslog
("err", "error on hot-unplugging device $deviceid");
2895 sub qemu_findorcreatescsihw
{
2896 my ($storecfg, $conf, $vmid, $device) = @_;
2898 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2899 my $controller = int($device->{index} / $maxdev);
2900 my $scsihwid="scsihw$controller";
2901 my $devices_list = vm_devices_list
($vmid);
2903 if(!defined($devices_list->{$scsihwid})) {
2904 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2909 sub qemu_bridgeadd
{
2910 my ($storecfg, $conf, $vmid, $device) = @_;
2913 my $bridgeid = undef;
2914 print_pci_addr
($device, $bridges);
2916 while (my ($k, $v) = each %$bridges) {
2919 return if !$bridgeid || $bridgeid < 1;
2920 my $bridge = "pci.$bridgeid";
2921 my $devices_list = vm_devices_list
($vmid);
2923 if(!defined($devices_list->{$bridge})) {
2924 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2929 sub qemu_netdevadd
{
2930 my ($vmid, $conf, $device, $deviceid) = @_;
2932 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2933 my %options = split(/[=,]/, $netdev);
2935 vm_mon_cmd
($vmid, "netdev_add", %options);
2939 sub qemu_netdevdel
{
2940 my ($vmid, $deviceid) = @_;
2942 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2946 sub qemu_block_set_io_throttle
{
2947 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2949 return if !check_running
($vmid) ;
2951 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));
2955 # old code, only used to shutdown old VM after update
2957 my ($fh, $timeout) = @_;
2959 my $sel = new IO
::Select
;
2966 while (scalar (@ready = $sel->can_read($timeout))) {
2968 if ($count = $fh->sysread($buf, 8192)) {
2969 if ($buf =~ /^(.*)\(qemu\) $/s) {
2976 if (!defined($count)) {
2983 die "monitor read timeout\n" if !scalar(@ready);
2988 # old code, only used to shutdown old VM after update
2989 sub vm_monitor_command
{
2990 my ($vmid, $cmdstr, $nocheck) = @_;
2995 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2997 my $sname = "${var_run_tmpdir}/$vmid.mon";
2999 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3000 die "unable to connect to VM $vmid socket - $!\n";
3004 # hack: migrate sometime blocks the monitor (when migrate_downtime
3006 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3007 $timeout = 60*60; # 1 hour
3011 my $data = __read_avail
($sock, $timeout);
3013 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3014 die "got unexpected qemu monitor banner\n";
3017 my $sel = new IO
::Select
;
3020 if (!scalar(my @ready = $sel->can_write($timeout))) {
3021 die "monitor write error - timeout";
3024 my $fullcmd = "$cmdstr\r";
3026 # syslog('info', "VM $vmid monitor command: $cmdstr");
3029 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3030 die "monitor write error - $!";
3033 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3037 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3038 $timeout = 60*60; # 1 hour
3039 } elsif ($cmdstr =~ m/^(eject|change)/) {
3040 $timeout = 60; # note: cdrom mount command is slow
3042 if ($res = __read_avail
($sock, $timeout)) {
3044 my @lines = split("\r?\n", $res);
3046 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3048 $res = join("\n", @lines);
3056 syslog
("err", "VM $vmid monitor command failed - $err");
3063 sub qemu_block_resize
{
3064 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3066 my $running = check_running
($vmid);
3068 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3070 return if !$running;
3072 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3076 sub qemu_volume_snapshot
{
3077 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3079 my $running = check_running
($vmid);
3081 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3083 return if !$running;
3085 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3089 sub qemu_volume_snapshot_delete
{
3090 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3092 my $running = check_running
($vmid);
3094 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3096 return if !$running;
3098 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3104 #need to impplement call to qemu-ga
3107 sub qga_unfreezefs
{
3110 #need to impplement call to qemu-ga
3113 sub set_migration_caps
{
3119 "auto-converge" => 1,
3121 "x-rdma-pin-all" => 0,
3125 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3127 for my $supported_capability (@$supported_capabilities) {
3128 if ($enabled_cap->{$supported_capability->{capability
}} eq 1) {
3130 capability
=> $supported_capability->{capability
},
3131 state => JSON
::true
,
3136 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3140 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3142 lock_config
($vmid, sub {
3143 my $conf = load_config
($vmid, $migratedfrom);
3145 die "you can't start a vm if it's a template\n" if is_template
($conf);
3147 check_lock
($conf) if !$skiplock;
3149 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3151 my $defaults = load_defaults
();
3153 # set environment variable useful inside network script
3154 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3156 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3158 my $migrate_port = 0;
3161 if ($statefile eq 'tcp') {
3162 my $localip = "localhost";
3163 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3164 if ($datacenterconf->{migration_unsecure
}) {
3165 my $nodename = PVE
::INotify
::nodename
();
3166 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3168 $migrate_port = PVE
::Tools
::next_migrate_port
();
3169 $migrate_uri = "tcp:${localip}:${migrate_port}";
3170 push @$cmd, '-incoming', $migrate_uri;
3173 push @$cmd, '-loadstate', $statefile;
3180 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3181 my $d = parse_hostpci
($conf->{"hostpci$i"});
3183 my $info = pci_device_info
("0000:$d->{pciid}");
3184 die "IOMMU not present\n" if !check_iommu_support
();
3185 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3186 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3187 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3190 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3192 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3195 die "start failed: $err" if $err;
3197 print "migration listens on $migrate_uri\n" if $migrate_uri;
3199 if ($statefile && $statefile ne 'tcp') {
3200 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3204 if ($migratedfrom) {
3207 PVE
::QemuServer
::set_migration_caps
($vmid);
3212 print "spice listens on port $spice_port\n";
3213 if ($spice_ticket) {
3214 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3215 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3221 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3222 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3223 if $conf->{balloon
};
3224 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3225 path
=> "machine/peripheral/balloon0",
3226 property
=> "guest-stats-polling-interval",
3234 my ($vmid, $execute, %params) = @_;
3236 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3237 vm_qmp_command
($vmid, $cmd);
3240 sub vm_mon_cmd_nocheck
{
3241 my ($vmid, $execute, %params) = @_;
3243 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3244 vm_qmp_command
($vmid, $cmd, 1);
3247 sub vm_qmp_command
{
3248 my ($vmid, $cmd, $nocheck) = @_;
3253 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3254 $timeout = $cmd->{arguments
}->{timeout
};
3255 delete $cmd->{arguments
}->{timeout
};
3259 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3260 my $sname = qmp_socket
($vmid);
3262 my $qmpclient = PVE
::QMPClient-
>new();
3264 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3265 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3266 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3267 if scalar(%{$cmd->{arguments
}});
3268 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3270 die "unable to open monitor socket\n";
3274 syslog
("err", "VM $vmid qmp command failed - $err");
3281 sub vm_human_monitor_command
{
3282 my ($vmid, $cmdline) = @_;
3287 execute
=> 'human-monitor-command',
3288 arguments
=> { 'command-line' => $cmdline},
3291 return vm_qmp_command
($vmid, $cmd);
3294 sub vm_commandline
{
3295 my ($storecfg, $vmid) = @_;
3297 my $conf = load_config
($vmid);
3299 my $defaults = load_defaults
();
3301 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3303 return join(' ', @$cmd);
3307 my ($vmid, $skiplock) = @_;
3309 lock_config
($vmid, sub {
3311 my $conf = load_config
($vmid);
3313 check_lock
($conf) if !$skiplock;
3315 vm_mon_cmd
($vmid, "system_reset");
3319 sub get_vm_volumes
{
3323 foreach_volid
($conf, sub {
3324 my ($volid, $is_cdrom) = @_;
3326 return if $volid =~ m
|^/|;
3328 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3331 push @$vollist, $volid;
3337 sub vm_stop_cleanup
{
3338 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3341 fairsched_rmnod
($vmid); # try to destroy group
3344 my $vollist = get_vm_volumes
($conf);
3345 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3348 foreach my $ext (qw(mon qmp pid vnc qga)) {
3349 unlink "/var/run/qemu-server/${vmid}.$ext";
3352 warn $@ if $@; # avoid errors - just warn
3355 # Note: use $nockeck to skip tests if VM configuration file exists.
3356 # We need that when migration VMs to other nodes (files already moved)
3357 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3359 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3361 $force = 1 if !defined($force) && !$shutdown;
3364 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3365 kill 15, $pid if $pid;
3366 my $conf = load_config
($vmid, $migratedfrom);
3367 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3371 lock_config
($vmid, sub {
3373 my $pid = check_running
($vmid, $nocheck);
3378 $conf = load_config
($vmid);
3379 check_lock
($conf) if !$skiplock;
3380 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3381 my $opts = parse_startup
($conf->{startup
});
3382 $timeout = $opts->{down
} if $opts->{down
};
3386 $timeout = 60 if !defined($timeout);
3390 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3393 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3400 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3405 if ($count >= $timeout) {
3407 warn "VM still running - terminating now with SIGTERM\n";
3410 die "VM quit/powerdown failed - got timeout\n";
3413 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3418 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3421 die "VM quit/powerdown failed\n";
3429 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3434 if ($count >= $timeout) {
3435 warn "VM still running - terminating now with SIGKILL\n";
3440 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3445 my ($vmid, $skiplock) = @_;
3447 lock_config
($vmid, sub {
3449 my $conf = load_config
($vmid);
3451 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3453 vm_mon_cmd
($vmid, "stop");
3458 my ($vmid, $skiplock) = @_;
3460 lock_config
($vmid, sub {
3462 my $conf = load_config
($vmid);
3464 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3466 vm_mon_cmd
($vmid, "cont");
3471 my ($vmid, $skiplock, $key) = @_;
3473 lock_config
($vmid, sub {
3475 my $conf = load_config
($vmid);
3477 # there is no qmp command, so we use the human monitor command
3478 vm_human_monitor_command
($vmid, "sendkey $key");
3483 my ($storecfg, $vmid, $skiplock) = @_;
3485 lock_config
($vmid, sub {
3487 my $conf = load_config
($vmid);
3489 check_lock
($conf) if !$skiplock;
3491 if (!check_running
($vmid)) {
3492 fairsched_rmnod
($vmid); # try to destroy group
3493 destroy_vm
($storecfg, $vmid);
3495 die "VM $vmid is running - destroy failed\n";
3503 my ($filename, $buf) = @_;
3505 my $fh = IO
::File-
>new($filename, "w");
3506 return undef if !$fh;
3508 my $res = print $fh $buf;
3515 sub pci_device_info
{
3520 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3521 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3523 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3524 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3526 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3527 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3529 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3530 return undef if !defined($product) || $product !~ s/^0x//;
3535 product
=> $product,
3541 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3550 my $name = $dev->{name
};
3552 my $fn = "$pcisysfs/devices/$name/reset";
3554 return file_write
($fn, "1");
3557 sub pci_dev_bind_to_stub
{
3560 my $name = $dev->{name
};
3562 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3563 return 1 if -d
$testdir;
3565 my $data = "$dev->{vendor} $dev->{product}";
3566 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3568 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3569 if (!file_write
($fn, $name)) {
3570 return undef if -f
$fn;
3573 $fn = "$pcisysfs/drivers/pci-stub/bind";
3574 if (! -d
$testdir) {
3575 return undef if !file_write
($fn, $name);
3581 sub print_pci_addr
{
3582 my ($id, $bridges) = @_;
3586 piix3
=> { bus
=> 0, addr
=> 1 },
3587 #addr2 : first videocard
3588 balloon0
=> { bus
=> 0, addr
=> 3 },
3589 watchdog
=> { bus
=> 0, addr
=> 4 },
3590 scsihw0
=> { bus
=> 0, addr
=> 5 },
3591 scsihw1
=> { bus
=> 0, addr
=> 6 },
3592 ahci0
=> { bus
=> 0, addr
=> 7 },
3593 qga0
=> { bus
=> 0, addr
=> 8 },
3594 spice
=> { bus
=> 0, addr
=> 9 },
3595 virtio0
=> { bus
=> 0, addr
=> 10 },
3596 virtio1
=> { bus
=> 0, addr
=> 11 },
3597 virtio2
=> { bus
=> 0, addr
=> 12 },
3598 virtio3
=> { bus
=> 0, addr
=> 13 },
3599 virtio4
=> { bus
=> 0, addr
=> 14 },
3600 virtio5
=> { bus
=> 0, addr
=> 15 },
3601 hostpci0
=> { bus
=> 0, addr
=> 16 },
3602 hostpci1
=> { bus
=> 0, addr
=> 17 },
3603 net0
=> { bus
=> 0, addr
=> 18 },
3604 net1
=> { bus
=> 0, addr
=> 19 },
3605 net2
=> { bus
=> 0, addr
=> 20 },
3606 net3
=> { bus
=> 0, addr
=> 21 },
3607 net4
=> { bus
=> 0, addr
=> 22 },
3608 net5
=> { bus
=> 0, addr
=> 23 },
3609 vga1
=> { bus
=> 0, addr
=> 24 },
3610 vga2
=> { bus
=> 0, addr
=> 25 },
3611 vga3
=> { bus
=> 0, addr
=> 26 },
3612 #addr29 : usb-host (pve-usb.cfg)
3613 'pci.1' => { bus
=> 0, addr
=> 30 },
3614 'pci.2' => { bus
=> 0, addr
=> 31 },
3615 'net6' => { bus
=> 1, addr
=> 1 },
3616 'net7' => { bus
=> 1, addr
=> 2 },
3617 'net8' => { bus
=> 1, addr
=> 3 },
3618 'net9' => { bus
=> 1, addr
=> 4 },
3619 'net10' => { bus
=> 1, addr
=> 5 },
3620 'net11' => { bus
=> 1, addr
=> 6 },
3621 'net12' => { bus
=> 1, addr
=> 7 },
3622 'net13' => { bus
=> 1, addr
=> 8 },
3623 'net14' => { bus
=> 1, addr
=> 9 },
3624 'net15' => { bus
=> 1, addr
=> 10 },
3625 'net16' => { bus
=> 1, addr
=> 11 },
3626 'net17' => { bus
=> 1, addr
=> 12 },
3627 'net18' => { bus
=> 1, addr
=> 13 },
3628 'net19' => { bus
=> 1, addr
=> 14 },
3629 'net20' => { bus
=> 1, addr
=> 15 },
3630 'net21' => { bus
=> 1, addr
=> 16 },
3631 'net22' => { bus
=> 1, addr
=> 17 },
3632 'net23' => { bus
=> 1, addr
=> 18 },
3633 'net24' => { bus
=> 1, addr
=> 19 },
3634 'net25' => { bus
=> 1, addr
=> 20 },
3635 'net26' => { bus
=> 1, addr
=> 21 },
3636 'net27' => { bus
=> 1, addr
=> 22 },
3637 'net28' => { bus
=> 1, addr
=> 23 },
3638 'net29' => { bus
=> 1, addr
=> 24 },
3639 'net30' => { bus
=> 1, addr
=> 25 },
3640 'net31' => { bus
=> 1, addr
=> 26 },
3641 'virtio6' => { bus
=> 2, addr
=> 1 },
3642 'virtio7' => { bus
=> 2, addr
=> 2 },
3643 'virtio8' => { bus
=> 2, addr
=> 3 },
3644 'virtio9' => { bus
=> 2, addr
=> 4 },
3645 'virtio10' => { bus
=> 2, addr
=> 5 },
3646 'virtio11' => { bus
=> 2, addr
=> 6 },
3647 'virtio12' => { bus
=> 2, addr
=> 7 },
3648 'virtio13' => { bus
=> 2, addr
=> 8 },
3649 'virtio14' => { bus
=> 2, addr
=> 9 },
3650 'virtio15' => { bus
=> 2, addr
=> 10 },
3653 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3654 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3655 my $bus = $devices->{$id}->{bus
};
3656 $res = ",bus=pci.$bus,addr=$addr";
3657 $bridges->{$bus} = 1 if $bridges;
3663 # vzdump restore implementaion
3665 sub tar_archive_read_firstfile
{
3666 my $archive = shift;
3668 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3670 # try to detect archive type first
3671 my $pid = open (TMP
, "tar tf '$archive'|") ||
3672 die "unable to open file '$archive'\n";
3673 my $firstfile = <TMP
>;
3677 die "ERROR: archive contaions no data\n" if !$firstfile;
3683 sub tar_restore_cleanup
{
3684 my ($storecfg, $statfile) = @_;
3686 print STDERR
"starting cleanup\n";
3688 if (my $fd = IO
::File-
>new($statfile, "r")) {
3689 while (defined(my $line = <$fd>)) {
3690 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3693 if ($volid =~ m
|^/|) {
3694 unlink $volid || die 'unlink failed\n';
3696 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3698 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3700 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3702 print STDERR
"unable to parse line in statfile - $line";
3709 sub restore_archive
{
3710 my ($archive, $vmid, $user, $opts) = @_;
3712 my $format = $opts->{format
};
3715 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3716 $format = 'tar' if !$format;
3718 } elsif ($archive =~ m/\.tar$/) {
3719 $format = 'tar' if !$format;
3720 } elsif ($archive =~ m/.tar.lzo$/) {
3721 $format = 'tar' if !$format;
3723 } elsif ($archive =~ m/\.vma$/) {
3724 $format = 'vma' if !$format;
3725 } elsif ($archive =~ m/\.vma\.gz$/) {
3726 $format = 'vma' if !$format;
3728 } elsif ($archive =~ m/\.vma\.lzo$/) {
3729 $format = 'vma' if !$format;
3732 $format = 'vma' if !$format; # default
3735 # try to detect archive format
3736 if ($format eq 'tar') {
3737 return restore_tar_archive
($archive, $vmid, $user, $opts);
3739 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3743 sub restore_update_config_line
{
3744 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3746 return if $line =~ m/^\#qmdump\#/;
3747 return if $line =~ m/^\#vzdump\#/;
3748 return if $line =~ m/^lock:/;
3749 return if $line =~ m/^unused\d+:/;
3750 return if $line =~ m/^parent:/;
3751 return if $line =~ m/^template:/; # restored VM is never a template
3753 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3754 # try to convert old 1.X settings
3755 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3756 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3757 my ($model, $macaddr) = split(/\=/, $devconfig);
3758 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3761 bridge
=> "vmbr$ind",
3762 macaddr
=> $macaddr,
3764 my $netstr = print_net
($net);
3766 print $outfd "net$cookie->{netcount}: $netstr\n";
3767 $cookie->{netcount
}++;
3769 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3770 my ($id, $netstr) = ($1, $2);
3771 my $net = parse_net
($netstr);
3772 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3773 $netstr = print_net
($net);
3774 print $outfd "$id: $netstr\n";
3775 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3778 if ($line =~ m/backup=no/) {
3779 print $outfd "#$line";
3780 } elsif ($virtdev && $map->{$virtdev}) {
3781 my $di = parse_drive
($virtdev, $value);
3782 delete $di->{format
}; # format can change on restore
3783 $di->{file
} = $map->{$virtdev};
3784 $value = print_drive
($vmid, $di);
3785 print $outfd "$virtdev: $value\n";
3795 my ($cfg, $vmid) = @_;
3797 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3799 my $volid_hash = {};
3800 foreach my $storeid (keys %$info) {
3801 foreach my $item (@{$info->{$storeid}}) {
3802 next if !($item->{volid
} && $item->{size
});
3803 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3804 $volid_hash->{$item->{volid
}} = $item;
3811 sub get_used_paths
{
3812 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3816 my $scan_config = sub {
3817 my ($cref, $snapname) = @_;
3819 foreach my $key (keys %$cref) {
3820 my $value = $cref->{$key};
3821 if (valid_drivename
($key)) {
3822 next if $skip_drive && $key eq $skip_drive;
3823 my $drive = parse_drive
($key, $value);
3824 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3825 if ($drive->{file
} =~ m!^/!) {
3826 $used_path->{$drive->{file
}}++; # = 1;
3828 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3830 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3832 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3833 $used_path->{$path}++; # = 1;
3839 &$scan_config($conf);
3843 if ($scan_snapshots) {
3844 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3845 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3852 sub update_disksize
{
3853 my ($vmid, $conf, $volid_hash) = @_;
3859 # Note: it is allowed to define multiple storages with same path (alias), so
3860 # we need to check both 'volid' and real 'path' (two different volid can point
3861 # to the same path).
3866 foreach my $opt (keys %$conf) {
3867 if (valid_drivename
($opt)) {
3868 my $drive = parse_drive
($opt, $conf->{$opt});
3869 my $volid = $drive->{file
};
3872 $used->{$volid} = 1;
3873 if ($volid_hash->{$volid} &&
3874 (my $path = $volid_hash->{$volid}->{path
})) {
3875 $usedpath->{$path} = 1;
3878 next if drive_is_cdrom
($drive);
3879 next if !$volid_hash->{$volid};
3881 $drive->{size
} = $volid_hash->{$volid}->{size
};
3882 my $new = print_drive
($vmid, $drive);
3883 if ($new ne $conf->{$opt}) {
3885 $conf->{$opt} = $new;
3890 # remove 'unusedX' entry if volume is used
3891 foreach my $opt (keys %$conf) {
3892 next if $opt !~ m/^unused\d+$/;
3893 my $volid = $conf->{$opt};
3894 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3895 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3897 delete $conf->{$opt};
3901 foreach my $volid (sort keys %$volid_hash) {
3902 next if $volid =~ m/vm-$vmid-state-/;
3903 next if $used->{$volid};
3904 my $path = $volid_hash->{$volid}->{path
};
3905 next if !$path; # just to be sure
3906 next if $usedpath->{$path};
3908 add_unused_volume
($conf, $volid);
3909 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3916 my ($vmid, $nolock) = @_;
3918 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3920 my $volid_hash = scan_volids
($cfg, $vmid);
3922 my $updatefn = sub {
3925 my $conf = load_config
($vmid);
3930 foreach my $volid (keys %$volid_hash) {
3931 my $info = $volid_hash->{$volid};
3932 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3935 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3937 update_config_nolock
($vmid, $conf, 1) if $changes;
3940 if (defined($vmid)) {
3944 lock_config
($vmid, $updatefn, $vmid);
3947 my $vmlist = config_list
();
3948 foreach my $vmid (keys %$vmlist) {
3952 lock_config
($vmid, $updatefn, $vmid);
3958 sub restore_vma_archive
{
3959 my ($archive, $vmid, $user, $opts, $comp) = @_;
3961 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3962 my $readfrom = $archive;
3967 my $qarchive = PVE
::Tools
::shellquote
($archive);
3968 if ($comp eq 'gzip') {
3969 $uncomp = "zcat $qarchive|";
3970 } elsif ($comp eq 'lzop') {
3971 $uncomp = "lzop -d -c $qarchive|";
3973 die "unknown compression method '$comp'\n";
3978 my $tmpdir = "/var/tmp/vzdumptmp$$";
3981 # disable interrupts (always do cleanups)
3982 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3983 warn "got interrupt - ignored\n";
3986 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3987 POSIX
::mkfifo
($mapfifo, 0600);
3990 my $openfifo = sub {
3991 open($fifofh, '>', $mapfifo) || die $!;
3994 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4001 my $rpcenv = PVE
::RPCEnvironment
::get
();
4003 my $conffile = config_file
($vmid);
4004 my $tmpfn = "$conffile.$$.tmp";
4006 # Note: $oldconf is undef if VM does not exists
4007 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4009 my $print_devmap = sub {
4010 my $virtdev_hash = {};
4012 my $cfgfn = "$tmpdir/qemu-server.conf";
4014 # we can read the config - that is already extracted
4015 my $fh = IO
::File-
>new($cfgfn, "r") ||
4016 "unable to read qemu-server.conf - $!\n";
4018 while (defined(my $line = <$fh>)) {
4019 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4020 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4021 die "archive does not contain data for drive '$virtdev'\n"
4022 if !$devinfo->{$devname};
4023 if (defined($opts->{storage
})) {
4024 $storeid = $opts->{storage
} || 'local';
4025 } elsif (!$storeid) {
4028 $format = 'raw' if !$format;
4029 $devinfo->{$devname}->{devname
} = $devname;
4030 $devinfo->{$devname}->{virtdev
} = $virtdev;
4031 $devinfo->{$devname}->{format
} = $format;
4032 $devinfo->{$devname}->{storeid
} = $storeid;
4034 # check permission on storage
4035 my $pool = $opts->{pool
}; # todo: do we need that?
4036 if ($user ne 'root@pam') {
4037 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4040 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4044 foreach my $devname (keys %$devinfo) {
4045 die "found no device mapping information for device '$devname'\n"
4046 if !$devinfo->{$devname}->{virtdev
};
4049 my $cfg = cfs_read_file
('storage.cfg');
4051 # create empty/temp config
4053 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4054 foreach_drive
($oldconf, sub {
4055 my ($ds, $drive) = @_;
4057 return if drive_is_cdrom
($drive);
4059 my $volid = $drive->{file
};
4061 return if !$volid || $volid =~ m
|^/|;
4063 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4064 return if !$path || !$owner || ($owner != $vmid);
4066 # Note: only delete disk we want to restore
4067 # other volumes will become unused
4068 if ($virtdev_hash->{$ds}) {
4069 PVE
::Storage
::vdisk_free
($cfg, $volid);
4075 foreach my $virtdev (sort keys %$virtdev_hash) {
4076 my $d = $virtdev_hash->{$virtdev};
4077 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4078 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4080 # test if requested format is supported
4081 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4082 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4083 $d->{format
} = $defFormat if !$supported;
4085 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4086 $d->{format
}, undef, $alloc_size);
4087 print STDERR
"new volume ID is '$volid'\n";
4088 $d->{volid
} = $volid;
4089 my $path = PVE
::Storage
::path
($cfg, $volid);
4091 my $write_zeros = 1;
4092 # fixme: what other storages types initialize volumes with zero?
4093 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4094 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4098 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4100 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4101 $map->{$virtdev} = $volid;
4104 $fh->seek(0, 0) || die "seek failed - $!\n";
4106 my $outfd = new IO
::File
($tmpfn, "w") ||
4107 die "unable to write config for VM $vmid\n";
4109 my $cookie = { netcount
=> 0 };
4110 while (defined(my $line = <$fh>)) {
4111 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4120 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4121 die "interrupted by signal\n";
4123 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4125 $oldtimeout = alarm($timeout);
4132 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4133 my ($dev_id, $size, $devname) = ($1, $2, $3);
4134 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4135 } elsif ($line =~ m/^CTIME: /) {
4137 print $fifofh "done\n";
4138 my $tmp = $oldtimeout || 0;
4139 $oldtimeout = undef;
4145 print "restore vma archive: $cmd\n";
4146 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4150 alarm($oldtimeout) if $oldtimeout;
4158 my $cfg = cfs_read_file
('storage.cfg');
4159 foreach my $devname (keys %$devinfo) {
4160 my $volid = $devinfo->{$devname}->{volid
};
4163 if ($volid =~ m
|^/|) {
4164 unlink $volid || die 'unlink failed\n';
4166 PVE
::Storage
::vdisk_free
($cfg, $volid);
4168 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4170 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4177 rename($tmpfn, $conffile) ||
4178 die "unable to commit configuration file '$conffile'\n";
4180 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4182 eval { rescan
($vmid, 1); };
4186 sub restore_tar_archive
{
4187 my ($archive, $vmid, $user, $opts) = @_;
4189 if ($archive ne '-') {
4190 my $firstfile = tar_archive_read_firstfile
($archive);
4191 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4192 if $firstfile ne 'qemu-server.conf';
4195 my $storecfg = cfs_read_file
('storage.cfg');
4197 # destroy existing data - keep empty config
4198 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4199 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4201 my $tocmd = "/usr/lib/qemu-server/qmextract";
4203 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4204 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4205 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4206 $tocmd .= ' --info' if $opts->{info
};
4208 # tar option "xf" does not autodetect compression when read from STDIN,
4209 # so we pipe to zcat
4210 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4211 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4213 my $tmpdir = "/var/tmp/vzdumptmp$$";
4216 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4217 local $ENV{VZDUMP_VMID
} = $vmid;
4218 local $ENV{VZDUMP_USER
} = $user;
4220 my $conffile = config_file
($vmid);
4221 my $tmpfn = "$conffile.$$.tmp";
4223 # disable interrupts (always do cleanups)
4224 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4225 print STDERR
"got interrupt - ignored\n";
4230 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4231 die "interrupted by signal\n";
4234 if ($archive eq '-') {
4235 print "extracting archive from STDIN\n";
4236 run_command
($cmd, input
=> "<&STDIN");
4238 print "extracting archive '$archive'\n";
4242 return if $opts->{info
};
4246 my $statfile = "$tmpdir/qmrestore.stat";
4247 if (my $fd = IO
::File-
>new($statfile, "r")) {
4248 while (defined (my $line = <$fd>)) {
4249 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4250 $map->{$1} = $2 if $1;
4252 print STDERR
"unable to parse line in statfile - $line\n";
4258 my $confsrc = "$tmpdir/qemu-server.conf";
4260 my $srcfd = new IO
::File
($confsrc, "r") ||
4261 die "unable to open file '$confsrc'\n";
4263 my $outfd = new IO
::File
($tmpfn, "w") ||
4264 die "unable to write config for VM $vmid\n";
4266 my $cookie = { netcount
=> 0 };
4267 while (defined (my $line = <$srcfd>)) {
4268 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4280 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4287 rename $tmpfn, $conffile ||
4288 die "unable to commit configuration file '$conffile'\n";
4290 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4292 eval { rescan
($vmid, 1); };
4297 # Internal snapshots
4299 # NOTE: Snapshot create/delete involves several non-atomic
4300 # action, and can take a long time.
4301 # So we try to avoid locking the file and use 'lock' variable
4302 # inside the config file instead.
4304 my $snapshot_copy_config = sub {
4305 my ($source, $dest) = @_;
4307 foreach my $k (keys %$source) {
4308 next if $k eq 'snapshots';
4309 next if $k eq 'snapstate';
4310 next if $k eq 'snaptime';
4311 next if $k eq 'vmstate';
4312 next if $k eq 'lock';
4313 next if $k eq 'digest';
4314 next if $k eq 'description';
4315 next if $k =~ m/^unused\d+$/;
4317 $dest->{$k} = $source->{$k};
4321 my $snapshot_apply_config = sub {
4322 my ($conf, $snap) = @_;
4324 # copy snapshot list
4326 snapshots
=> $conf->{snapshots
},
4329 # keep description and list of unused disks
4330 foreach my $k (keys %$conf) {
4331 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4332 $newconf->{$k} = $conf->{$k};
4335 &$snapshot_copy_config($snap, $newconf);
4340 sub foreach_writable_storage
{
4341 my ($conf, $func) = @_;
4345 foreach my $ds (keys %$conf) {
4346 next if !valid_drivename
($ds);
4348 my $drive = parse_drive
($ds, $conf->{$ds});
4350 next if drive_is_cdrom
($drive);
4352 my $volid = $drive->{file
};
4354 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4355 $sidhash->{$sid} = $sid if $sid;
4358 foreach my $sid (sort keys %$sidhash) {
4363 my $alloc_vmstate_volid = sub {
4364 my ($storecfg, $vmid, $conf, $snapname) = @_;
4366 # Note: we try to be smart when selecting a $target storage
4370 # search shared storage first
4371 foreach_writable_storage
($conf, sub {
4373 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4374 return if !$scfg->{shared
};
4376 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4380 # now search local storage
4381 foreach_writable_storage
($conf, sub {
4383 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4384 return if $scfg->{shared
};
4386 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4390 $target = 'local' if !$target;
4392 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4393 # we abort live save after $conf->{memory}, so we need at max twice that space
4394 my $size = $conf->{memory
}*2 + $driver_state_size;
4396 my $name = "vm-$vmid-state-$snapname";
4397 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4398 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4399 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4404 my $snapshot_prepare = sub {
4405 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4409 my $updatefn = sub {
4411 my $conf = load_config
($vmid);
4413 die "you can't take a snapshot if it's a template\n"
4414 if is_template
($conf);
4418 $conf->{lock} = 'snapshot';
4420 die "snapshot name '$snapname' already used\n"
4421 if defined($conf->{snapshots
}->{$snapname});
4423 my $storecfg = PVE
::Storage
::config
();
4424 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4426 $snap = $conf->{snapshots
}->{$snapname} = {};
4428 if ($save_vmstate && check_running
($vmid)) {
4429 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4432 &$snapshot_copy_config($conf, $snap);
4434 $snap->{snapstate
} = "prepare";
4435 $snap->{snaptime
} = time();
4436 $snap->{description
} = $comment if $comment;
4438 # always overwrite machine if we save vmstate. This makes sure we
4439 # can restore it later using correct machine type
4440 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4442 update_config_nolock
($vmid, $conf, 1);
4445 lock_config
($vmid, $updatefn);
4450 my $snapshot_commit = sub {
4451 my ($vmid, $snapname) = @_;
4453 my $updatefn = sub {
4455 my $conf = load_config
($vmid);
4457 die "missing snapshot lock\n"
4458 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4460 my $snap = $conf->{snapshots
}->{$snapname};
4462 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4464 die "wrong snapshot state\n"
4465 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4467 delete $snap->{snapstate
};
4468 delete $conf->{lock};
4470 my $newconf = &$snapshot_apply_config($conf, $snap);
4472 $newconf->{parent
} = $snapname;
4474 update_config_nolock
($vmid, $newconf, 1);
4477 lock_config
($vmid, $updatefn);
4480 sub snapshot_rollback
{
4481 my ($vmid, $snapname) = @_;
4487 my $storecfg = PVE
::Storage
::config
();
4489 my $updatefn = sub {
4491 my $conf = load_config
($vmid);
4493 die "you can't rollback if vm is a template\n" if is_template
($conf);
4495 $snap = $conf->{snapshots
}->{$snapname};
4497 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4499 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4500 if $snap->{snapstate
};
4504 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4507 die "unable to rollback vm $vmid: vm is running\n"
4508 if check_running
($vmid);
4511 $conf->{lock} = 'rollback';
4513 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4514 delete $conf->{lock};
4520 my $has_machine_config = defined($conf->{machine
});
4522 # copy snapshot config to current config
4523 $conf = &$snapshot_apply_config($conf, $snap);
4524 $conf->{parent
} = $snapname;
4526 # Note: old code did not store 'machine', so we try to be smart
4527 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4528 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4529 # we remove the 'machine' configuration if not explicitly specified
4530 # in the original config.
4531 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4534 update_config_nolock
($vmid, $conf, 1);
4536 if (!$prepare && $snap->{vmstate
}) {
4537 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4538 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4542 lock_config
($vmid, $updatefn);
4544 foreach_drive
($snap, sub {
4545 my ($ds, $drive) = @_;
4547 return if drive_is_cdrom
($drive);
4549 my $volid = $drive->{file
};
4550 my $device = "drive-$ds";
4552 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4556 lock_config
($vmid, $updatefn);
4559 my $savevm_wait = sub {
4563 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4564 if (!$stat->{status
}) {
4565 die "savevm not active\n";
4566 } elsif ($stat->{status
} eq 'active') {
4569 } elsif ($stat->{status
} eq 'completed') {
4572 die "query-savevm returned status '$stat->{status}'\n";
4577 sub snapshot_create
{
4578 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4580 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4582 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4586 my $running = check_running
($vmid);
4589 # create internal snapshots of all drives
4591 my $storecfg = PVE
::Storage
::config
();
4594 if ($snap->{vmstate
}) {
4595 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4596 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4597 &$savevm_wait($vmid);
4599 vm_mon_cmd
($vmid, "savevm-start");
4603 qga_freezefs
($vmid) if $running && $freezefs;
4605 foreach_drive
($snap, sub {
4606 my ($ds, $drive) = @_;
4608 return if drive_is_cdrom
($drive);
4610 my $volid = $drive->{file
};
4611 my $device = "drive-$ds";
4613 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4614 $drivehash->{$ds} = 1;
4619 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4622 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4626 warn "snapshot create failed: starting cleanup\n";
4627 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4632 &$snapshot_commit($vmid, $snapname);
4635 # Note: $drivehash is only set when called from snapshot_create.
4636 sub snapshot_delete
{
4637 my ($vmid, $snapname, $force, $drivehash) = @_;
4644 my $unlink_parent = sub {
4645 my ($confref, $new_parent) = @_;
4647 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4649 $confref->{parent
} = $new_parent;
4651 delete $confref->{parent
};
4656 my $updatefn = sub {
4657 my ($remove_drive) = @_;
4659 my $conf = load_config
($vmid);
4663 die "you can't delete a snapshot if vm is a template\n"
4664 if is_template
($conf);
4667 $snap = $conf->{snapshots
}->{$snapname};
4669 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4671 # remove parent refs
4672 &$unlink_parent($conf, $snap->{parent
});
4673 foreach my $sn (keys %{$conf->{snapshots
}}) {
4674 next if $sn eq $snapname;
4675 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4678 if ($remove_drive) {
4679 if ($remove_drive eq 'vmstate') {
4680 delete $snap->{$remove_drive};
4682 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4683 my $volid = $drive->{file
};
4684 delete $snap->{$remove_drive};
4685 add_unused_volume
($conf, $volid);
4690 $snap->{snapstate
} = 'delete';
4692 delete $conf->{snapshots
}->{$snapname};
4693 delete $conf->{lock} if $drivehash;
4694 foreach my $volid (@$unused) {
4695 add_unused_volume
($conf, $volid);
4699 update_config_nolock
($vmid, $conf, 1);
4702 lock_config
($vmid, $updatefn);
4704 # now remove vmstate file
4706 my $storecfg = PVE
::Storage
::config
();
4708 if ($snap->{vmstate
}) {
4709 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4711 die $err if !$force;
4714 # save changes (remove vmstate from snapshot)
4715 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4718 # now remove all internal snapshots
4719 foreach_drive
($snap, sub {
4720 my ($ds, $drive) = @_;
4722 return if drive_is_cdrom
($drive);
4724 my $volid = $drive->{file
};
4725 my $device = "drive-$ds";
4727 if (!$drivehash || $drivehash->{$ds}) {
4728 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4730 die $err if !$force;
4735 # save changes (remove drive fron snapshot)
4736 lock_config
($vmid, $updatefn, $ds) if !$force;
4737 push @$unused, $volid;
4740 # now cleanup config
4742 lock_config
($vmid, $updatefn);
4746 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4749 foreach_drive
($conf, sub {
4750 my ($ds, $drive) = @_;
4752 return if drive_is_cdrom
($drive);
4753 my $volid = $drive->{file
};
4754 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4757 return $err ?
0 : 1;
4760 sub template_create
{
4761 my ($vmid, $conf, $disk) = @_;
4763 my $storecfg = PVE
::Storage
::config
();
4765 foreach_drive
($conf, sub {
4766 my ($ds, $drive) = @_;
4768 return if drive_is_cdrom
($drive);
4769 return if $disk && $ds ne $disk;
4771 my $volid = $drive->{file
};
4772 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4774 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4775 $drive->{file
} = $voliddst;
4776 $conf->{$ds} = print_drive
($vmid, $drive);
4777 update_config_nolock
($vmid, $conf, 1);
4784 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4787 sub qemu_img_convert
{
4788 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4790 my $storecfg = PVE
::Storage
::config
();
4791 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4792 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4794 if ($src_storeid && $dst_storeid) {
4795 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4796 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4798 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4799 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4801 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4802 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4805 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4806 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4807 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4811 if($line =~ m/\((\S+)\/100\
%\)/){
4813 my $transferred = int($size * $percent / 100);
4814 my $remaining = $size - $transferred;
4816 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4821 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4823 die "copy failed: $err" if $err;
4827 sub qemu_img_format
{
4828 my ($scfg, $volname) = @_;
4830 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4832 } elsif ($scfg->{type
} eq 'iscsi') {
4833 return "host_device";
4839 sub qemu_drive_mirror
{
4840 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4846 my $storecfg = PVE
::Storage
::config
();
4847 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4850 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4853 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4857 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4860 #fixme : sometime drive-mirror timeout, but works fine after.
4861 # (I have see the problem with big volume > 200GB), so we need to eval
4862 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4863 sync
=> "full", target
=> $dst_path, format
=> $format); };
4865 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4866 sync
=> "full", target
=> $dst_path); };
4871 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4872 my $stat = @$stats[0];
4873 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4874 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4876 my $transferred = $stat->{offset
};
4877 my $total = $stat->{len
};
4878 my $remaining = $total - $transferred;
4879 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4881 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4883 last if ($stat->{len
} == $stat->{offset
});
4884 if ($old_len == $stat->{offset
}) {
4885 if ($maxwait && $count > $maxwait) {
4886 # if writes to disk occurs the disk needs to be freezed
4887 # to be able to complete the migration
4888 vm_suspend
($vmid,1);
4892 $count++ unless $frozen;
4898 $old_len = $stat->{offset
};
4902 if ($vmiddst == $vmid) {
4903 # switch the disk if source and destination are on the same guest
4904 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4908 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4909 die "mirroring error: $err";
4912 if ($vmiddst != $vmid) {
4913 # if we clone a disk for a new target vm, we don't switch the disk
4914 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4920 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4921 $newvmid, $storage, $format, $full, $newvollist) = @_;
4926 print "create linked clone of drive $drivename ($drive->{file})\n";
4927 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4928 push @$newvollist, $newvolid;
4930 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4931 $storeid = $storage if $storage;
4933 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4935 $format = $drive->{format
} || $defFormat;
4938 # test if requested format is supported - else use default
4939 my $supported = grep { $_ eq $format } @$validFormats;
4940 $format = $defFormat if !$supported;
4942 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4944 print "create full clone of drive $drivename ($drive->{file})\n";
4945 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4946 push @$newvollist, $newvolid;
4948 if (!$running || $snapname) {
4949 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4951 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4955 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4958 $disk->{format
} = undef;
4959 $disk->{file
} = $newvolid;
4960 $disk->{size
} = $size;
4965 # this only works if VM is running
4966 sub get_current_qemu_machine
{
4969 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4970 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4972 my ($current, $default);
4973 foreach my $e (@$res) {
4974 $default = $e->{name
} if $e->{'is-default'};
4975 $current = $e->{name
} if $e->{'is-current'};
4978 # fallback to the default machine if current is not supported by qemu
4979 return $current || $default || 'pc';