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>][,firewall=0|1]",
482 description
=> <<EODESCR,
483 Specify network devices.
485 MODEL is one of: $nic_model_list_txt
487 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
488 automatically generated if not specified.
490 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
492 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
494 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
500 The DHCP server assign addresses to the guest starting from 10.0.2.15.
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
506 for (my $i = 0; $i < $MAX_NETS; $i++) {
507 $confdesc->{"net$i"} = $netdesc;
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
516 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
524 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
530 type
=> 'string', format
=> 'pve-qm-drive',
531 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
532 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
534 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
538 type
=> 'string', format
=> 'pve-qm-drive',
539 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
540 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
542 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
546 type
=> 'string', format
=> 'pve-qm-usb-device',
547 typetext
=> 'host=HOSTUSBDEVICE|spice',
548 description
=> <<EODESCR,
549 Configure an USB device (n is 0 to 4). This can be used to
550 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
552 'bus-port(.port)*' (decimal numbers) or
553 'vendor_id:product_id' (hexadeciaml numbers)
555 You can use the 'lsusb -t' command to list existing usb devices.
557 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
559 The value 'spice' can be used to add a usb redirection devices for spice.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
567 type
=> 'string', format
=> 'pve-qm-hostpci',
568 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]",
569 description
=> <<EODESCR,
570 Map host pci devices. HOSTPCIDEVICE syntax is:
572 'bus:dev.func' (hexadecimal numbers)
574 You can us the 'lspci' command to list existing pci devices.
576 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
578 The 'driver' option is currently ignored.
580 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
582 Experimental: user reported problems with this option.
585 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
590 pattern
=> '(/dev/ttyS\d+|socket)',
591 description
=> <<EODESCR,
592 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
594 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
596 Experimental: user reported problems with this option.
603 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
604 description
=> <<EODESCR,
605 Map host parallel devices (n is 0 to 2).
607 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
609 Experimental: user reported problems with this option.
613 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
614 $confdesc->{"parallel$i"} = $paralleldesc;
617 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
618 $confdesc->{"serial$i"} = $serialdesc;
621 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
622 $confdesc->{"hostpci$i"} = $hostpcidesc;
625 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
626 $drivename_hash->{"ide$i"} = 1;
627 $confdesc->{"ide$i"} = $idedesc;
630 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
631 $drivename_hash->{"sata$i"} = 1;
632 $confdesc->{"sata$i"} = $satadesc;
635 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
636 $drivename_hash->{"scsi$i"} = 1;
637 $confdesc->{"scsi$i"} = $scsidesc ;
640 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
641 $drivename_hash->{"virtio$i"} = 1;
642 $confdesc->{"virtio$i"} = $virtiodesc;
645 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
646 $confdesc->{"usb$i"} = $usbdesc;
651 type
=> 'string', format
=> 'pve-volume-id',
652 description
=> "Reference to unused volumes.",
655 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
656 $confdesc->{"unused$i"} = $unuseddesc;
659 my $kvm_api_version = 0;
663 return $kvm_api_version if $kvm_api_version;
665 my $fh = IO
::File-
>new("</dev/kvm") ||
668 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
669 $kvm_api_version = $v;
674 return $kvm_api_version;
677 my $kvm_user_version;
679 sub kvm_user_version
{
681 return $kvm_user_version if $kvm_user_version;
683 $kvm_user_version = 'unknown';
685 my $tmp = `kvm -help 2>/dev/null`;
687 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
688 $kvm_user_version = $2;
691 return $kvm_user_version;
695 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
698 # order is important - used to autoselect boot disk
699 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
700 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
701 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
702 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
705 sub valid_drivename
{
708 return defined($drivename_hash->{$dev});
713 return defined($confdesc->{$key});
717 return $nic_model_list;
720 sub os_list_description
{
725 w2k
=> 'Windows 2000',
726 w2k3
=>, 'Windows 2003',
727 w2k8
=> 'Windows 2008',
728 wvista
=> 'Windows Vista',
730 win8
=> 'Windows 8/2012',
740 return $cdrom_path if $cdrom_path;
742 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
743 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
744 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
748 my ($storecfg, $vmid, $cdrom) = @_;
750 if ($cdrom eq 'cdrom') {
751 return get_cdrom_path
();
752 } elsif ($cdrom eq 'none') {
754 } elsif ($cdrom =~ m
|^/|) {
757 return PVE
::Storage
::path
($storecfg, $cdrom);
761 # try to convert old style file names to volume IDs
762 sub filename_to_volume_id
{
763 my ($vmid, $file, $media) = @_;
765 if (!($file eq 'none' || $file eq 'cdrom' ||
766 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
768 return undef if $file =~ m
|/|;
770 if ($media && $media eq 'cdrom') {
771 $file = "local:iso/$file";
773 $file = "local:$vmid/$file";
780 sub verify_media_type
{
781 my ($opt, $vtype, $media) = @_;
786 if ($media eq 'disk') {
788 } elsif ($media eq 'cdrom') {
791 die "internal error";
794 return if ($vtype eq $etype);
796 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
799 sub cleanup_drive_path
{
800 my ($opt, $storecfg, $drive) = @_;
802 # try to convert filesystem paths to volume IDs
804 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
805 ($drive->{file
} !~ m
|^/dev/.+|) &&
806 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
807 ($drive->{file
} !~ m/^\d+$/)) {
808 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
809 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
810 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
811 verify_media_type
($opt, $vtype, $drive->{media
});
812 $drive->{file
} = $volid;
815 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
818 sub create_conf_nolock
{
819 my ($vmid, $settings) = @_;
821 my $filename = config_file
($vmid);
823 die "configuration file '$filename' already exists\n" if -f
$filename;
825 my $defaults = load_defaults
();
827 $settings->{name
} = "vm$vmid" if !$settings->{name
};
828 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
831 foreach my $opt (keys %$settings) {
832 next if !$confdesc->{$opt};
834 my $value = $settings->{$opt};
837 $data .= "$opt: $value\n";
840 PVE
::Tools
::file_set_contents
($filename, $data);
843 my $parse_size = sub {
846 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
847 my ($size, $unit) = ($1, $3);
850 $size = $size * 1024;
851 } elsif ($unit eq 'M') {
852 $size = $size * 1024 * 1024;
853 } elsif ($unit eq 'G') {
854 $size = $size * 1024 * 1024 * 1024;
860 my $format_size = sub {
865 my $kb = int($size/1024);
866 return $size if $kb*1024 != $size;
868 my $mb = int($kb/1024);
869 return "${kb}K" if $mb*1024 != $kb;
871 my $gb = int($mb/1024);
872 return "${mb}M" if $gb*1024 != $mb;
877 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
878 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
879 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
880 # [,aio=native|threads][,discard=ignore|on]
883 my ($key, $data) = @_;
887 # $key may be undefined - used to verify JSON parameters
888 if (!defined($key)) {
889 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
891 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
892 $res->{interface
} = $1;
898 foreach my $p (split (/,/, $data)) {
899 next if $p =~ m/^\s*$/;
901 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
902 my ($k, $v) = ($1, $2);
904 $k = 'file' if $k eq 'volume';
906 return undef if defined $res->{$k};
908 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
909 return undef if !$v || $v !~ m/^\d+/;
911 $v = sprintf("%.3f", $v / (1024*1024));
915 if (!$res->{file
} && $p !~ m/=/) {
923 return undef if !$res->{file
};
925 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
929 return undef if $res->{cache
} &&
930 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
931 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
932 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
933 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
934 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
935 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
936 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
937 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
938 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
939 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
940 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
941 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
942 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
944 return undef if $res->{mbps_rd
} && $res->{mbps
};
945 return undef if $res->{mbps_wr
} && $res->{mbps
};
947 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
949 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
951 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{iops_rd
} && $res->{iops
};
955 return undef if $res->{iops_wr
} && $res->{iops
};
958 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
959 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
960 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
961 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
962 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
963 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
967 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
970 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
971 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
972 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
973 return undef if $res->{interface
} eq 'virtio';
976 # rerror does not work with scsi drives
977 if ($res->{rerror
}) {
978 return undef if $res->{interface
} eq 'scsi';
984 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
987 my ($vmid, $drive) = @_;
990 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
991 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
994 if ($drive->{size
}) {
995 $opts .= ",size=" . &$format_size($drive->{size
});
998 return "$drive->{file}$opts";
1002 my($fh, $noerr) = @_;
1005 my $SG_GET_VERSION_NUM = 0x2282;
1007 my $versionbuf = "\x00" x
8;
1008 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1010 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1013 my $version = unpack("I", $versionbuf);
1014 if ($version < 30000) {
1015 die "scsi generic interface too old\n" if !$noerr;
1019 my $buf = "\x00" x
36;
1020 my $sensebuf = "\x00" x
8;
1021 my $cmd = pack("C x3 C x1", 0x12, 36);
1023 # see /usr/include/scsi/sg.h
1024 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1026 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1027 length($sensebuf), 0, length($buf), $buf,
1028 $cmd, $sensebuf, 6000);
1030 $ret = ioctl($fh, $SG_IO, $packet);
1032 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1036 my @res = unpack($sg_io_hdr_t, $packet);
1037 if ($res[17] || $res[18]) {
1038 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1043 (my $byte0, my $byte1, $res->{vendor
},
1044 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1046 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1047 $res->{type
} = $byte0 & 31;
1055 my $fh = IO
::File-
>new("+<$path") || return undef;
1056 my $res = scsi_inquiry
($fh, 1);
1062 sub 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,downscript=/var/lib/qemu-server/pve-bridgedown$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+)$/) {
1266 } elsif ($kvp =~ m/^firewall=(\d+)$/) {
1267 $res->{firewall
} = $1;
1274 return undef if !$res->{model
};
1282 my $res = "$net->{model}";
1283 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1284 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1285 $res .= ",rate=$net->{rate}" if $net->{rate
};
1286 $res .= ",tag=$net->{tag}" if $net->{tag
};
1291 sub add_random_macs
{
1292 my ($settings) = @_;
1294 foreach my $opt (keys %$settings) {
1295 next if $opt !~ m/^net(\d+)$/;
1296 my $net = parse_net
($settings->{$opt});
1298 $settings->{$opt} = print_net
($net);
1302 sub add_unused_volume
{
1303 my ($config, $volid) = @_;
1306 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1307 my $test = "unused$ind";
1308 if (my $vid = $config->{$test}) {
1309 return if $vid eq $volid; # do not add duplicates
1315 die "To many unused volume - please delete them first.\n" if !$key;
1317 $config->{$key} = $volid;
1322 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1323 sub verify_bootdisk
{
1324 my ($value, $noerr) = @_;
1326 return $value if valid_drivename
($value);
1328 return undef if $noerr;
1330 die "invalid boot disk '$value'\n";
1333 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1335 my ($value, $noerr) = @_;
1337 return $value if parse_net
($value);
1339 return undef if $noerr;
1341 die "unable to parse network options\n";
1344 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1346 my ($value, $noerr) = @_;
1348 return $value if parse_drive
(undef, $value);
1350 return undef if $noerr;
1352 die "unable to parse drive options\n";
1355 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1356 sub verify_hostpci
{
1357 my ($value, $noerr) = @_;
1359 return $value if parse_hostpci
($value);
1361 return undef if $noerr;
1363 die "unable to parse pci id\n";
1366 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1367 sub verify_watchdog
{
1368 my ($value, $noerr) = @_;
1370 return $value if parse_watchdog
($value);
1372 return undef if $noerr;
1374 die "unable to parse watchdog options\n";
1377 sub parse_watchdog
{
1380 return undef if !$value;
1384 foreach my $p (split(/,/, $value)) {
1385 next if $p =~ m/^\s*$/;
1387 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1389 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1390 $res->{action
} = $2;
1399 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1400 sub verify_startup
{
1401 my ($value, $noerr) = @_;
1403 return $value if parse_startup
($value);
1405 return undef if $noerr;
1407 die "unable to parse startup options\n";
1413 return undef if !$value;
1417 foreach my $p (split(/,/, $value)) {
1418 next if $p =~ m/^\s*$/;
1420 if ($p =~ m/^(order=)?(\d+)$/) {
1422 } elsif ($p =~ m/^up=(\d+)$/) {
1424 } elsif ($p =~ m/^down=(\d+)$/) {
1434 sub parse_usb_device
{
1437 return undef if !$value;
1439 my @dl = split(/,/, $value);
1443 foreach my $v (@dl) {
1444 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1446 $res->{vendorid
} = $2;
1447 $res->{productid
} = $4;
1448 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1450 $res->{hostbus
} = $1;
1451 $res->{hostport
} = $2;
1452 } elsif ($v =~ m/^spice$/) {
1459 return undef if !$found;
1464 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1465 sub verify_usb_device
{
1466 my ($value, $noerr) = @_;
1468 return $value if parse_usb_device
($value);
1470 return undef if $noerr;
1472 die "unable to parse usb device\n";
1475 # add JSON properties for create and set function
1476 sub json_config_properties
{
1479 foreach my $opt (keys %$confdesc) {
1480 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1481 $prop->{$opt} = $confdesc->{$opt};
1488 my ($key, $value) = @_;
1490 die "unknown setting '$key'\n" if !$confdesc->{$key};
1492 my $type = $confdesc->{$key}->{type
};
1494 if (!defined($value)) {
1495 die "got undefined value\n";
1498 if ($value =~ m/[\n\r]/) {
1499 die "property contains a line feed\n";
1502 if ($type eq 'boolean') {
1503 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1504 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1505 die "type check ('boolean') failed - got '$value'\n";
1506 } elsif ($type eq 'integer') {
1507 return int($1) if $value =~ m/^(\d+)$/;
1508 die "type check ('integer') failed - got '$value'\n";
1509 } elsif ($type eq 'number') {
1510 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1511 die "type check ('number') failed - got '$value'\n";
1512 } elsif ($type eq 'string') {
1513 if (my $fmt = $confdesc->{$key}->{format
}) {
1514 if ($fmt eq 'pve-qm-drive') {
1515 # special case - we need to pass $key to parse_drive()
1516 my $drive = parse_drive
($key, $value);
1517 return $value if $drive;
1518 die "unable to parse drive options\n";
1520 PVE
::JSONSchema
::check_format
($fmt, $value);
1523 $value =~ s/^\"(.*)\"$/$1/;
1526 die "internal error"
1530 sub lock_config_full
{
1531 my ($vmid, $timeout, $code, @param) = @_;
1533 my $filename = config_file_lock
($vmid);
1535 my $res = lock_file
($filename, $timeout, $code, @param);
1542 sub lock_config_mode
{
1543 my ($vmid, $timeout, $shared, $code, @param) = @_;
1545 my $filename = config_file_lock
($vmid);
1547 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1555 my ($vmid, $code, @param) = @_;
1557 return lock_config_full
($vmid, 10, $code, @param);
1560 sub cfs_config_path
{
1561 my ($vmid, $node) = @_;
1563 $node = $nodename if !$node;
1564 return "nodes/$node/qemu-server/$vmid.conf";
1567 sub check_iommu_support
{
1568 #fixme : need to check IOMMU support
1569 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1577 my ($vmid, $node) = @_;
1579 my $cfspath = cfs_config_path
($vmid, $node);
1580 return "/etc/pve/$cfspath";
1583 sub config_file_lock
{
1586 return "$lock_dir/lock-$vmid.conf";
1592 my $conf = config_file
($vmid);
1593 utime undef, undef, $conf;
1597 my ($storecfg, $vmid, $keep_empty_config) = @_;
1599 my $conffile = config_file
($vmid);
1601 my $conf = load_config
($vmid);
1605 # only remove disks owned by this VM
1606 foreach_drive
($conf, sub {
1607 my ($ds, $drive) = @_;
1609 return if drive_is_cdrom
($drive);
1611 my $volid = $drive->{file
};
1613 return if !$volid || $volid =~ m
|^/|;
1615 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1616 return if !$path || !$owner || ($owner != $vmid);
1618 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1621 if ($keep_empty_config) {
1622 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1627 # also remove unused disk
1629 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1632 PVE
::Storage
::foreach_volid
($dl, sub {
1633 my ($volid, $sid, $volname, $d) = @_;
1634 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1644 my ($vmid, $node) = @_;
1646 my $cfspath = cfs_config_path
($vmid, $node);
1648 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1650 die "no such VM ('$vmid')\n" if !defined($conf);
1655 sub parse_vm_config
{
1656 my ($filename, $raw) = @_;
1658 return undef if !defined($raw);
1661 digest
=> Digest
::SHA
::sha1_hex
($raw),
1665 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1666 || die "got strange filename '$filename'";
1673 my @lines = split(/\n/, $raw);
1674 foreach my $line (@lines) {
1675 next if $line =~ m/^\s*$/;
1677 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1679 $conf->{description
} = $descr if $descr;
1681 $conf = $res->{snapshots
}->{$snapname} = {};
1685 if ($line =~ m/^\#(.*)\s*$/) {
1686 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1690 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1691 $descr .= PVE
::Tools
::decode_text
($2);
1692 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1693 $conf->{snapstate
} = $1;
1694 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1697 $conf->{$key} = $value;
1698 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1701 eval { $value = check_type
($key, $value); };
1703 warn "vm $vmid - unable to parse value of '$key' - $@";
1705 my $fmt = $confdesc->{$key}->{format
};
1706 if ($fmt && $fmt eq 'pve-qm-drive') {
1707 my $v = parse_drive
($key, $value);
1708 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1709 $v->{file
} = $volid;
1710 $value = print_drive
($vmid, $v);
1712 warn "vm $vmid - unable to parse value of '$key'\n";
1717 if ($key eq 'cdrom') {
1718 $conf->{ide2
} = $value;
1720 $conf->{$key} = $value;
1726 $conf->{description
} = $descr if $descr;
1728 delete $res->{snapstate
}; # just to be sure
1733 sub write_vm_config
{
1734 my ($filename, $conf) = @_;
1736 delete $conf->{snapstate
}; # just to be sure
1738 if ($conf->{cdrom
}) {
1739 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1740 $conf->{ide2
} = $conf->{cdrom
};
1741 delete $conf->{cdrom
};
1744 # we do not use 'smp' any longer
1745 if ($conf->{sockets
}) {
1746 delete $conf->{smp
};
1747 } elsif ($conf->{smp
}) {
1748 $conf->{sockets
} = $conf->{smp
};
1749 delete $conf->{cores
};
1750 delete $conf->{smp
};
1753 if ($conf->{maxcpus
} && $conf->{sockets
}) {
1754 delete $conf->{sockets
};
1757 my $used_volids = {};
1759 my $cleanup_config = sub {
1760 my ($cref, $snapname) = @_;
1762 foreach my $key (keys %$cref) {
1763 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1764 $key eq 'snapstate';
1765 my $value = $cref->{$key};
1766 eval { $value = check_type
($key, $value); };
1767 die "unable to parse value of '$key' - $@" if $@;
1769 $cref->{$key} = $value;
1771 if (!$snapname && valid_drivename
($key)) {
1772 my $drive = parse_drive
($key, $value);
1773 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1778 &$cleanup_config($conf);
1779 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1780 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1783 # remove 'unusedX' settings if we re-add a volume
1784 foreach my $key (keys %$conf) {
1785 my $value = $conf->{$key};
1786 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1787 delete $conf->{$key};
1791 my $generate_raw_config = sub {
1796 # add description as comment to top of file
1797 my $descr = $conf->{description
} || '';
1798 foreach my $cl (split(/\n/, $descr)) {
1799 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1802 foreach my $key (sort keys %$conf) {
1803 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1804 $raw .= "$key: $conf->{$key}\n";
1809 my $raw = &$generate_raw_config($conf);
1810 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1811 $raw .= "\n[$snapname]\n";
1812 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1818 sub update_config_nolock
{
1819 my ($vmid, $conf, $skiplock) = @_;
1821 check_lock
($conf) if !$skiplock;
1823 my $cfspath = cfs_config_path
($vmid);
1825 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1829 my ($vmid, $conf, $skiplock) = @_;
1831 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1838 # we use static defaults from our JSON schema configuration
1839 foreach my $key (keys %$confdesc) {
1840 if (defined(my $default = $confdesc->{$key}->{default})) {
1841 $res->{$key} = $default;
1845 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1846 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1852 my $vmlist = PVE
::Cluster
::get_vmlist
();
1854 return $res if !$vmlist || !$vmlist->{ids
};
1855 my $ids = $vmlist->{ids
};
1857 foreach my $vmid (keys %$ids) {
1858 my $d = $ids->{$vmid};
1859 next if !$d->{node
} || $d->{node
} ne $nodename;
1860 next if !$d->{type
} || $d->{type
} ne 'qemu';
1861 $res->{$vmid}->{exists} = 1;
1866 # test if VM uses local resources (to prevent migration)
1867 sub check_local_resources
{
1868 my ($conf, $noerr) = @_;
1872 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1873 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1875 foreach my $k (keys %$conf) {
1876 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1877 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1880 die "VM uses local resources\n" if $loc_res && !$noerr;
1885 # check if used storages are available on all nodes (use by migrate)
1886 sub check_storage_availability
{
1887 my ($storecfg, $conf, $node) = @_;
1889 foreach_drive
($conf, sub {
1890 my ($ds, $drive) = @_;
1892 my $volid = $drive->{file
};
1895 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1898 # check if storage is available on both nodes
1899 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1900 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1904 # list nodes where all VM images are available (used by has_feature API)
1906 my ($conf, $storecfg) = @_;
1908 my $nodelist = PVE
::Cluster
::get_nodelist
();
1909 my $nodehash = { map { $_ => 1 } @$nodelist };
1910 my $nodename = PVE
::INotify
::nodename
();
1912 foreach_drive
($conf, sub {
1913 my ($ds, $drive) = @_;
1915 my $volid = $drive->{file
};
1918 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1920 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1921 if ($scfg->{disable
}) {
1923 } elsif (my $avail = $scfg->{nodes
}) {
1924 foreach my $node (keys %$nodehash) {
1925 delete $nodehash->{$node} if !$avail->{$node};
1927 } elsif (!$scfg->{shared
}) {
1928 foreach my $node (keys %$nodehash) {
1929 delete $nodehash->{$node} if $node ne $nodename
1941 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1945 my ($pidfile, $pid) = @_;
1947 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1951 return undef if !$line;
1952 my @param = split(/\0/, $line);
1954 my $cmd = $param[0];
1955 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1957 for (my $i = 0; $i < scalar (@param); $i++) {
1960 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1961 my $p = $param[$i+1];
1962 return 1 if $p && ($p eq $pidfile);
1971 my ($vmid, $nocheck, $node) = @_;
1973 my $filename = config_file
($vmid, $node);
1975 die "unable to find configuration file for VM $vmid - no such machine\n"
1976 if !$nocheck && ! -f
$filename;
1978 my $pidfile = pidfile_name
($vmid);
1980 if (my $fd = IO
::File-
>new("<$pidfile")) {
1985 my $mtime = $st->mtime;
1986 if ($mtime > time()) {
1987 warn "file '$filename' modified in future\n";
1990 if ($line =~ m/^(\d+)$/) {
1992 if (check_cmdline
($pidfile, $pid)) {
1993 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2005 my $vzlist = config_list
();
2007 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2009 while (defined(my $de = $fd->read)) {
2010 next if $de !~ m/^(\d+)\.pid$/;
2012 next if !defined($vzlist->{$vmid});
2013 if (my $pid = check_running
($vmid)) {
2014 $vzlist->{$vmid}->{pid
} = $pid;
2022 my ($storecfg, $conf) = @_;
2024 my $bootdisk = $conf->{bootdisk
};
2025 return undef if !$bootdisk;
2026 return undef if !valid_drivename
($bootdisk);
2028 return undef if !$conf->{$bootdisk};
2030 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2031 return undef if !defined($drive);
2033 return undef if drive_is_cdrom
($drive);
2035 my $volid = $drive->{file
};
2036 return undef if !$volid;
2038 return $drive->{size
};
2041 my $last_proc_pid_stat;
2043 # get VM status information
2044 # This must be fast and should not block ($full == false)
2045 # We only query KVM using QMP if $full == true (this can be slow)
2047 my ($opt_vmid, $full) = @_;
2051 my $storecfg = PVE
::Storage
::config
();
2053 my $list = vzlist
();
2054 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2056 my $cpucount = $cpuinfo->{cpus
} || 1;
2058 foreach my $vmid (keys %$list) {
2059 next if $opt_vmid && ($vmid ne $opt_vmid);
2061 my $cfspath = cfs_config_path
($vmid);
2062 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2065 $d->{pid
} = $list->{$vmid}->{pid
};
2067 # fixme: better status?
2068 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2070 my $size = disksize
($storecfg, $conf);
2071 if (defined($size)) {
2072 $d->{disk
} = 0; # no info available
2073 $d->{maxdisk
} = $size;
2079 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2080 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2082 $d->{name
} = $conf->{name
} || "VM $vmid";
2083 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2085 if ($conf->{balloon
}) {
2086 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2087 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2098 $d->{diskwrite
} = 0;
2100 $d->{template
} = is_template
($conf);
2105 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2106 foreach my $dev (keys %$netdev) {
2107 next if $dev !~ m/^tap([1-9]\d*)i/;
2109 my $d = $res->{$vmid};
2112 $d->{netout
} += $netdev->{$dev}->{receive
};
2113 $d->{netin
} += $netdev->{$dev}->{transmit
};
2116 my $ctime = gettimeofday
;
2118 foreach my $vmid (keys %$list) {
2120 my $d = $res->{$vmid};
2121 my $pid = $d->{pid
};
2124 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2125 next if !$pstat; # not running
2127 my $used = $pstat->{utime} + $pstat->{stime
};
2129 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2131 if ($pstat->{vsize
}) {
2132 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2135 my $old = $last_proc_pid_stat->{$pid};
2137 $last_proc_pid_stat->{$pid} = {
2145 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2147 if ($dtime > 1000) {
2148 my $dutime = $used - $old->{used
};
2150 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2151 $last_proc_pid_stat->{$pid} = {
2157 $d->{cpu
} = $old->{cpu
};
2161 return $res if !$full;
2163 my $qmpclient = PVE
::QMPClient-
>new();
2165 my $ballooncb = sub {
2166 my ($vmid, $resp) = @_;
2168 my $info = $resp->{'return'};
2169 return if !$info->{max_mem
};
2171 my $d = $res->{$vmid};
2173 # use memory assigned to VM
2174 $d->{maxmem
} = $info->{max_mem
};
2175 $d->{balloon
} = $info->{actual
};
2177 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2178 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2179 $d->{freemem
} = $info->{free_mem
};
2184 my $blockstatscb = sub {
2185 my ($vmid, $resp) = @_;
2186 my $data = $resp->{'return'} || [];
2187 my $totalrdbytes = 0;
2188 my $totalwrbytes = 0;
2189 for my $blockstat (@$data) {
2190 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2191 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2193 $res->{$vmid}->{diskread
} = $totalrdbytes;
2194 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2197 my $statuscb = sub {
2198 my ($vmid, $resp) = @_;
2200 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2201 # this fails if ballon driver is not loaded, so this must be
2202 # the last commnand (following command are aborted if this fails).
2203 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2205 my $status = 'unknown';
2206 if (!defined($status = $resp->{'return'}->{status
})) {
2207 warn "unable to get VM status\n";
2211 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2214 foreach my $vmid (keys %$list) {
2215 next if $opt_vmid && ($vmid ne $opt_vmid);
2216 next if !$res->{$vmid}->{pid
}; # not running
2217 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2220 $qmpclient->queue_execute();
2222 foreach my $vmid (keys %$list) {
2223 next if $opt_vmid && ($vmid ne $opt_vmid);
2224 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2231 my ($conf, $func) = @_;
2233 foreach my $ds (keys %$conf) {
2234 next if !valid_drivename
($ds);
2236 my $drive = parse_drive
($ds, $conf->{$ds});
2239 &$func($ds, $drive);
2244 my ($conf, $func) = @_;
2248 my $test_volid = sub {
2249 my ($volid, $is_cdrom) = @_;
2253 $volhash->{$volid} = $is_cdrom || 0;
2256 foreach_drive
($conf, sub {
2257 my ($ds, $drive) = @_;
2258 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2261 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2262 my $snap = $conf->{snapshots
}->{$snapname};
2263 &$test_volid($snap->{vmstate
}, 0);
2264 foreach_drive
($snap, sub {
2265 my ($ds, $drive) = @_;
2266 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2270 foreach my $volid (keys %$volhash) {
2271 &$func($volid, $volhash->{$volid});
2275 sub vga_conf_has_spice
{
2278 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2283 sub config_to_command
{
2284 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2287 my $globalFlags = [];
2288 my $machineFlags = [];
2294 my $kvmver = kvm_user_version
();
2295 my $vernum = 0; # unknown
2296 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2297 $vernum = $1*1000000+$2*1000;
2298 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2299 $vernum = $1*1000000+$2*1000+$3;
2302 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2304 my $have_ovz = -f
'/proc/vz/vestat';
2306 push @$cmd, '/usr/bin/kvm';
2308 push @$cmd, '-id', $vmid;
2312 my $qmpsocket = qmp_socket
($vmid);
2313 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2314 push @$cmd, '-mon', "chardev=qmp,mode=control";
2316 my $socket = vnc_socket
($vmid);
2317 push @$cmd, '-vnc', "unix:$socket,x509,password";
2319 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2321 push @$cmd, '-daemonize';
2323 $pciaddr = print_pci_addr
("piix3", $bridges);
2324 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2327 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2328 next if !$conf->{"usb$i"};
2331 # include usb device config
2332 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2334 my $vga = $conf->{vga
};
2336 my $qxlnum = vga_conf_has_spice
($vga);
2337 $vga = 'qxl' if $qxlnum;
2340 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2341 $conf->{ostype
} eq 'win7' ||
2342 $conf->{ostype
} eq 'w2k8')) {
2349 # enable absolute mouse coordinates (needed by vnc)
2351 if (defined($conf->{tablet
})) {
2352 $tablet = $conf->{tablet
};
2354 $tablet = $defaults->{tablet
};
2355 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2356 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2359 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2362 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2363 my $d = parse_hostpci
($conf->{"hostpci$i"});
2365 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2366 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2367 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar";
2371 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2372 my $d = parse_usb_device
($conf->{"usb$i"});
2374 if ($d->{vendorid
} && $d->{productid
}) {
2375 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2376 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2377 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2378 } elsif ($d->{spice
}) {
2379 # usb redir support for spice
2380 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2381 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2386 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2387 if (my $path = $conf->{"serial$i"}) {
2388 if ($path eq 'socket') {
2389 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2390 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2391 push @$devices, '-device', "isa-serial,chardev=serial$i";
2393 die "no such serial device\n" if ! -c
$path;
2394 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2395 push @$devices, '-device', "isa-serial,chardev=serial$i";
2401 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2402 if (my $path = $conf->{"parallel$i"}) {
2403 die "no such parallel device\n" if ! -c
$path;
2404 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2405 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2406 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2410 my $vmname = $conf->{name
} || "vm$vmid";
2412 push @$cmd, '-name', $vmname;
2415 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2416 $sockets = $conf->{sockets
} if $conf->{sockets
};
2418 my $cores = $conf->{cores
} || 1;
2419 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2422 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2424 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2427 push @$cmd, '-nodefaults';
2429 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2431 my $bootindex_hash = {};
2433 foreach my $o (split(//, $bootorder)) {
2434 $bootindex_hash->{$o} = $i*100;
2438 push @$cmd, '-boot', "menu=on";
2440 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2442 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2444 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2447 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2449 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2450 my $useLocaltime = $conf->{localtime};
2452 if (my $ost = $conf->{ostype
}) {
2453 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2455 if ($ost =~ m/^w/) { # windows
2456 $useLocaltime = 1 if !defined($conf->{localtime});
2458 # use time drift fix when acpi is enabled
2459 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2460 $tdf = 1 if !defined($conf->{tdf
});
2464 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2466 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2467 push @$cmd, '-no-hpet';
2468 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2469 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2472 if ($ost eq 'win7' || $ost eq 'win8') {
2473 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2477 push @$rtcFlags, 'driftfix=slew' if $tdf;
2480 push @$machineFlags, 'accel=tcg';
2482 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2485 my $machine_type = $forcemachine || $conf->{machine
};
2486 if ($machine_type) {
2487 push @$machineFlags, "type=${machine_type}";
2490 if ($conf->{startdate
}) {
2491 push @$rtcFlags, "base=$conf->{startdate}";
2492 } elsif ($useLocaltime) {
2493 push @$rtcFlags, 'base=localtime';
2496 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2497 $cpu = $conf->{cpu
} if $conf->{cpu
};
2499 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2501 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2503 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2505 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2507 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2509 # Note: enforce needs kernel 3.10, so we do not use it for now
2510 # push @$cmd, '-cpu', "$cpu,enforce";
2511 push @$cmd, '-cpu', $cpu;
2513 push @$cmd, '-S' if $conf->{freeze
};
2515 # set keyboard layout
2516 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2517 push @$cmd, '-k', $kb if $kb;
2520 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2521 #push @$cmd, '-soundhw', 'es1370';
2522 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2524 if($conf->{agent
}) {
2525 my $qgasocket = qga_socket
($vmid);
2526 my $pciaddr = print_pci_addr
("qga0", $bridges);
2527 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2528 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2529 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2536 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2537 for(my $i = 1; $i < $qxlnum; $i++){
2538 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2539 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2542 # assume other OS works like Linux
2543 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2544 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2548 my $pciaddr = print_pci_addr
("spice", $bridges);
2550 $spice_port = PVE
::Tools
::next_spice_port
();
2552 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2554 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2555 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2556 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2559 # enable balloon by default, unless explicitly disabled
2560 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2561 $pciaddr = print_pci_addr
("balloon0", $bridges);
2562 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2565 if ($conf->{watchdog
}) {
2566 my $wdopts = parse_watchdog
($conf->{watchdog
});
2567 $pciaddr = print_pci_addr
("watchdog", $bridges);
2568 my $watchdog = $wdopts->{model
} || 'i6300esb';
2569 push @$devices, '-device', "$watchdog$pciaddr";
2570 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2574 my $scsicontroller = {};
2575 my $ahcicontroller = {};
2576 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2578 foreach_drive
($conf, sub {
2579 my ($ds, $drive) = @_;
2581 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2582 push @$vollist, $drive->{file
};
2585 $use_virtio = 1 if $ds =~ m/^virtio/;
2587 if (drive_is_cdrom
($drive)) {
2588 if ($bootindex_hash->{d
}) {
2589 $drive->{bootindex
} = $bootindex_hash->{d
};
2590 $bootindex_hash->{d
} += 1;
2593 if ($bootindex_hash->{c
}) {
2594 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2595 $bootindex_hash->{c
} += 1;
2599 if ($drive->{interface
} eq 'scsi') {
2601 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2602 my $controller = int($drive->{index} / $maxdev);
2603 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2604 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2605 $scsicontroller->{$controller}=1;
2608 if ($drive->{interface
} eq 'sata') {
2609 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2610 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2611 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2612 $ahcicontroller->{$controller}=1;
2615 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2616 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2619 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2621 for (my $i = 0; $i < $MAX_NETS; $i++) {
2622 next if !$conf->{"net$i"};
2623 my $d = parse_net
($conf->{"net$i"});
2626 $use_virtio = 1 if $d->{model
} eq 'virtio';
2628 if ($bootindex_hash->{n
}) {
2629 $d->{bootindex
} = $bootindex_hash->{n
};
2630 $bootindex_hash->{n
} += 1;
2633 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2634 push @$devices, '-netdev', $netdevfull;
2636 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2637 push @$devices, '-device', $netdevicefull;
2641 while (my ($k, $v) = each %$bridges) {
2642 $pciaddr = print_pci_addr
("pci.$k");
2643 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2647 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2648 # when the VM uses virtio devices.
2649 if (!$use_virtio && $have_ovz) {
2651 my $cpuunits = defined($conf->{cpuunits
}) ?
2652 $conf->{cpuunits
} : $defaults->{cpuunits
};
2654 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2656 # fixme: cpulimit is currently ignored
2657 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2661 if ($conf->{args
}) {
2662 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2666 push @$cmd, @$devices;
2667 push @$cmd, '-rtc', join(',', @$rtcFlags)
2668 if scalar(@$rtcFlags);
2669 push @$cmd, '-machine', join(',', @$machineFlags)
2670 if scalar(@$machineFlags);
2671 push @$cmd, '-global', join(',', @$globalFlags)
2672 if scalar(@$globalFlags);
2674 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2679 return "${var_run_tmpdir}/$vmid.vnc";
2685 my $res = vm_mon_cmd
($vmid, 'query-spice');
2687 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2692 return "${var_run_tmpdir}/$vmid.qmp";
2697 return "${var_run_tmpdir}/$vmid.qga";
2702 return "${var_run_tmpdir}/$vmid.pid";
2705 sub vm_devices_list
{
2708 my $res = vm_mon_cmd
($vmid, 'query-pci');
2711 foreach my $pcibus (@$res) {
2712 foreach my $device (@{$pcibus->{devices
}}) {
2713 next if !$device->{'qdev_id'};
2714 $devices->{$device->{'qdev_id'}} = $device;
2722 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2724 return 1 if !check_running
($vmid);
2726 if ($deviceid eq 'tablet') {
2727 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2728 qemu_deviceadd
($vmid, $devicefull);
2732 return 1 if !$conf->{hotplug
};
2734 my $devices_list = vm_devices_list
($vmid);
2735 return 1 if defined($devices_list->{$deviceid});
2737 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2739 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2740 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2741 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2742 qemu_deviceadd
($vmid, $devicefull);
2743 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2744 qemu_drivedel
($vmid, $deviceid);
2749 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2750 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2751 my $pciaddr = print_pci_addr
($deviceid);
2752 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2753 qemu_deviceadd
($vmid, $devicefull);
2754 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2757 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2758 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2759 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2760 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2761 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2762 if(!qemu_deviceadd
($vmid, $devicefull)) {
2763 qemu_drivedel
($vmid, $deviceid);
2768 if ($deviceid =~ m/^(net)(\d+)$/) {
2769 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2770 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2771 qemu_deviceadd
($vmid, $netdevicefull);
2772 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2773 qemu_netdevdel
($vmid, $deviceid);
2778 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2780 my $pciaddr = print_pci_addr
($deviceid);
2781 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2782 qemu_deviceadd
($vmid, $devicefull);
2783 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2789 sub vm_deviceunplug
{
2790 my ($vmid, $conf, $deviceid) = @_;
2792 return 1 if !check_running
($vmid);
2794 if ($deviceid eq 'tablet') {
2795 qemu_devicedel
($vmid, $deviceid);
2799 return 1 if !$conf->{hotplug
};
2801 my $devices_list = vm_devices_list
($vmid);
2802 return 1 if !defined($devices_list->{$deviceid});
2804 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2806 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2807 qemu_devicedel
($vmid, $deviceid);
2808 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2809 return undef if !qemu_drivedel
($vmid, $deviceid);
2812 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2813 return undef if !qemu_devicedel
($vmid, $deviceid);
2816 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2817 return undef if !qemu_devicedel
($vmid, $deviceid);
2818 return undef if !qemu_drivedel
($vmid, $deviceid);
2821 if ($deviceid =~ m/^(net)(\d+)$/) {
2822 qemu_devicedel
($vmid, $deviceid);
2823 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2824 return undef if !qemu_netdevdel
($vmid, $deviceid);
2830 sub qemu_deviceadd
{
2831 my ($vmid, $devicefull) = @_;
2833 $devicefull = "driver=".$devicefull;
2834 my %options = split(/[=,]/, $devicefull);
2836 vm_mon_cmd
($vmid, "device_add" , %options);
2840 sub qemu_devicedel
{
2841 my($vmid, $deviceid) = @_;
2842 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2847 my($storecfg, $vmid, $device) = @_;
2849 my $drive = print_drive_full
($storecfg, $vmid, $device);
2850 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2851 # If the command succeeds qemu prints: "OK"
2852 if ($ret !~ m/OK/s) {
2853 syslog
("err", "adding drive failed: $ret");
2860 my($vmid, $deviceid) = @_;
2862 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2864 if ($ret =~ m/Device \'.*?\' not found/s) {
2865 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2867 elsif ($ret ne "") {
2868 syslog
("err", "deleting drive $deviceid failed : $ret");
2874 sub qemu_deviceaddverify
{
2875 my ($vmid,$deviceid) = @_;
2877 for (my $i = 0; $i <= 5; $i++) {
2878 my $devices_list = vm_devices_list
($vmid);
2879 return 1 if defined($devices_list->{$deviceid});
2882 syslog
("err", "error on hotplug device $deviceid");
2887 sub qemu_devicedelverify
{
2888 my ($vmid,$deviceid) = @_;
2890 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2891 for (my $i = 0; $i <= 5; $i++) {
2892 my $devices_list = vm_devices_list
($vmid);
2893 return 1 if !defined($devices_list->{$deviceid});
2896 syslog
("err", "error on hot-unplugging device $deviceid");
2900 sub qemu_findorcreatescsihw
{
2901 my ($storecfg, $conf, $vmid, $device) = @_;
2903 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2904 my $controller = int($device->{index} / $maxdev);
2905 my $scsihwid="scsihw$controller";
2906 my $devices_list = vm_devices_list
($vmid);
2908 if(!defined($devices_list->{$scsihwid})) {
2909 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2914 sub qemu_bridgeadd
{
2915 my ($storecfg, $conf, $vmid, $device) = @_;
2918 my $bridgeid = undef;
2919 print_pci_addr
($device, $bridges);
2921 while (my ($k, $v) = each %$bridges) {
2924 return if !$bridgeid || $bridgeid < 1;
2925 my $bridge = "pci.$bridgeid";
2926 my $devices_list = vm_devices_list
($vmid);
2928 if(!defined($devices_list->{$bridge})) {
2929 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2934 sub qemu_netdevadd
{
2935 my ($vmid, $conf, $device, $deviceid) = @_;
2937 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2938 my %options = split(/[=,]/, $netdev);
2940 vm_mon_cmd
($vmid, "netdev_add", %options);
2944 sub qemu_netdevdel
{
2945 my ($vmid, $deviceid) = @_;
2947 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2951 sub qemu_cpu_hotplug
{
2952 my ($vmid, $conf, $cores) = @_;
2954 die "new cores config is not defined" if !$cores;
2955 die "you can't add more cores than maxcpus"
2956 if $conf->{maxcpus
} && ($cores > $conf->{maxcpus
});
2957 return if !check_running
($vmid);
2959 my $currentcores = $conf->{cores
} if $conf->{cores
};
2960 die "current cores is not defined" if !$currentcores;
2961 die "maxcpus is not defined" if !$conf->{maxcpus
};
2962 raise_param_exc
({ 'cores' => "online cpu unplug is not yet possible" })
2963 if($cores < $currentcores);
2965 my $currentrunningcores = vm_mon_cmd
($vmid, "query-cpus");
2966 raise_param_exc
({ 'cores' => "cores number if running vm is different than configuration" })
2967 if scalar (@{$currentrunningcores}) != $currentcores;
2969 for(my $i = $currentcores; $i < $cores; $i++) {
2970 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
2974 sub qemu_block_set_io_throttle
{
2975 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2977 return if !check_running
($vmid) ;
2979 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));
2983 # old code, only used to shutdown old VM after update
2985 my ($fh, $timeout) = @_;
2987 my $sel = new IO
::Select
;
2994 while (scalar (@ready = $sel->can_read($timeout))) {
2996 if ($count = $fh->sysread($buf, 8192)) {
2997 if ($buf =~ /^(.*)\(qemu\) $/s) {
3004 if (!defined($count)) {
3011 die "monitor read timeout\n" if !scalar(@ready);
3016 # old code, only used to shutdown old VM after update
3017 sub vm_monitor_command
{
3018 my ($vmid, $cmdstr, $nocheck) = @_;
3023 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3025 my $sname = "${var_run_tmpdir}/$vmid.mon";
3027 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3028 die "unable to connect to VM $vmid socket - $!\n";
3032 # hack: migrate sometime blocks the monitor (when migrate_downtime
3034 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3035 $timeout = 60*60; # 1 hour
3039 my $data = __read_avail
($sock, $timeout);
3041 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3042 die "got unexpected qemu monitor banner\n";
3045 my $sel = new IO
::Select
;
3048 if (!scalar(my @ready = $sel->can_write($timeout))) {
3049 die "monitor write error - timeout";
3052 my $fullcmd = "$cmdstr\r";
3054 # syslog('info', "VM $vmid monitor command: $cmdstr");
3057 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3058 die "monitor write error - $!";
3061 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3065 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3066 $timeout = 60*60; # 1 hour
3067 } elsif ($cmdstr =~ m/^(eject|change)/) {
3068 $timeout = 60; # note: cdrom mount command is slow
3070 if ($res = __read_avail
($sock, $timeout)) {
3072 my @lines = split("\r?\n", $res);
3074 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3076 $res = join("\n", @lines);
3084 syslog
("err", "VM $vmid monitor command failed - $err");
3091 sub qemu_block_resize
{
3092 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3094 my $running = check_running
($vmid);
3096 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3098 return if !$running;
3100 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3104 sub qemu_volume_snapshot
{
3105 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3107 my $running = check_running
($vmid);
3109 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3111 return if !$running;
3113 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3117 sub qemu_volume_snapshot_delete
{
3118 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3120 my $running = check_running
($vmid);
3122 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3124 return if !$running;
3126 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3132 #need to impplement call to qemu-ga
3135 sub qga_unfreezefs
{
3138 #need to impplement call to qemu-ga
3141 sub set_migration_caps
{
3147 "auto-converge" => 1,
3149 "x-rdma-pin-all" => 0,
3153 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3155 for my $supported_capability (@$supported_capabilities) {
3157 capability
=> $supported_capability->{capability
},
3158 state => $enabled_cap->{$supported_capability->{capability
}} ? JSON
::true
: JSON
::false
,
3162 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3166 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3168 lock_config
($vmid, sub {
3169 my $conf = load_config
($vmid, $migratedfrom);
3171 die "you can't start a vm if it's a template\n" if is_template
($conf);
3173 check_lock
($conf) if !$skiplock;
3175 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3177 my $defaults = load_defaults
();
3179 # set environment variable useful inside network script
3180 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3182 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3184 my $migrate_port = 0;
3187 if ($statefile eq 'tcp') {
3188 my $localip = "localhost";
3189 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3190 if ($datacenterconf->{migration_unsecure
}) {
3191 my $nodename = PVE
::INotify
::nodename
();
3192 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3194 $migrate_port = PVE
::Tools
::next_migrate_port
();
3195 $migrate_uri = "tcp:${localip}:${migrate_port}";
3196 push @$cmd, '-incoming', $migrate_uri;
3199 push @$cmd, '-loadstate', $statefile;
3206 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3207 my $d = parse_hostpci
($conf->{"hostpci$i"});
3209 my $info = pci_device_info
("0000:$d->{pciid}");
3210 die "IOMMU not present\n" if !check_iommu_support
();
3211 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3212 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3213 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3216 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3218 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3221 die "start failed: $err" if $err;
3223 print "migration listens on $migrate_uri\n" if $migrate_uri;
3225 if ($statefile && $statefile ne 'tcp') {
3226 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3230 if ($migratedfrom) {
3233 PVE
::QemuServer
::set_migration_caps
($vmid);
3238 print "spice listens on port $spice_port\n";
3239 if ($spice_ticket) {
3240 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3241 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3247 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3248 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3249 if $conf->{balloon
};
3250 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3251 path
=> "machine/peripheral/balloon0",
3252 property
=> "guest-stats-polling-interval",
3260 my ($vmid, $execute, %params) = @_;
3262 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3263 vm_qmp_command
($vmid, $cmd);
3266 sub vm_mon_cmd_nocheck
{
3267 my ($vmid, $execute, %params) = @_;
3269 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3270 vm_qmp_command
($vmid, $cmd, 1);
3273 sub vm_qmp_command
{
3274 my ($vmid, $cmd, $nocheck) = @_;
3279 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3280 $timeout = $cmd->{arguments
}->{timeout
};
3281 delete $cmd->{arguments
}->{timeout
};
3285 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3286 my $sname = qmp_socket
($vmid);
3288 my $qmpclient = PVE
::QMPClient-
>new();
3290 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3291 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3292 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3293 if scalar(%{$cmd->{arguments
}});
3294 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3296 die "unable to open monitor socket\n";
3300 syslog
("err", "VM $vmid qmp command failed - $err");
3307 sub vm_human_monitor_command
{
3308 my ($vmid, $cmdline) = @_;
3313 execute
=> 'human-monitor-command',
3314 arguments
=> { 'command-line' => $cmdline},
3317 return vm_qmp_command
($vmid, $cmd);
3320 sub vm_commandline
{
3321 my ($storecfg, $vmid) = @_;
3323 my $conf = load_config
($vmid);
3325 my $defaults = load_defaults
();
3327 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3329 return join(' ', @$cmd);
3333 my ($vmid, $skiplock) = @_;
3335 lock_config
($vmid, sub {
3337 my $conf = load_config
($vmid);
3339 check_lock
($conf) if !$skiplock;
3341 vm_mon_cmd
($vmid, "system_reset");
3345 sub get_vm_volumes
{
3349 foreach_volid
($conf, sub {
3350 my ($volid, $is_cdrom) = @_;
3352 return if $volid =~ m
|^/|;
3354 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3357 push @$vollist, $volid;
3363 sub vm_stop_cleanup
{
3364 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3367 fairsched_rmnod
($vmid); # try to destroy group
3370 my $vollist = get_vm_volumes
($conf);
3371 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3374 foreach my $ext (qw(mon qmp pid vnc qga)) {
3375 unlink "/var/run/qemu-server/${vmid}.$ext";
3378 warn $@ if $@; # avoid errors - just warn
3381 # Note: use $nockeck to skip tests if VM configuration file exists.
3382 # We need that when migration VMs to other nodes (files already moved)
3383 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3385 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3387 $force = 1 if !defined($force) && !$shutdown;
3390 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3391 kill 15, $pid if $pid;
3392 my $conf = load_config
($vmid, $migratedfrom);
3393 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3397 lock_config
($vmid, sub {
3399 my $pid = check_running
($vmid, $nocheck);
3404 $conf = load_config
($vmid);
3405 check_lock
($conf) if !$skiplock;
3406 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3407 my $opts = parse_startup
($conf->{startup
});
3408 $timeout = $opts->{down
} if $opts->{down
};
3412 $timeout = 60 if !defined($timeout);
3416 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3419 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3426 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3431 if ($count >= $timeout) {
3433 warn "VM still running - terminating now with SIGTERM\n";
3436 die "VM quit/powerdown failed - got timeout\n";
3439 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3444 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3447 die "VM quit/powerdown failed\n";
3455 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3460 if ($count >= $timeout) {
3461 warn "VM still running - terminating now with SIGKILL\n";
3466 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3471 my ($vmid, $skiplock) = @_;
3473 lock_config
($vmid, sub {
3475 my $conf = load_config
($vmid);
3477 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3479 vm_mon_cmd
($vmid, "stop");
3484 my ($vmid, $skiplock) = @_;
3486 lock_config
($vmid, sub {
3488 my $conf = load_config
($vmid);
3490 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3492 vm_mon_cmd
($vmid, "cont");
3497 my ($vmid, $skiplock, $key) = @_;
3499 lock_config
($vmid, sub {
3501 my $conf = load_config
($vmid);
3503 # there is no qmp command, so we use the human monitor command
3504 vm_human_monitor_command
($vmid, "sendkey $key");
3509 my ($storecfg, $vmid, $skiplock) = @_;
3511 lock_config
($vmid, sub {
3513 my $conf = load_config
($vmid);
3515 check_lock
($conf) if !$skiplock;
3517 if (!check_running
($vmid)) {
3518 fairsched_rmnod
($vmid); # try to destroy group
3519 destroy_vm
($storecfg, $vmid);
3521 die "VM $vmid is running - destroy failed\n";
3529 my ($filename, $buf) = @_;
3531 my $fh = IO
::File-
>new($filename, "w");
3532 return undef if !$fh;
3534 my $res = print $fh $buf;
3541 sub pci_device_info
{
3546 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3547 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3549 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3550 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3552 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3553 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3555 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3556 return undef if !defined($product) || $product !~ s/^0x//;
3561 product
=> $product,
3567 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3576 my $name = $dev->{name
};
3578 my $fn = "$pcisysfs/devices/$name/reset";
3580 return file_write
($fn, "1");
3583 sub pci_dev_bind_to_stub
{
3586 my $name = $dev->{name
};
3588 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3589 return 1 if -d
$testdir;
3591 my $data = "$dev->{vendor} $dev->{product}";
3592 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3594 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3595 if (!file_write
($fn, $name)) {
3596 return undef if -f
$fn;
3599 $fn = "$pcisysfs/drivers/pci-stub/bind";
3600 if (! -d
$testdir) {
3601 return undef if !file_write
($fn, $name);
3607 sub print_pci_addr
{
3608 my ($id, $bridges) = @_;
3612 piix3
=> { bus
=> 0, addr
=> 1 },
3613 #addr2 : first videocard
3614 balloon0
=> { bus
=> 0, addr
=> 3 },
3615 watchdog
=> { bus
=> 0, addr
=> 4 },
3616 scsihw0
=> { bus
=> 0, addr
=> 5 },
3617 scsihw1
=> { bus
=> 0, addr
=> 6 },
3618 ahci0
=> { bus
=> 0, addr
=> 7 },
3619 qga0
=> { bus
=> 0, addr
=> 8 },
3620 spice
=> { bus
=> 0, addr
=> 9 },
3621 virtio0
=> { bus
=> 0, addr
=> 10 },
3622 virtio1
=> { bus
=> 0, addr
=> 11 },
3623 virtio2
=> { bus
=> 0, addr
=> 12 },
3624 virtio3
=> { bus
=> 0, addr
=> 13 },
3625 virtio4
=> { bus
=> 0, addr
=> 14 },
3626 virtio5
=> { bus
=> 0, addr
=> 15 },
3627 hostpci0
=> { bus
=> 0, addr
=> 16 },
3628 hostpci1
=> { bus
=> 0, addr
=> 17 },
3629 net0
=> { bus
=> 0, addr
=> 18 },
3630 net1
=> { bus
=> 0, addr
=> 19 },
3631 net2
=> { bus
=> 0, addr
=> 20 },
3632 net3
=> { bus
=> 0, addr
=> 21 },
3633 net4
=> { bus
=> 0, addr
=> 22 },
3634 net5
=> { bus
=> 0, addr
=> 23 },
3635 vga1
=> { bus
=> 0, addr
=> 24 },
3636 vga2
=> { bus
=> 0, addr
=> 25 },
3637 vga3
=> { bus
=> 0, addr
=> 26 },
3638 #addr29 : usb-host (pve-usb.cfg)
3639 'pci.1' => { bus
=> 0, addr
=> 30 },
3640 'pci.2' => { bus
=> 0, addr
=> 31 },
3641 'net6' => { bus
=> 1, addr
=> 1 },
3642 'net7' => { bus
=> 1, addr
=> 2 },
3643 'net8' => { bus
=> 1, addr
=> 3 },
3644 'net9' => { bus
=> 1, addr
=> 4 },
3645 'net10' => { bus
=> 1, addr
=> 5 },
3646 'net11' => { bus
=> 1, addr
=> 6 },
3647 'net12' => { bus
=> 1, addr
=> 7 },
3648 'net13' => { bus
=> 1, addr
=> 8 },
3649 'net14' => { bus
=> 1, addr
=> 9 },
3650 'net15' => { bus
=> 1, addr
=> 10 },
3651 'net16' => { bus
=> 1, addr
=> 11 },
3652 'net17' => { bus
=> 1, addr
=> 12 },
3653 'net18' => { bus
=> 1, addr
=> 13 },
3654 'net19' => { bus
=> 1, addr
=> 14 },
3655 'net20' => { bus
=> 1, addr
=> 15 },
3656 'net21' => { bus
=> 1, addr
=> 16 },
3657 'net22' => { bus
=> 1, addr
=> 17 },
3658 'net23' => { bus
=> 1, addr
=> 18 },
3659 'net24' => { bus
=> 1, addr
=> 19 },
3660 'net25' => { bus
=> 1, addr
=> 20 },
3661 'net26' => { bus
=> 1, addr
=> 21 },
3662 'net27' => { bus
=> 1, addr
=> 22 },
3663 'net28' => { bus
=> 1, addr
=> 23 },
3664 'net29' => { bus
=> 1, addr
=> 24 },
3665 'net30' => { bus
=> 1, addr
=> 25 },
3666 'net31' => { bus
=> 1, addr
=> 26 },
3667 'virtio6' => { bus
=> 2, addr
=> 1 },
3668 'virtio7' => { bus
=> 2, addr
=> 2 },
3669 'virtio8' => { bus
=> 2, addr
=> 3 },
3670 'virtio9' => { bus
=> 2, addr
=> 4 },
3671 'virtio10' => { bus
=> 2, addr
=> 5 },
3672 'virtio11' => { bus
=> 2, addr
=> 6 },
3673 'virtio12' => { bus
=> 2, addr
=> 7 },
3674 'virtio13' => { bus
=> 2, addr
=> 8 },
3675 'virtio14' => { bus
=> 2, addr
=> 9 },
3676 'virtio15' => { bus
=> 2, addr
=> 10 },
3679 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3680 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3681 my $bus = $devices->{$id}->{bus
};
3682 $res = ",bus=pci.$bus,addr=$addr";
3683 $bridges->{$bus} = 1 if $bridges;
3689 # vzdump restore implementaion
3691 sub tar_archive_read_firstfile
{
3692 my $archive = shift;
3694 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3696 # try to detect archive type first
3697 my $pid = open (TMP
, "tar tf '$archive'|") ||
3698 die "unable to open file '$archive'\n";
3699 my $firstfile = <TMP
>;
3703 die "ERROR: archive contaions no data\n" if !$firstfile;
3709 sub tar_restore_cleanup
{
3710 my ($storecfg, $statfile) = @_;
3712 print STDERR
"starting cleanup\n";
3714 if (my $fd = IO
::File-
>new($statfile, "r")) {
3715 while (defined(my $line = <$fd>)) {
3716 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3719 if ($volid =~ m
|^/|) {
3720 unlink $volid || die 'unlink failed\n';
3722 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3724 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3726 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3728 print STDERR
"unable to parse line in statfile - $line";
3735 sub restore_archive
{
3736 my ($archive, $vmid, $user, $opts) = @_;
3738 my $format = $opts->{format
};
3741 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3742 $format = 'tar' if !$format;
3744 } elsif ($archive =~ m/\.tar$/) {
3745 $format = 'tar' if !$format;
3746 } elsif ($archive =~ m/.tar.lzo$/) {
3747 $format = 'tar' if !$format;
3749 } elsif ($archive =~ m/\.vma$/) {
3750 $format = 'vma' if !$format;
3751 } elsif ($archive =~ m/\.vma\.gz$/) {
3752 $format = 'vma' if !$format;
3754 } elsif ($archive =~ m/\.vma\.lzo$/) {
3755 $format = 'vma' if !$format;
3758 $format = 'vma' if !$format; # default
3761 # try to detect archive format
3762 if ($format eq 'tar') {
3763 return restore_tar_archive
($archive, $vmid, $user, $opts);
3765 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3769 sub restore_update_config_line
{
3770 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3772 return if $line =~ m/^\#qmdump\#/;
3773 return if $line =~ m/^\#vzdump\#/;
3774 return if $line =~ m/^lock:/;
3775 return if $line =~ m/^unused\d+:/;
3776 return if $line =~ m/^parent:/;
3777 return if $line =~ m/^template:/; # restored VM is never a template
3779 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3780 # try to convert old 1.X settings
3781 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3782 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3783 my ($model, $macaddr) = split(/\=/, $devconfig);
3784 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3787 bridge
=> "vmbr$ind",
3788 macaddr
=> $macaddr,
3790 my $netstr = print_net
($net);
3792 print $outfd "net$cookie->{netcount}: $netstr\n";
3793 $cookie->{netcount
}++;
3795 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3796 my ($id, $netstr) = ($1, $2);
3797 my $net = parse_net
($netstr);
3798 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3799 $netstr = print_net
($net);
3800 print $outfd "$id: $netstr\n";
3801 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3804 if ($line =~ m/backup=no/) {
3805 print $outfd "#$line";
3806 } elsif ($virtdev && $map->{$virtdev}) {
3807 my $di = parse_drive
($virtdev, $value);
3808 delete $di->{format
}; # format can change on restore
3809 $di->{file
} = $map->{$virtdev};
3810 $value = print_drive
($vmid, $di);
3811 print $outfd "$virtdev: $value\n";
3821 my ($cfg, $vmid) = @_;
3823 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3825 my $volid_hash = {};
3826 foreach my $storeid (keys %$info) {
3827 foreach my $item (@{$info->{$storeid}}) {
3828 next if !($item->{volid
} && $item->{size
});
3829 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3830 $volid_hash->{$item->{volid
}} = $item;
3837 sub get_used_paths
{
3838 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3842 my $scan_config = sub {
3843 my ($cref, $snapname) = @_;
3845 foreach my $key (keys %$cref) {
3846 my $value = $cref->{$key};
3847 if (valid_drivename
($key)) {
3848 next if $skip_drive && $key eq $skip_drive;
3849 my $drive = parse_drive
($key, $value);
3850 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3851 if ($drive->{file
} =~ m!^/!) {
3852 $used_path->{$drive->{file
}}++; # = 1;
3854 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3856 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3858 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3859 $used_path->{$path}++; # = 1;
3865 &$scan_config($conf);
3869 if ($scan_snapshots) {
3870 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3871 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3878 sub update_disksize
{
3879 my ($vmid, $conf, $volid_hash) = @_;
3885 # Note: it is allowed to define multiple storages with same path (alias), so
3886 # we need to check both 'volid' and real 'path' (two different volid can point
3887 # to the same path).
3892 foreach my $opt (keys %$conf) {
3893 if (valid_drivename
($opt)) {
3894 my $drive = parse_drive
($opt, $conf->{$opt});
3895 my $volid = $drive->{file
};
3898 $used->{$volid} = 1;
3899 if ($volid_hash->{$volid} &&
3900 (my $path = $volid_hash->{$volid}->{path
})) {
3901 $usedpath->{$path} = 1;
3904 next if drive_is_cdrom
($drive);
3905 next if !$volid_hash->{$volid};
3907 $drive->{size
} = $volid_hash->{$volid}->{size
};
3908 my $new = print_drive
($vmid, $drive);
3909 if ($new ne $conf->{$opt}) {
3911 $conf->{$opt} = $new;
3916 # remove 'unusedX' entry if volume is used
3917 foreach my $opt (keys %$conf) {
3918 next if $opt !~ m/^unused\d+$/;
3919 my $volid = $conf->{$opt};
3920 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3921 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3923 delete $conf->{$opt};
3927 foreach my $volid (sort keys %$volid_hash) {
3928 next if $volid =~ m/vm-$vmid-state-/;
3929 next if $used->{$volid};
3930 my $path = $volid_hash->{$volid}->{path
};
3931 next if !$path; # just to be sure
3932 next if $usedpath->{$path};
3934 add_unused_volume
($conf, $volid);
3935 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3942 my ($vmid, $nolock) = @_;
3944 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3946 my $volid_hash = scan_volids
($cfg, $vmid);
3948 my $updatefn = sub {
3951 my $conf = load_config
($vmid);
3956 foreach my $volid (keys %$volid_hash) {
3957 my $info = $volid_hash->{$volid};
3958 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3961 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3963 update_config_nolock
($vmid, $conf, 1) if $changes;
3966 if (defined($vmid)) {
3970 lock_config
($vmid, $updatefn, $vmid);
3973 my $vmlist = config_list
();
3974 foreach my $vmid (keys %$vmlist) {
3978 lock_config
($vmid, $updatefn, $vmid);
3984 sub restore_vma_archive
{
3985 my ($archive, $vmid, $user, $opts, $comp) = @_;
3987 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3988 my $readfrom = $archive;
3993 my $qarchive = PVE
::Tools
::shellquote
($archive);
3994 if ($comp eq 'gzip') {
3995 $uncomp = "zcat $qarchive|";
3996 } elsif ($comp eq 'lzop') {
3997 $uncomp = "lzop -d -c $qarchive|";
3999 die "unknown compression method '$comp'\n";
4004 my $tmpdir = "/var/tmp/vzdumptmp$$";
4007 # disable interrupts (always do cleanups)
4008 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4009 warn "got interrupt - ignored\n";
4012 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4013 POSIX
::mkfifo
($mapfifo, 0600);
4016 my $openfifo = sub {
4017 open($fifofh, '>', $mapfifo) || die $!;
4020 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4027 my $rpcenv = PVE
::RPCEnvironment
::get
();
4029 my $conffile = config_file
($vmid);
4030 my $tmpfn = "$conffile.$$.tmp";
4032 # Note: $oldconf is undef if VM does not exists
4033 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4035 my $print_devmap = sub {
4036 my $virtdev_hash = {};
4038 my $cfgfn = "$tmpdir/qemu-server.conf";
4040 # we can read the config - that is already extracted
4041 my $fh = IO
::File-
>new($cfgfn, "r") ||
4042 "unable to read qemu-server.conf - $!\n";
4044 while (defined(my $line = <$fh>)) {
4045 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4046 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4047 die "archive does not contain data for drive '$virtdev'\n"
4048 if !$devinfo->{$devname};
4049 if (defined($opts->{storage
})) {
4050 $storeid = $opts->{storage
} || 'local';
4051 } elsif (!$storeid) {
4054 $format = 'raw' if !$format;
4055 $devinfo->{$devname}->{devname
} = $devname;
4056 $devinfo->{$devname}->{virtdev
} = $virtdev;
4057 $devinfo->{$devname}->{format
} = $format;
4058 $devinfo->{$devname}->{storeid
} = $storeid;
4060 # check permission on storage
4061 my $pool = $opts->{pool
}; # todo: do we need that?
4062 if ($user ne 'root@pam') {
4063 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4066 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4070 foreach my $devname (keys %$devinfo) {
4071 die "found no device mapping information for device '$devname'\n"
4072 if !$devinfo->{$devname}->{virtdev
};
4075 my $cfg = cfs_read_file
('storage.cfg');
4077 # create empty/temp config
4079 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4080 foreach_drive
($oldconf, sub {
4081 my ($ds, $drive) = @_;
4083 return if drive_is_cdrom
($drive);
4085 my $volid = $drive->{file
};
4087 return if !$volid || $volid =~ m
|^/|;
4089 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4090 return if !$path || !$owner || ($owner != $vmid);
4092 # Note: only delete disk we want to restore
4093 # other volumes will become unused
4094 if ($virtdev_hash->{$ds}) {
4095 PVE
::Storage
::vdisk_free
($cfg, $volid);
4101 foreach my $virtdev (sort keys %$virtdev_hash) {
4102 my $d = $virtdev_hash->{$virtdev};
4103 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4104 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4106 # test if requested format is supported
4107 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4108 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4109 $d->{format
} = $defFormat if !$supported;
4111 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4112 $d->{format
}, undef, $alloc_size);
4113 print STDERR
"new volume ID is '$volid'\n";
4114 $d->{volid
} = $volid;
4115 my $path = PVE
::Storage
::path
($cfg, $volid);
4117 my $write_zeros = 1;
4118 # fixme: what other storages types initialize volumes with zero?
4119 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4120 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4124 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4126 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4127 $map->{$virtdev} = $volid;
4130 $fh->seek(0, 0) || die "seek failed - $!\n";
4132 my $outfd = new IO
::File
($tmpfn, "w") ||
4133 die "unable to write config for VM $vmid\n";
4135 my $cookie = { netcount
=> 0 };
4136 while (defined(my $line = <$fh>)) {
4137 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4146 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4147 die "interrupted by signal\n";
4149 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4151 $oldtimeout = alarm($timeout);
4158 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4159 my ($dev_id, $size, $devname) = ($1, $2, $3);
4160 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4161 } elsif ($line =~ m/^CTIME: /) {
4162 # we correctly received the vma config, so we can disable
4163 # the timeout now for disk allocation (set to 10 minutes, so
4164 # that we always timeout if something goes wrong)
4167 print $fifofh "done\n";
4168 my $tmp = $oldtimeout || 0;
4169 $oldtimeout = undef;
4175 print "restore vma archive: $cmd\n";
4176 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4180 alarm($oldtimeout) if $oldtimeout;
4188 my $cfg = cfs_read_file
('storage.cfg');
4189 foreach my $devname (keys %$devinfo) {
4190 my $volid = $devinfo->{$devname}->{volid
};
4193 if ($volid =~ m
|^/|) {
4194 unlink $volid || die 'unlink failed\n';
4196 PVE
::Storage
::vdisk_free
($cfg, $volid);
4198 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4200 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4207 rename($tmpfn, $conffile) ||
4208 die "unable to commit configuration file '$conffile'\n";
4210 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4212 eval { rescan
($vmid, 1); };
4216 sub restore_tar_archive
{
4217 my ($archive, $vmid, $user, $opts) = @_;
4219 if ($archive ne '-') {
4220 my $firstfile = tar_archive_read_firstfile
($archive);
4221 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4222 if $firstfile ne 'qemu-server.conf';
4225 my $storecfg = cfs_read_file
('storage.cfg');
4227 # destroy existing data - keep empty config
4228 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4229 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4231 my $tocmd = "/usr/lib/qemu-server/qmextract";
4233 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4234 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4235 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4236 $tocmd .= ' --info' if $opts->{info
};
4238 # tar option "xf" does not autodetect compression when read from STDIN,
4239 # so we pipe to zcat
4240 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4241 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4243 my $tmpdir = "/var/tmp/vzdumptmp$$";
4246 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4247 local $ENV{VZDUMP_VMID
} = $vmid;
4248 local $ENV{VZDUMP_USER
} = $user;
4250 my $conffile = config_file
($vmid);
4251 my $tmpfn = "$conffile.$$.tmp";
4253 # disable interrupts (always do cleanups)
4254 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4255 print STDERR
"got interrupt - ignored\n";
4260 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4261 die "interrupted by signal\n";
4264 if ($archive eq '-') {
4265 print "extracting archive from STDIN\n";
4266 run_command
($cmd, input
=> "<&STDIN");
4268 print "extracting archive '$archive'\n";
4272 return if $opts->{info
};
4276 my $statfile = "$tmpdir/qmrestore.stat";
4277 if (my $fd = IO
::File-
>new($statfile, "r")) {
4278 while (defined (my $line = <$fd>)) {
4279 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4280 $map->{$1} = $2 if $1;
4282 print STDERR
"unable to parse line in statfile - $line\n";
4288 my $confsrc = "$tmpdir/qemu-server.conf";
4290 my $srcfd = new IO
::File
($confsrc, "r") ||
4291 die "unable to open file '$confsrc'\n";
4293 my $outfd = new IO
::File
($tmpfn, "w") ||
4294 die "unable to write config for VM $vmid\n";
4296 my $cookie = { netcount
=> 0 };
4297 while (defined (my $line = <$srcfd>)) {
4298 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4310 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4317 rename $tmpfn, $conffile ||
4318 die "unable to commit configuration file '$conffile'\n";
4320 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4322 eval { rescan
($vmid, 1); };
4327 # Internal snapshots
4329 # NOTE: Snapshot create/delete involves several non-atomic
4330 # action, and can take a long time.
4331 # So we try to avoid locking the file and use 'lock' variable
4332 # inside the config file instead.
4334 my $snapshot_copy_config = sub {
4335 my ($source, $dest) = @_;
4337 foreach my $k (keys %$source) {
4338 next if $k eq 'snapshots';
4339 next if $k eq 'snapstate';
4340 next if $k eq 'snaptime';
4341 next if $k eq 'vmstate';
4342 next if $k eq 'lock';
4343 next if $k eq 'digest';
4344 next if $k eq 'description';
4345 next if $k =~ m/^unused\d+$/;
4347 $dest->{$k} = $source->{$k};
4351 my $snapshot_apply_config = sub {
4352 my ($conf, $snap) = @_;
4354 # copy snapshot list
4356 snapshots
=> $conf->{snapshots
},
4359 # keep description and list of unused disks
4360 foreach my $k (keys %$conf) {
4361 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4362 $newconf->{$k} = $conf->{$k};
4365 &$snapshot_copy_config($snap, $newconf);
4370 sub foreach_writable_storage
{
4371 my ($conf, $func) = @_;
4375 foreach my $ds (keys %$conf) {
4376 next if !valid_drivename
($ds);
4378 my $drive = parse_drive
($ds, $conf->{$ds});
4380 next if drive_is_cdrom
($drive);
4382 my $volid = $drive->{file
};
4384 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4385 $sidhash->{$sid} = $sid if $sid;
4388 foreach my $sid (sort keys %$sidhash) {
4393 my $alloc_vmstate_volid = sub {
4394 my ($storecfg, $vmid, $conf, $snapname) = @_;
4396 # Note: we try to be smart when selecting a $target storage
4400 # search shared storage first
4401 foreach_writable_storage
($conf, sub {
4403 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4404 return if !$scfg->{shared
};
4406 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4410 # now search local storage
4411 foreach_writable_storage
($conf, sub {
4413 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4414 return if $scfg->{shared
};
4416 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4420 $target = 'local' if !$target;
4422 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4423 # we abort live save after $conf->{memory}, so we need at max twice that space
4424 my $size = $conf->{memory
}*2 + $driver_state_size;
4426 my $name = "vm-$vmid-state-$snapname";
4427 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4428 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4429 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4434 my $snapshot_prepare = sub {
4435 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4439 my $updatefn = sub {
4441 my $conf = load_config
($vmid);
4443 die "you can't take a snapshot if it's a template\n"
4444 if is_template
($conf);
4448 $conf->{lock} = 'snapshot';
4450 die "snapshot name '$snapname' already used\n"
4451 if defined($conf->{snapshots
}->{$snapname});
4453 my $storecfg = PVE
::Storage
::config
();
4454 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4456 $snap = $conf->{snapshots
}->{$snapname} = {};
4458 if ($save_vmstate && check_running
($vmid)) {
4459 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4462 &$snapshot_copy_config($conf, $snap);
4464 $snap->{snapstate
} = "prepare";
4465 $snap->{snaptime
} = time();
4466 $snap->{description
} = $comment if $comment;
4468 # always overwrite machine if we save vmstate. This makes sure we
4469 # can restore it later using correct machine type
4470 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4472 update_config_nolock
($vmid, $conf, 1);
4475 lock_config
($vmid, $updatefn);
4480 my $snapshot_commit = sub {
4481 my ($vmid, $snapname) = @_;
4483 my $updatefn = sub {
4485 my $conf = load_config
($vmid);
4487 die "missing snapshot lock\n"
4488 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4490 my $snap = $conf->{snapshots
}->{$snapname};
4492 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4494 die "wrong snapshot state\n"
4495 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4497 delete $snap->{snapstate
};
4498 delete $conf->{lock};
4500 my $newconf = &$snapshot_apply_config($conf, $snap);
4502 $newconf->{parent
} = $snapname;
4504 update_config_nolock
($vmid, $newconf, 1);
4507 lock_config
($vmid, $updatefn);
4510 sub snapshot_rollback
{
4511 my ($vmid, $snapname) = @_;
4517 my $storecfg = PVE
::Storage
::config
();
4519 my $updatefn = sub {
4521 my $conf = load_config
($vmid);
4523 die "you can't rollback if vm is a template\n" if is_template
($conf);
4525 $snap = $conf->{snapshots
}->{$snapname};
4527 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4529 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4530 if $snap->{snapstate
};
4534 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4537 die "unable to rollback vm $vmid: vm is running\n"
4538 if check_running
($vmid);
4541 $conf->{lock} = 'rollback';
4543 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4544 delete $conf->{lock};
4550 my $has_machine_config = defined($conf->{machine
});
4552 # copy snapshot config to current config
4553 $conf = &$snapshot_apply_config($conf, $snap);
4554 $conf->{parent
} = $snapname;
4556 # Note: old code did not store 'machine', so we try to be smart
4557 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4558 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4559 # we remove the 'machine' configuration if not explicitly specified
4560 # in the original config.
4561 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4564 update_config_nolock
($vmid, $conf, 1);
4566 if (!$prepare && $snap->{vmstate
}) {
4567 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4568 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4572 lock_config
($vmid, $updatefn);
4574 foreach_drive
($snap, sub {
4575 my ($ds, $drive) = @_;
4577 return if drive_is_cdrom
($drive);
4579 my $volid = $drive->{file
};
4580 my $device = "drive-$ds";
4582 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4586 lock_config
($vmid, $updatefn);
4589 my $savevm_wait = sub {
4593 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4594 if (!$stat->{status
}) {
4595 die "savevm not active\n";
4596 } elsif ($stat->{status
} eq 'active') {
4599 } elsif ($stat->{status
} eq 'completed') {
4602 die "query-savevm returned status '$stat->{status}'\n";
4607 sub snapshot_create
{
4608 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4610 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4612 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4616 my $running = check_running
($vmid);
4619 # create internal snapshots of all drives
4621 my $storecfg = PVE
::Storage
::config
();
4624 if ($snap->{vmstate
}) {
4625 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4626 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4627 &$savevm_wait($vmid);
4629 vm_mon_cmd
($vmid, "savevm-start");
4633 qga_freezefs
($vmid) if $running && $freezefs;
4635 foreach_drive
($snap, sub {
4636 my ($ds, $drive) = @_;
4638 return if drive_is_cdrom
($drive);
4640 my $volid = $drive->{file
};
4641 my $device = "drive-$ds";
4643 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4644 $drivehash->{$ds} = 1;
4649 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4652 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4656 warn "snapshot create failed: starting cleanup\n";
4657 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4662 &$snapshot_commit($vmid, $snapname);
4665 # Note: $drivehash is only set when called from snapshot_create.
4666 sub snapshot_delete
{
4667 my ($vmid, $snapname, $force, $drivehash) = @_;
4674 my $unlink_parent = sub {
4675 my ($confref, $new_parent) = @_;
4677 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4679 $confref->{parent
} = $new_parent;
4681 delete $confref->{parent
};
4686 my $updatefn = sub {
4687 my ($remove_drive) = @_;
4689 my $conf = load_config
($vmid);
4693 die "you can't delete a snapshot if vm is a template\n"
4694 if is_template
($conf);
4697 $snap = $conf->{snapshots
}->{$snapname};
4699 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4701 # remove parent refs
4702 &$unlink_parent($conf, $snap->{parent
});
4703 foreach my $sn (keys %{$conf->{snapshots
}}) {
4704 next if $sn eq $snapname;
4705 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4708 if ($remove_drive) {
4709 if ($remove_drive eq 'vmstate') {
4710 delete $snap->{$remove_drive};
4712 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4713 my $volid = $drive->{file
};
4714 delete $snap->{$remove_drive};
4715 add_unused_volume
($conf, $volid);
4720 $snap->{snapstate
} = 'delete';
4722 delete $conf->{snapshots
}->{$snapname};
4723 delete $conf->{lock} if $drivehash;
4724 foreach my $volid (@$unused) {
4725 add_unused_volume
($conf, $volid);
4729 update_config_nolock
($vmid, $conf, 1);
4732 lock_config
($vmid, $updatefn);
4734 # now remove vmstate file
4736 my $storecfg = PVE
::Storage
::config
();
4738 if ($snap->{vmstate
}) {
4739 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4741 die $err if !$force;
4744 # save changes (remove vmstate from snapshot)
4745 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4748 # now remove all internal snapshots
4749 foreach_drive
($snap, sub {
4750 my ($ds, $drive) = @_;
4752 return if drive_is_cdrom
($drive);
4754 my $volid = $drive->{file
};
4755 my $device = "drive-$ds";
4757 if (!$drivehash || $drivehash->{$ds}) {
4758 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4760 die $err if !$force;
4765 # save changes (remove drive fron snapshot)
4766 lock_config
($vmid, $updatefn, $ds) if !$force;
4767 push @$unused, $volid;
4770 # now cleanup config
4772 lock_config
($vmid, $updatefn);
4776 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4779 foreach_drive
($conf, sub {
4780 my ($ds, $drive) = @_;
4782 return if drive_is_cdrom
($drive);
4783 my $volid = $drive->{file
};
4784 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4787 return $err ?
0 : 1;
4790 sub template_create
{
4791 my ($vmid, $conf, $disk) = @_;
4793 my $storecfg = PVE
::Storage
::config
();
4795 foreach_drive
($conf, sub {
4796 my ($ds, $drive) = @_;
4798 return if drive_is_cdrom
($drive);
4799 return if $disk && $ds ne $disk;
4801 my $volid = $drive->{file
};
4802 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4804 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4805 $drive->{file
} = $voliddst;
4806 $conf->{$ds} = print_drive
($vmid, $drive);
4807 update_config_nolock
($vmid, $conf, 1);
4814 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4817 sub qemu_img_convert
{
4818 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4820 my $storecfg = PVE
::Storage
::config
();
4821 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4822 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4824 if ($src_storeid && $dst_storeid) {
4825 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4826 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4828 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4829 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4831 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4832 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4835 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4836 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4837 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4841 if($line =~ m/\((\S+)\/100\
%\)/){
4843 my $transferred = int($size * $percent / 100);
4844 my $remaining = $size - $transferred;
4846 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4851 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4853 die "copy failed: $err" if $err;
4857 sub qemu_img_format
{
4858 my ($scfg, $volname) = @_;
4860 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4862 } elsif ($scfg->{type
} eq 'iscsi') {
4863 return "host_device";
4869 sub qemu_drive_mirror
{
4870 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4876 my $storecfg = PVE
::Storage
::config
();
4877 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4880 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4883 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4887 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4890 #fixme : sometime drive-mirror timeout, but works fine after.
4891 # (I have see the problem with big volume > 200GB), so we need to eval
4892 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4893 sync
=> "full", target
=> $dst_path, format
=> $format); };
4895 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4896 sync
=> "full", target
=> $dst_path); };
4901 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4902 my $stat = @$stats[0];
4903 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4904 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4906 my $transferred = $stat->{offset
};
4907 my $total = $stat->{len
};
4908 my $remaining = $total - $transferred;
4909 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4911 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4913 last if ($stat->{len
} == $stat->{offset
});
4914 if ($old_len == $stat->{offset
}) {
4915 if ($maxwait && $count > $maxwait) {
4916 # if writes to disk occurs the disk needs to be freezed
4917 # to be able to complete the migration
4918 vm_suspend
($vmid,1);
4922 $count++ unless $frozen;
4928 $old_len = $stat->{offset
};
4932 if ($vmiddst == $vmid) {
4933 # switch the disk if source and destination are on the same guest
4934 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4938 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4939 die "mirroring error: $err";
4942 if ($vmiddst != $vmid) {
4943 # if we clone a disk for a new target vm, we don't switch the disk
4944 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4950 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4951 $newvmid, $storage, $format, $full, $newvollist) = @_;
4956 print "create linked clone of drive $drivename ($drive->{file})\n";
4957 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4958 push @$newvollist, $newvolid;
4960 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4961 $storeid = $storage if $storage;
4963 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4965 $format = $drive->{format
} || $defFormat;
4968 # test if requested format is supported - else use default
4969 my $supported = grep { $_ eq $format } @$validFormats;
4970 $format = $defFormat if !$supported;
4972 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4974 print "create full clone of drive $drivename ($drive->{file})\n";
4975 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4976 push @$newvollist, $newvolid;
4978 if (!$running || $snapname) {
4979 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4981 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4985 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4988 $disk->{format
} = undef;
4989 $disk->{file
} = $newvolid;
4990 $disk->{size
} = $size;
4995 # this only works if VM is running
4996 sub get_current_qemu_machine
{
4999 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5000 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
5002 my ($current, $default);
5003 foreach my $e (@$res) {
5004 $default = $e->{name
} if $e->{'is-default'};
5005 $current = $e->{name
} if $e->{'is-current'};
5008 # fallback to the default machine if current is not supported by qemu
5009 return $current || $default || 'pc';