1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
36 # Note about locking: we use flock on the config file protect
37 # against concurent actions.
38 # Aditionaly, we have a 'lock' setting in the config file. This
39 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
40 # allowed when such lock is set. But you can ignore this kind of
41 # lock with the --skiplock flag.
43 cfs_register_file
('/qemu-server/',
47 PVE
::JSONSchema
::register_standard_option
('skiplock', {
48 description
=> "Ignore locks - only root is allowed to use this option.",
53 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
54 description
=> "Some command save/restore state from this location.",
60 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
61 description
=> "The name of the snapshot.",
62 type
=> 'string', format
=> 'pve-configid',
66 #no warnings 'redefine';
68 unless(defined(&_VZSYSCALLS_H_
)) {
69 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
70 require 'sys/syscall.ph';
71 if(defined(&__x86_64__
)) {
72 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
73 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
74 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
75 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
76 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
77 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
78 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
79 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
81 elsif(defined( &__i386__
) ) {
82 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
83 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
84 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
85 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
86 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
87 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
88 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
89 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
91 die("no fairsched syscall for this arch");
93 require 'asm/ioctl.ph';
94 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
98 my ($parent, $weight, $desired) = @_;
100 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
103 sub fairsched_rmnod
{
106 return syscall(&__NR_fairsched_rmnod
, int($id));
110 my ($pid, $newid) = @_;
112 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
115 sub fairsched_vcpus
{
116 my ($id, $vcpus) = @_;
118 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
122 my ($id, $op, $rate) = @_;
124 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
127 use constant FAIRSCHED_SET_RATE
=> 0;
128 use constant FAIRSCHED_DROP_RATE
=> 1;
129 use constant FAIRSCHED_GET_RATE
=> 2;
131 sub fairsched_cpulimit
{
132 my ($id, $limit) = @_;
134 my $cpulim1024 = int($limit * 1024 / 100);
135 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
137 return fairsched_rate
($id, $op, $cpulim1024);
140 my $nodename = PVE
::INotify
::nodename
();
142 mkdir "/etc/pve/nodes/$nodename";
143 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
146 my $var_run_tmpdir = "/var/run/qemu-server";
147 mkdir $var_run_tmpdir;
149 my $lock_dir = "/var/lock/qemu-server";
152 my $pcisysfs = "/sys/bus/pci";
158 description
=> "Specifies whether a VM will be started during system bootup.",
164 description
=> "Automatic restart after crash (currently ignored).",
170 description
=> "Allow hotplug for disk and network device",
176 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
182 description
=> "Lock/unlock the VM.",
183 enum
=> [qw(migrate backup snapshot rollback)],
188 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
195 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
203 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
210 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
216 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
224 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
225 enum
=> PVE
::Tools
::kvmkeymaplist
(),
230 type
=> 'string', format
=> 'dns-name',
231 description
=> "Set a name for the VM. Only used on the configuration web interface.",
236 description
=> "scsi controller model",
237 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)],
243 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
248 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
249 description
=> <<EODESC,
250 Used to enable special optimization/features for specific
253 other => unspecified OS
254 wxp => Microsoft Windows XP
255 w2k => Microsoft Windows 2000
256 w2k3 => Microsoft Windows 2003
257 w2k8 => Microsoft Windows 2008
258 wvista => Microsoft Windows Vista
259 win7 => Microsoft Windows 7
260 win8 => Microsoft Windows 8/2012
261 l24 => Linux 2.4 Kernel
262 l26 => Linux 2.6/3.X Kernel
263 solaris => solaris/opensolaris/openindiania kernel
265 other|l24|l26|solaris ... no special behaviour
266 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
272 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
273 pattern
=> '[acdn]{1,4}',
278 type
=> 'string', format
=> 'pve-qm-bootdisk',
279 description
=> "Enable booting from specified disk.",
280 pattern
=> '(ide|sata|scsi|virtio)\d+',
285 description
=> "The number of CPUs. Please use option -sockets instead.",
292 description
=> "The number of CPU sockets.",
299 description
=> "The number of cores per socket.",
306 description
=> "Maximum cpus for hotplug.",
313 description
=> "Enable/disable ACPI.",
319 description
=> "Enable/disable Qemu GuestAgent.",
325 description
=> "Enable/disable KVM hardware virtualization.",
331 description
=> "Enable/disable time drift fix.",
337 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
342 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
347 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
348 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
352 type
=> 'string', format
=> 'pve-qm-watchdog',
353 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
354 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
359 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
360 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
361 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
366 type
=> 'string', format
=> 'pve-qm-startup',
367 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
368 description
=> "Startup and shutdown behavior. Order is a non-negative number defining the general startup order. Shutdown in done with reverse ordering. Additionally you can set the 'up' or 'down' delay in seconds, which specifies a delay to wait before the next VM is started or stopped.",
373 description
=> "Enable/disable Template.",
379 description
=> <<EODESCR,
380 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
382 args: -no-reboot -no-hpet
389 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
394 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
398 migrate_downtime
=> {
401 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
407 type
=> 'string', format
=> 'pve-qm-drive',
408 typetext
=> 'volume',
409 description
=> "This is an alias for option -ide2",
413 description
=> "Emulated CPU type.",
415 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
418 parent
=> get_standard_option
('pve-snapshot-name', {
420 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
424 description
=> "Timestamp for snapshots.",
430 type
=> 'string', format
=> 'pve-volume-id',
431 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
434 description
=> "Specific the Qemu machine type.",
436 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
442 # what about other qemu settings ?
444 #machine => 'string',
457 ##soundhw => 'string',
459 while (my ($k, $v) = each %$confdesc) {
460 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
463 my $MAX_IDE_DISKS = 4;
464 my $MAX_SCSI_DISKS = 14;
465 my $MAX_VIRTIO_DISKS = 16;
466 my $MAX_SATA_DISKS = 6;
467 my $MAX_USB_DEVICES = 5;
469 my $MAX_UNUSED_DISKS = 8;
470 my $MAX_HOSTPCI_DEVICES = 2;
471 my $MAX_SERIAL_PORTS = 4;
472 my $MAX_PARALLEL_PORTS = 3;
474 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
475 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3'];
476 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
480 type
=> 'string', format
=> 'pve-qm-net',
481 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
482 description
=> <<EODESCR,
483 Specify network devices.
485 MODEL is one of: $nic_model_list_txt
487 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
488 automatically generated if not specified.
490 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
492 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
494 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
500 The DHCP server assign addresses to the guest starting from 10.0.2.15.
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
506 for (my $i = 0; $i < $MAX_NETS; $i++) {
507 $confdesc->{"net$i"} = $netdesc;
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
516 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
524 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
530 type
=> 'string', format
=> 'pve-qm-drive',
531 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
532 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
534 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
538 type
=> 'string', format
=> 'pve-qm-drive',
539 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
540 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
542 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
546 type
=> 'string', format
=> 'pve-qm-usb-device',
547 typetext
=> 'host=HOSTUSBDEVICE|spice',
548 description
=> <<EODESCR,
549 Configure an USB device (n is 0 to 4). This can be used to
550 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
552 'bus-port(.port)*' (decimal numbers) or
553 'vendor_id:product_id' (hexadeciaml numbers)
555 You can use the 'lsusb -t' command to list existing usb devices.
557 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
559 The value 'spice' can be used to add a usb redirection devices for spice.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
567 type
=> 'string', format
=> 'pve-qm-hostpci',
568 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]",
569 description
=> <<EODESCR,
570 Map host pci devices. HOSTPCIDEVICE syntax is:
572 'bus:dev.func' (hexadecimal numbers)
574 You can us the 'lspci' command to list existing pci devices.
576 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
578 The 'driver' option is currently ignored.
580 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
582 Experimental: user reported problems with this option.
585 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
590 pattern
=> '(/dev/ttyS\d+|socket)',
591 description
=> <<EODESCR,
592 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
594 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
596 Experimental: user reported problems with this option.
603 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
604 description
=> <<EODESCR,
605 Map host parallel devices (n is 0 to 2).
607 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
609 Experimental: user reported problems with this option.
613 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
614 $confdesc->{"parallel$i"} = $paralleldesc;
617 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
618 $confdesc->{"serial$i"} = $serialdesc;
621 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
622 $confdesc->{"hostpci$i"} = $hostpcidesc;
625 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
626 $drivename_hash->{"ide$i"} = 1;
627 $confdesc->{"ide$i"} = $idedesc;
630 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
631 $drivename_hash->{"sata$i"} = 1;
632 $confdesc->{"sata$i"} = $satadesc;
635 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
636 $drivename_hash->{"scsi$i"} = 1;
637 $confdesc->{"scsi$i"} = $scsidesc ;
640 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
641 $drivename_hash->{"virtio$i"} = 1;
642 $confdesc->{"virtio$i"} = $virtiodesc;
645 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
646 $confdesc->{"usb$i"} = $usbdesc;
651 type
=> 'string', format
=> 'pve-volume-id',
652 description
=> "Reference to unused volumes.",
655 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
656 $confdesc->{"unused$i"} = $unuseddesc;
659 my $kvm_api_version = 0;
663 return $kvm_api_version if $kvm_api_version;
665 my $fh = IO
::File-
>new("</dev/kvm") ||
668 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
669 $kvm_api_version = $v;
674 return $kvm_api_version;
677 my $kvm_user_version;
679 sub kvm_user_version
{
681 return $kvm_user_version if $kvm_user_version;
683 $kvm_user_version = 'unknown';
685 my $tmp = `kvm -help 2>/dev/null`;
687 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
688 $kvm_user_version = $2;
691 return $kvm_user_version;
695 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
698 # order is important - used to autoselect boot disk
699 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
700 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
701 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
702 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
705 sub valid_drivename
{
708 return defined($drivename_hash->{$dev});
713 return defined($confdesc->{$key});
717 return $nic_model_list;
720 sub os_list_description
{
725 w2k
=> 'Windows 2000',
726 w2k3
=>, 'Windows 2003',
727 w2k8
=> 'Windows 2008',
728 wvista
=> 'Windows Vista',
730 win8
=> 'Windows 8/2012',
740 return $cdrom_path if $cdrom_path;
742 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
743 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
744 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
748 my ($storecfg, $vmid, $cdrom) = @_;
750 if ($cdrom eq 'cdrom') {
751 return get_cdrom_path
();
752 } elsif ($cdrom eq 'none') {
754 } elsif ($cdrom =~ m
|^/|) {
757 return PVE
::Storage
::path
($storecfg, $cdrom);
761 # try to convert old style file names to volume IDs
762 sub filename_to_volume_id
{
763 my ($vmid, $file, $media) = @_;
765 if (!($file eq 'none' || $file eq 'cdrom' ||
766 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
768 return undef if $file =~ m
|/|;
770 if ($media && $media eq 'cdrom') {
771 $file = "local:iso/$file";
773 $file = "local:$vmid/$file";
780 sub verify_media_type
{
781 my ($opt, $vtype, $media) = @_;
786 if ($media eq 'disk') {
788 } elsif ($media eq 'cdrom') {
791 die "internal error";
794 return if ($vtype eq $etype);
796 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
799 sub cleanup_drive_path
{
800 my ($opt, $storecfg, $drive) = @_;
802 # try to convert filesystem paths to volume IDs
804 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
805 ($drive->{file
} !~ m
|^/dev/.+|) &&
806 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
807 ($drive->{file
} !~ m/^\d+$/)) {
808 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
809 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
810 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
811 verify_media_type
($opt, $vtype, $drive->{media
});
812 $drive->{file
} = $volid;
815 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
818 sub create_conf_nolock
{
819 my ($vmid, $settings) = @_;
821 my $filename = config_file
($vmid);
823 die "configuration file '$filename' already exists\n" if -f
$filename;
825 my $defaults = load_defaults
();
827 $settings->{name
} = "vm$vmid" if !$settings->{name
};
828 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
831 foreach my $opt (keys %$settings) {
832 next if !$confdesc->{$opt};
834 my $value = $settings->{$opt};
837 $data .= "$opt: $value\n";
840 PVE
::Tools
::file_set_contents
($filename, $data);
843 my $parse_size = sub {
846 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
847 my ($size, $unit) = ($1, $3);
850 $size = $size * 1024;
851 } elsif ($unit eq 'M') {
852 $size = $size * 1024 * 1024;
853 } elsif ($unit eq 'G') {
854 $size = $size * 1024 * 1024 * 1024;
860 my $format_size = sub {
865 my $kb = int($size/1024);
866 return $size if $kb*1024 != $size;
868 my $mb = int($kb/1024);
869 return "${kb}K" if $mb*1024 != $kb;
871 my $gb = int($mb/1024);
872 return "${mb}M" if $gb*1024 != $mb;
877 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
878 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
879 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
880 # [,aio=native|threads][,discard=ignore|on]
883 my ($key, $data) = @_;
887 # $key may be undefined - used to verify JSON parameters
888 if (!defined($key)) {
889 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
891 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
892 $res->{interface
} = $1;
898 foreach my $p (split (/,/, $data)) {
899 next if $p =~ m/^\s*$/;
901 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
902 my ($k, $v) = ($1, $2);
904 $k = 'file' if $k eq 'volume';
906 return undef if defined $res->{$k};
908 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
909 return undef if !$v || $v !~ m/^\d+/;
911 $v = sprintf("%.3f", $v / (1024*1024));
915 if (!$res->{file
} && $p !~ m/=/) {
923 return undef if !$res->{file
};
925 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
929 return undef if $res->{cache
} &&
930 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
931 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
932 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
933 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
934 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
935 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
936 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
937 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
938 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
939 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
940 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
941 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
942 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
944 return undef if $res->{mbps_rd
} && $res->{mbps
};
945 return undef if $res->{mbps_wr
} && $res->{mbps
};
947 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
949 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
951 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{iops_rd
} && $res->{iops
};
955 return undef if $res->{iops_wr
} && $res->{iops
};
958 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
959 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
960 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
961 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
962 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
963 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
967 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
970 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
971 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
972 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
973 return undef if $res->{interface
} eq 'virtio';
976 # rerror does not work with scsi drives
977 if ($res->{rerror
}) {
978 return undef if $res->{interface
} eq 'scsi';
984 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
987 my ($vmid, $drive) = @_;
990 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
991 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
994 if ($drive->{size
}) {
995 $opts .= ",size=" . &$format_size($drive->{size
});
998 return "$drive->{file}$opts";
1002 my($fh, $noerr) = @_;
1005 my $SG_GET_VERSION_NUM = 0x2282;
1007 my $versionbuf = "\x00" x
8;
1008 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1010 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1013 my $version = unpack("I", $versionbuf);
1014 if ($version < 30000) {
1015 die "scsi generic interface too old\n" if !$noerr;
1019 my $buf = "\x00" x
36;
1020 my $sensebuf = "\x00" x
8;
1021 my $cmd = pack("C x3 C x1", 0x12, 36);
1023 # see /usr/include/scsi/sg.h
1024 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1026 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1027 length($sensebuf), 0, length($buf), $buf,
1028 $cmd, $sensebuf, 6000);
1030 $ret = ioctl($fh, $SG_IO, $packet);
1032 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1036 my @res = unpack($sg_io_hdr_t, $packet);
1037 if ($res[17] || $res[18]) {
1038 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1043 (my $byte0, my $byte1, $res->{vendor
},
1044 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1046 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1047 $res->{type
} = $byte0 & 31;
1055 my $fh = IO
::File-
>new("+<$path") || return undef;
1056 my $res = scsi_inquiry
($fh, 1);
1062 sub print_drivedevice_full
{
1063 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1068 if ($drive->{interface
} eq 'virtio') {
1069 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1070 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1071 } elsif ($drive->{interface
} eq 'scsi') {
1072 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1073 my $controller = int($drive->{index} / $maxdev);
1074 my $unit = $drive->{index} % $maxdev;
1075 my $devicetype = 'hd';
1077 if (drive_is_cdrom
($drive)) {
1080 if ($drive->{file
} =~ m
|^/|) {
1081 $path = $drive->{file
};
1083 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1086 if($path =~ m/^iscsi\:\/\
//){
1087 $devicetype = 'generic';
1089 if (my $info = path_is_scsi
($path)) {
1090 if ($info->{type
} == 0) {
1091 $devicetype = 'block';
1092 } elsif ($info->{type
} == 1) { # tape
1093 $devicetype = 'generic';
1099 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1100 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1102 $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1105 } elsif ($drive->{interface
} eq 'ide'){
1107 my $controller = int($drive->{index} / $maxdev);
1108 my $unit = $drive->{index} % $maxdev;
1109 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1111 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1112 } elsif ($drive->{interface
} eq 'sata'){
1113 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1114 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1115 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1116 } elsif ($drive->{interface
} eq 'usb') {
1118 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1120 die "unsupported interface type";
1123 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1128 sub print_drive_full
{
1129 my ($storecfg, $vmid, $drive) = @_;
1132 foreach my $o (@qemu_drive_options) {
1133 next if $o eq 'bootindex';
1134 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1137 foreach my $o (qw(bps bps_rd bps_wr)) {
1138 my $v = $drive->{"m$o"};
1139 $opts .= ",$o=" . int($v*1024*1024) if $v;
1142 # use linux-aio by default (qemu default is threads)
1143 $opts .= ",aio=native" if !$drive->{aio
};
1146 my $volid = $drive->{file
};
1147 if (drive_is_cdrom
($drive)) {
1148 $path = get_iso_path
($storecfg, $vmid, $volid);
1150 if ($volid =~ m
|^/|) {
1153 $path = PVE
::Storage
::path
($storecfg, $volid);
1157 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1159 my $pathinfo = $path ?
"file=$path," : '';
1161 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1164 sub print_netdevice_full
{
1165 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1167 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1169 my $device = $net->{model
};
1170 if ($net->{model
} eq 'virtio') {
1171 $device = 'virtio-net-pci';
1174 # qemu > 0.15 always try to boot from network - we disable that by
1175 # not loading the pxe rom file
1176 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1177 my $pciaddr = print_pci_addr
("$netid", $bridges);
1178 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1179 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1183 sub print_netdev_full
{
1184 my ($vmid, $conf, $net, $netid) = @_;
1187 if ($netid =~ m/^net(\d+)$/) {
1191 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1193 my $ifname = "tap${vmid}i$i";
1195 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1196 die "interface name '$ifname' is too long (max 15 character)\n"
1197 if length($ifname) >= 16;
1199 my $vhostparam = '';
1200 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1202 my $vmname = $conf->{name
} || "vm$vmid";
1204 if ($net->{bridge
}) {
1205 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1207 return "type=user,id=$netid,hostname=$vmname";
1211 sub drive_is_cdrom
{
1214 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1221 return undef if !$value;
1224 my @list = split(/,/, $value);
1228 foreach my $kv (@list) {
1230 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) {
1233 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1234 $res->{driver
} = $1;
1235 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1236 $res->{rombar
} = $1;
1238 warn "unknown hostpci setting '$kv'\n";
1242 return undef if !$found;
1247 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1253 foreach my $kvp (split(/,/, $data)) {
1255 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1257 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1258 $res->{model
} = $model;
1259 $res->{macaddr
} = $mac;
1260 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1261 $res->{bridge
} = $1;
1262 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1264 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1272 return undef if !$res->{model
};
1280 my $res = "$net->{model}";
1281 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1282 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1283 $res .= ",rate=$net->{rate}" if $net->{rate
};
1284 $res .= ",tag=$net->{tag}" if $net->{tag
};
1289 sub add_random_macs
{
1290 my ($settings) = @_;
1292 foreach my $opt (keys %$settings) {
1293 next if $opt !~ m/^net(\d+)$/;
1294 my $net = parse_net
($settings->{$opt});
1296 $settings->{$opt} = print_net
($net);
1300 sub add_unused_volume
{
1301 my ($config, $volid) = @_;
1304 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1305 my $test = "unused$ind";
1306 if (my $vid = $config->{$test}) {
1307 return if $vid eq $volid; # do not add duplicates
1313 die "To many unused volume - please delete them first.\n" if !$key;
1315 $config->{$key} = $volid;
1320 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1321 sub verify_bootdisk
{
1322 my ($value, $noerr) = @_;
1324 return $value if valid_drivename
($value);
1326 return undef if $noerr;
1328 die "invalid boot disk '$value'\n";
1331 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1333 my ($value, $noerr) = @_;
1335 return $value if parse_net
($value);
1337 return undef if $noerr;
1339 die "unable to parse network options\n";
1342 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1344 my ($value, $noerr) = @_;
1346 return $value if parse_drive
(undef, $value);
1348 return undef if $noerr;
1350 die "unable to parse drive options\n";
1353 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1354 sub verify_hostpci
{
1355 my ($value, $noerr) = @_;
1357 return $value if parse_hostpci
($value);
1359 return undef if $noerr;
1361 die "unable to parse pci id\n";
1364 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1365 sub verify_watchdog
{
1366 my ($value, $noerr) = @_;
1368 return $value if parse_watchdog
($value);
1370 return undef if $noerr;
1372 die "unable to parse watchdog options\n";
1375 sub parse_watchdog
{
1378 return undef if !$value;
1382 foreach my $p (split(/,/, $value)) {
1383 next if $p =~ m/^\s*$/;
1385 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1387 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1388 $res->{action
} = $2;
1397 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1398 sub verify_startup
{
1399 my ($value, $noerr) = @_;
1401 return $value if parse_startup
($value);
1403 return undef if $noerr;
1405 die "unable to parse startup options\n";
1411 return undef if !$value;
1415 foreach my $p (split(/,/, $value)) {
1416 next if $p =~ m/^\s*$/;
1418 if ($p =~ m/^(order=)?(\d+)$/) {
1420 } elsif ($p =~ m/^up=(\d+)$/) {
1422 } elsif ($p =~ m/^down=(\d+)$/) {
1432 sub parse_usb_device
{
1435 return undef if !$value;
1437 my @dl = split(/,/, $value);
1441 foreach my $v (@dl) {
1442 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1444 $res->{vendorid
} = $2;
1445 $res->{productid
} = $4;
1446 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1448 $res->{hostbus
} = $1;
1449 $res->{hostport
} = $2;
1450 } elsif ($v =~ m/^spice$/) {
1457 return undef if !$found;
1462 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1463 sub verify_usb_device
{
1464 my ($value, $noerr) = @_;
1466 return $value if parse_usb_device
($value);
1468 return undef if $noerr;
1470 die "unable to parse usb device\n";
1473 # add JSON properties for create and set function
1474 sub json_config_properties
{
1477 foreach my $opt (keys %$confdesc) {
1478 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1479 $prop->{$opt} = $confdesc->{$opt};
1486 my ($key, $value) = @_;
1488 die "unknown setting '$key'\n" if !$confdesc->{$key};
1490 my $type = $confdesc->{$key}->{type
};
1492 if (!defined($value)) {
1493 die "got undefined value\n";
1496 if ($value =~ m/[\n\r]/) {
1497 die "property contains a line feed\n";
1500 if ($type eq 'boolean') {
1501 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1502 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1503 die "type check ('boolean') failed - got '$value'\n";
1504 } elsif ($type eq 'integer') {
1505 return int($1) if $value =~ m/^(\d+)$/;
1506 die "type check ('integer') failed - got '$value'\n";
1507 } elsif ($type eq 'number') {
1508 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1509 die "type check ('number') failed - got '$value'\n";
1510 } elsif ($type eq 'string') {
1511 if (my $fmt = $confdesc->{$key}->{format
}) {
1512 if ($fmt eq 'pve-qm-drive') {
1513 # special case - we need to pass $key to parse_drive()
1514 my $drive = parse_drive
($key, $value);
1515 return $value if $drive;
1516 die "unable to parse drive options\n";
1518 PVE
::JSONSchema
::check_format
($fmt, $value);
1521 $value =~ s/^\"(.*)\"$/$1/;
1524 die "internal error"
1528 sub lock_config_full
{
1529 my ($vmid, $timeout, $code, @param) = @_;
1531 my $filename = config_file_lock
($vmid);
1533 my $res = lock_file
($filename, $timeout, $code, @param);
1540 sub lock_config_mode
{
1541 my ($vmid, $timeout, $shared, $code, @param) = @_;
1543 my $filename = config_file_lock
($vmid);
1545 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1553 my ($vmid, $code, @param) = @_;
1555 return lock_config_full
($vmid, 10, $code, @param);
1558 sub cfs_config_path
{
1559 my ($vmid, $node) = @_;
1561 $node = $nodename if !$node;
1562 return "nodes/$node/qemu-server/$vmid.conf";
1565 sub check_iommu_support
{
1566 #fixme : need to check IOMMU support
1567 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1575 my ($vmid, $node) = @_;
1577 my $cfspath = cfs_config_path
($vmid, $node);
1578 return "/etc/pve/$cfspath";
1581 sub config_file_lock
{
1584 return "$lock_dir/lock-$vmid.conf";
1590 my $conf = config_file
($vmid);
1591 utime undef, undef, $conf;
1595 my ($storecfg, $vmid, $keep_empty_config) = @_;
1597 my $conffile = config_file
($vmid);
1599 my $conf = load_config
($vmid);
1603 # only remove disks owned by this VM
1604 foreach_drive
($conf, sub {
1605 my ($ds, $drive) = @_;
1607 return if drive_is_cdrom
($drive);
1609 my $volid = $drive->{file
};
1611 return if !$volid || $volid =~ m
|^/|;
1613 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1614 return if !$path || !$owner || ($owner != $vmid);
1616 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1619 if ($keep_empty_config) {
1620 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1625 # also remove unused disk
1627 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1630 PVE
::Storage
::foreach_volid
($dl, sub {
1631 my ($volid, $sid, $volname, $d) = @_;
1632 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1642 my ($vmid, $node) = @_;
1644 my $cfspath = cfs_config_path
($vmid, $node);
1646 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1648 die "no such VM ('$vmid')\n" if !defined($conf);
1653 sub parse_vm_config
{
1654 my ($filename, $raw) = @_;
1656 return undef if !defined($raw);
1659 digest
=> Digest
::SHA
::sha1_hex
($raw),
1663 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1664 || die "got strange filename '$filename'";
1671 my @lines = split(/\n/, $raw);
1672 foreach my $line (@lines) {
1673 next if $line =~ m/^\s*$/;
1675 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1677 $conf->{description
} = $descr if $descr;
1679 $conf = $res->{snapshots
}->{$snapname} = {};
1683 if ($line =~ m/^\#(.*)\s*$/) {
1684 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1688 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1689 $descr .= PVE
::Tools
::decode_text
($2);
1690 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1691 $conf->{snapstate
} = $1;
1692 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1695 $conf->{$key} = $value;
1696 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1699 eval { $value = check_type
($key, $value); };
1701 warn "vm $vmid - unable to parse value of '$key' - $@";
1703 my $fmt = $confdesc->{$key}->{format
};
1704 if ($fmt && $fmt eq 'pve-qm-drive') {
1705 my $v = parse_drive
($key, $value);
1706 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1707 $v->{file
} = $volid;
1708 $value = print_drive
($vmid, $v);
1710 warn "vm $vmid - unable to parse value of '$key'\n";
1715 if ($key eq 'cdrom') {
1716 $conf->{ide2
} = $value;
1718 $conf->{$key} = $value;
1724 $conf->{description
} = $descr if $descr;
1726 delete $res->{snapstate
}; # just to be sure
1731 sub write_vm_config
{
1732 my ($filename, $conf) = @_;
1734 delete $conf->{snapstate
}; # just to be sure
1736 if ($conf->{cdrom
}) {
1737 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1738 $conf->{ide2
} = $conf->{cdrom
};
1739 delete $conf->{cdrom
};
1742 # we do not use 'smp' any longer
1743 if ($conf->{sockets
}) {
1744 delete $conf->{smp
};
1745 } elsif ($conf->{smp
}) {
1746 $conf->{sockets
} = $conf->{smp
};
1747 delete $conf->{cores
};
1748 delete $conf->{smp
};
1751 if ($conf->{maxcpus
} && $conf->{sockets
}) {
1752 delete $conf->{sockets
};
1755 my $used_volids = {};
1757 my $cleanup_config = sub {
1758 my ($cref, $snapname) = @_;
1760 foreach my $key (keys %$cref) {
1761 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1762 $key eq 'snapstate';
1763 my $value = $cref->{$key};
1764 eval { $value = check_type
($key, $value); };
1765 die "unable to parse value of '$key' - $@" if $@;
1767 $cref->{$key} = $value;
1769 if (!$snapname && valid_drivename
($key)) {
1770 my $drive = parse_drive
($key, $value);
1771 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1776 &$cleanup_config($conf);
1777 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1778 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1781 # remove 'unusedX' settings if we re-add a volume
1782 foreach my $key (keys %$conf) {
1783 my $value = $conf->{$key};
1784 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1785 delete $conf->{$key};
1789 my $generate_raw_config = sub {
1794 # add description as comment to top of file
1795 my $descr = $conf->{description
} || '';
1796 foreach my $cl (split(/\n/, $descr)) {
1797 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1800 foreach my $key (sort keys %$conf) {
1801 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1802 $raw .= "$key: $conf->{$key}\n";
1807 my $raw = &$generate_raw_config($conf);
1808 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1809 $raw .= "\n[$snapname]\n";
1810 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1816 sub update_config_nolock
{
1817 my ($vmid, $conf, $skiplock) = @_;
1819 check_lock
($conf) if !$skiplock;
1821 my $cfspath = cfs_config_path
($vmid);
1823 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1827 my ($vmid, $conf, $skiplock) = @_;
1829 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1836 # we use static defaults from our JSON schema configuration
1837 foreach my $key (keys %$confdesc) {
1838 if (defined(my $default = $confdesc->{$key}->{default})) {
1839 $res->{$key} = $default;
1843 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1844 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1850 my $vmlist = PVE
::Cluster
::get_vmlist
();
1852 return $res if !$vmlist || !$vmlist->{ids
};
1853 my $ids = $vmlist->{ids
};
1855 foreach my $vmid (keys %$ids) {
1856 my $d = $ids->{$vmid};
1857 next if !$d->{node
} || $d->{node
} ne $nodename;
1858 next if !$d->{type
} || $d->{type
} ne 'qemu';
1859 $res->{$vmid}->{exists} = 1;
1864 # test if VM uses local resources (to prevent migration)
1865 sub check_local_resources
{
1866 my ($conf, $noerr) = @_;
1870 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1871 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1873 foreach my $k (keys %$conf) {
1874 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1875 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1878 die "VM uses local resources\n" if $loc_res && !$noerr;
1883 # check if used storages are available on all nodes (use by migrate)
1884 sub check_storage_availability
{
1885 my ($storecfg, $conf, $node) = @_;
1887 foreach_drive
($conf, sub {
1888 my ($ds, $drive) = @_;
1890 my $volid = $drive->{file
};
1893 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1896 # check if storage is available on both nodes
1897 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1898 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1902 # list nodes where all VM images are available (used by has_feature API)
1904 my ($conf, $storecfg) = @_;
1906 my $nodelist = PVE
::Cluster
::get_nodelist
();
1907 my $nodehash = { map { $_ => 1 } @$nodelist };
1908 my $nodename = PVE
::INotify
::nodename
();
1910 foreach_drive
($conf, sub {
1911 my ($ds, $drive) = @_;
1913 my $volid = $drive->{file
};
1916 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1918 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1919 if ($scfg->{disable
}) {
1921 } elsif (my $avail = $scfg->{nodes
}) {
1922 foreach my $node (keys %$nodehash) {
1923 delete $nodehash->{$node} if !$avail->{$node};
1925 } elsif (!$scfg->{shared
}) {
1926 foreach my $node (keys %$nodehash) {
1927 delete $nodehash->{$node} if $node ne $nodename
1939 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1943 my ($pidfile, $pid) = @_;
1945 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1949 return undef if !$line;
1950 my @param = split(/\0/, $line);
1952 my $cmd = $param[0];
1953 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1955 for (my $i = 0; $i < scalar (@param); $i++) {
1958 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1959 my $p = $param[$i+1];
1960 return 1 if $p && ($p eq $pidfile);
1969 my ($vmid, $nocheck, $node) = @_;
1971 my $filename = config_file
($vmid, $node);
1973 die "unable to find configuration file for VM $vmid - no such machine\n"
1974 if !$nocheck && ! -f
$filename;
1976 my $pidfile = pidfile_name
($vmid);
1978 if (my $fd = IO
::File-
>new("<$pidfile")) {
1983 my $mtime = $st->mtime;
1984 if ($mtime > time()) {
1985 warn "file '$filename' modified in future\n";
1988 if ($line =~ m/^(\d+)$/) {
1990 if (check_cmdline
($pidfile, $pid)) {
1991 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2003 my $vzlist = config_list
();
2005 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2007 while (defined(my $de = $fd->read)) {
2008 next if $de !~ m/^(\d+)\.pid$/;
2010 next if !defined($vzlist->{$vmid});
2011 if (my $pid = check_running
($vmid)) {
2012 $vzlist->{$vmid}->{pid
} = $pid;
2020 my ($storecfg, $conf) = @_;
2022 my $bootdisk = $conf->{bootdisk
};
2023 return undef if !$bootdisk;
2024 return undef if !valid_drivename
($bootdisk);
2026 return undef if !$conf->{$bootdisk};
2028 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2029 return undef if !defined($drive);
2031 return undef if drive_is_cdrom
($drive);
2033 my $volid = $drive->{file
};
2034 return undef if !$volid;
2036 return $drive->{size
};
2039 my $last_proc_pid_stat;
2041 # get VM status information
2042 # This must be fast and should not block ($full == false)
2043 # We only query KVM using QMP if $full == true (this can be slow)
2045 my ($opt_vmid, $full) = @_;
2049 my $storecfg = PVE
::Storage
::config
();
2051 my $list = vzlist
();
2052 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2054 my $cpucount = $cpuinfo->{cpus
} || 1;
2056 foreach my $vmid (keys %$list) {
2057 next if $opt_vmid && ($vmid ne $opt_vmid);
2059 my $cfspath = cfs_config_path
($vmid);
2060 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2063 $d->{pid
} = $list->{$vmid}->{pid
};
2065 # fixme: better status?
2066 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2068 my $size = disksize
($storecfg, $conf);
2069 if (defined($size)) {
2070 $d->{disk
} = 0; # no info available
2071 $d->{maxdisk
} = $size;
2077 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2078 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2080 $d->{name
} = $conf->{name
} || "VM $vmid";
2081 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2083 if ($conf->{balloon
}) {
2084 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2085 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2096 $d->{diskwrite
} = 0;
2098 $d->{template
} = is_template
($conf);
2103 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2104 foreach my $dev (keys %$netdev) {
2105 next if $dev !~ m/^tap([1-9]\d*)i/;
2107 my $d = $res->{$vmid};
2110 $d->{netout
} += $netdev->{$dev}->{receive
};
2111 $d->{netin
} += $netdev->{$dev}->{transmit
};
2114 my $ctime = gettimeofday
;
2116 foreach my $vmid (keys %$list) {
2118 my $d = $res->{$vmid};
2119 my $pid = $d->{pid
};
2122 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2123 next if !$pstat; # not running
2125 my $used = $pstat->{utime} + $pstat->{stime
};
2127 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2129 if ($pstat->{vsize
}) {
2130 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2133 my $old = $last_proc_pid_stat->{$pid};
2135 $last_proc_pid_stat->{$pid} = {
2143 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2145 if ($dtime > 1000) {
2146 my $dutime = $used - $old->{used
};
2148 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2149 $last_proc_pid_stat->{$pid} = {
2155 $d->{cpu
} = $old->{cpu
};
2159 return $res if !$full;
2161 my $qmpclient = PVE
::QMPClient-
>new();
2163 my $ballooncb = sub {
2164 my ($vmid, $resp) = @_;
2166 my $info = $resp->{'return'};
2167 return if !$info->{max_mem
};
2169 my $d = $res->{$vmid};
2171 # use memory assigned to VM
2172 $d->{maxmem
} = $info->{max_mem
};
2173 $d->{balloon
} = $info->{actual
};
2175 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2176 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2177 $d->{freemem
} = $info->{free_mem
};
2182 my $blockstatscb = sub {
2183 my ($vmid, $resp) = @_;
2184 my $data = $resp->{'return'} || [];
2185 my $totalrdbytes = 0;
2186 my $totalwrbytes = 0;
2187 for my $blockstat (@$data) {
2188 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2189 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2191 $res->{$vmid}->{diskread
} = $totalrdbytes;
2192 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2195 my $statuscb = sub {
2196 my ($vmid, $resp) = @_;
2198 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2199 # this fails if ballon driver is not loaded, so this must be
2200 # the last commnand (following command are aborted if this fails).
2201 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2203 my $status = 'unknown';
2204 if (!defined($status = $resp->{'return'}->{status
})) {
2205 warn "unable to get VM status\n";
2209 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2212 foreach my $vmid (keys %$list) {
2213 next if $opt_vmid && ($vmid ne $opt_vmid);
2214 next if !$res->{$vmid}->{pid
}; # not running
2215 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2218 $qmpclient->queue_execute();
2220 foreach my $vmid (keys %$list) {
2221 next if $opt_vmid && ($vmid ne $opt_vmid);
2222 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2229 my ($conf, $func) = @_;
2231 foreach my $ds (keys %$conf) {
2232 next if !valid_drivename
($ds);
2234 my $drive = parse_drive
($ds, $conf->{$ds});
2237 &$func($ds, $drive);
2242 my ($conf, $func) = @_;
2246 my $test_volid = sub {
2247 my ($volid, $is_cdrom) = @_;
2251 $volhash->{$volid} = $is_cdrom || 0;
2254 foreach_drive
($conf, sub {
2255 my ($ds, $drive) = @_;
2256 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2259 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2260 my $snap = $conf->{snapshots
}->{$snapname};
2261 &$test_volid($snap->{vmstate
}, 0);
2262 foreach_drive
($snap, sub {
2263 my ($ds, $drive) = @_;
2264 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2268 foreach my $volid (keys %$volhash) {
2269 &$func($volid, $volhash->{$volid});
2273 sub vga_conf_has_spice
{
2276 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2281 sub config_to_command
{
2282 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2285 my $globalFlags = [];
2286 my $machineFlags = [];
2292 my $kvmver = kvm_user_version
();
2293 my $vernum = 0; # unknown
2294 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2295 $vernum = $1*1000000+$2*1000;
2296 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2297 $vernum = $1*1000000+$2*1000+$3;
2300 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2302 my $have_ovz = -f
'/proc/vz/vestat';
2304 push @$cmd, '/usr/bin/kvm';
2306 push @$cmd, '-id', $vmid;
2310 my $qmpsocket = qmp_socket
($vmid);
2311 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2312 push @$cmd, '-mon', "chardev=qmp,mode=control";
2314 my $socket = vnc_socket
($vmid);
2315 push @$cmd, '-vnc', "unix:$socket,x509,password";
2317 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2319 push @$cmd, '-daemonize';
2321 $pciaddr = print_pci_addr
("piix3", $bridges);
2322 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2325 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2326 next if !$conf->{"usb$i"};
2329 # include usb device config
2330 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2332 my $vga = $conf->{vga
};
2334 my $qxlnum = vga_conf_has_spice
($vga);
2335 $vga = 'qxl' if $qxlnum;
2338 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2339 $conf->{ostype
} eq 'win7' ||
2340 $conf->{ostype
} eq 'w2k8')) {
2347 # enable absolute mouse coordinates (needed by vnc)
2349 if (defined($conf->{tablet
})) {
2350 $tablet = $conf->{tablet
};
2352 $tablet = $defaults->{tablet
};
2353 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2354 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2357 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2360 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2361 my $d = parse_hostpci
($conf->{"hostpci$i"});
2363 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2364 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2365 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar";
2369 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2370 my $d = parse_usb_device
($conf->{"usb$i"});
2372 if ($d->{vendorid
} && $d->{productid
}) {
2373 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2374 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2375 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2376 } elsif ($d->{spice
}) {
2377 # usb redir support for spice
2378 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2379 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2384 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2385 if (my $path = $conf->{"serial$i"}) {
2386 if ($path eq 'socket') {
2387 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2388 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2389 push @$devices, '-device', "isa-serial,chardev=serial$i";
2391 die "no such serial device\n" if ! -c
$path;
2392 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2393 push @$devices, '-device', "isa-serial,chardev=serial$i";
2399 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2400 if (my $path = $conf->{"parallel$i"}) {
2401 die "no such parallel device\n" if ! -c
$path;
2402 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2403 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2404 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2408 my $vmname = $conf->{name
} || "vm$vmid";
2410 push @$cmd, '-name', $vmname;
2413 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2414 $sockets = $conf->{sockets
} if $conf->{sockets
};
2416 my $cores = $conf->{cores
} || 1;
2417 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2420 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2422 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2425 push @$cmd, '-nodefaults';
2427 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2429 my $bootindex_hash = {};
2431 foreach my $o (split(//, $bootorder)) {
2432 $bootindex_hash->{$o} = $i*100;
2436 push @$cmd, '-boot', "menu=on";
2438 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2440 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2442 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2445 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2447 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2448 my $useLocaltime = $conf->{localtime};
2450 if (my $ost = $conf->{ostype
}) {
2451 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2453 if ($ost =~ m/^w/) { # windows
2454 $useLocaltime = 1 if !defined($conf->{localtime});
2456 # use time drift fix when acpi is enabled
2457 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2458 $tdf = 1 if !defined($conf->{tdf
});
2462 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2464 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2465 push @$cmd, '-no-hpet';
2466 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2467 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2470 if ($ost eq 'win7' || $ost eq 'win8') {
2471 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2475 push @$rtcFlags, 'driftfix=slew' if $tdf;
2478 push @$machineFlags, 'accel=tcg';
2480 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2483 my $machine_type = $forcemachine || $conf->{machine
};
2484 if ($machine_type) {
2485 push @$machineFlags, "type=${machine_type}";
2488 if ($conf->{startdate
}) {
2489 push @$rtcFlags, "base=$conf->{startdate}";
2490 } elsif ($useLocaltime) {
2491 push @$rtcFlags, 'base=localtime';
2494 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2495 $cpu = $conf->{cpu
} if $conf->{cpu
};
2497 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2499 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2501 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2503 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2505 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2507 push @$cmd, '-cpu', $cpu;
2509 push @$cmd, '-S' if $conf->{freeze
};
2511 # set keyboard layout
2512 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2513 push @$cmd, '-k', $kb if $kb;
2516 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2517 #push @$cmd, '-soundhw', 'es1370';
2518 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2520 if($conf->{agent
}) {
2521 my $qgasocket = qga_socket
($vmid);
2522 my $pciaddr = print_pci_addr
("qga0", $bridges);
2523 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2524 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2525 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2532 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2533 for(my $i = 1; $i < $qxlnum; $i++){
2534 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2535 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2538 # assume other OS works like Linux
2539 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2540 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2544 my $pciaddr = print_pci_addr
("spice", $bridges);
2546 $spice_port = PVE
::Tools
::next_spice_port
();
2548 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2550 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2551 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2552 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2555 # enable balloon by default, unless explicitly disabled
2556 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2557 $pciaddr = print_pci_addr
("balloon0", $bridges);
2558 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2561 if ($conf->{watchdog
}) {
2562 my $wdopts = parse_watchdog
($conf->{watchdog
});
2563 $pciaddr = print_pci_addr
("watchdog", $bridges);
2564 my $watchdog = $wdopts->{model
} || 'i6300esb';
2565 push @$devices, '-device', "$watchdog$pciaddr";
2566 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2570 my $scsicontroller = {};
2571 my $ahcicontroller = {};
2572 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2574 foreach_drive
($conf, sub {
2575 my ($ds, $drive) = @_;
2577 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2578 push @$vollist, $drive->{file
};
2581 $use_virtio = 1 if $ds =~ m/^virtio/;
2583 if (drive_is_cdrom
($drive)) {
2584 if ($bootindex_hash->{d
}) {
2585 $drive->{bootindex
} = $bootindex_hash->{d
};
2586 $bootindex_hash->{d
} += 1;
2589 if ($bootindex_hash->{c
}) {
2590 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2591 $bootindex_hash->{c
} += 1;
2595 if ($drive->{interface
} eq 'scsi') {
2597 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2598 my $controller = int($drive->{index} / $maxdev);
2599 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2600 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2601 $scsicontroller->{$controller}=1;
2604 if ($drive->{interface
} eq 'sata') {
2605 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2606 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2607 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2608 $ahcicontroller->{$controller}=1;
2611 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2612 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2615 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2617 for (my $i = 0; $i < $MAX_NETS; $i++) {
2618 next if !$conf->{"net$i"};
2619 my $d = parse_net
($conf->{"net$i"});
2622 $use_virtio = 1 if $d->{model
} eq 'virtio';
2624 if ($bootindex_hash->{n
}) {
2625 $d->{bootindex
} = $bootindex_hash->{n
};
2626 $bootindex_hash->{n
} += 1;
2629 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2630 push @$devices, '-netdev', $netdevfull;
2632 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2633 push @$devices, '-device', $netdevicefull;
2637 while (my ($k, $v) = each %$bridges) {
2638 $pciaddr = print_pci_addr
("pci.$k");
2639 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2643 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2644 # when the VM uses virtio devices.
2645 if (!$use_virtio && $have_ovz) {
2647 my $cpuunits = defined($conf->{cpuunits
}) ?
2648 $conf->{cpuunits
} : $defaults->{cpuunits
};
2650 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2652 # fixme: cpulimit is currently ignored
2653 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2657 if ($conf->{args
}) {
2658 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2662 push @$cmd, @$devices;
2663 push @$cmd, '-rtc', join(',', @$rtcFlags)
2664 if scalar(@$rtcFlags);
2665 push @$cmd, '-machine', join(',', @$machineFlags)
2666 if scalar(@$machineFlags);
2667 push @$cmd, '-global', join(',', @$globalFlags)
2668 if scalar(@$globalFlags);
2670 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2675 return "${var_run_tmpdir}/$vmid.vnc";
2681 my $res = vm_mon_cmd
($vmid, 'query-spice');
2683 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2688 return "${var_run_tmpdir}/$vmid.qmp";
2693 return "${var_run_tmpdir}/$vmid.qga";
2698 return "${var_run_tmpdir}/$vmid.pid";
2701 sub vm_devices_list
{
2704 my $res = vm_mon_cmd
($vmid, 'query-pci');
2707 foreach my $pcibus (@$res) {
2708 foreach my $device (@{$pcibus->{devices
}}) {
2709 next if !$device->{'qdev_id'};
2710 $devices->{$device->{'qdev_id'}} = $device;
2718 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2720 return 1 if !check_running
($vmid);
2722 if ($deviceid eq 'tablet') {
2723 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2724 qemu_deviceadd
($vmid, $devicefull);
2728 return 1 if !$conf->{hotplug
};
2730 my $devices_list = vm_devices_list
($vmid);
2731 return 1 if defined($devices_list->{$deviceid});
2733 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2735 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2736 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2737 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2738 qemu_deviceadd
($vmid, $devicefull);
2739 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2740 qemu_drivedel
($vmid, $deviceid);
2745 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2746 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2747 my $pciaddr = print_pci_addr
($deviceid);
2748 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2749 qemu_deviceadd
($vmid, $devicefull);
2750 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2753 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2754 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2755 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2756 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2757 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2758 if(!qemu_deviceadd
($vmid, $devicefull)) {
2759 qemu_drivedel
($vmid, $deviceid);
2764 if ($deviceid =~ m/^(net)(\d+)$/) {
2765 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2766 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2767 qemu_deviceadd
($vmid, $netdevicefull);
2768 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2769 qemu_netdevdel
($vmid, $deviceid);
2774 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2776 my $pciaddr = print_pci_addr
($deviceid);
2777 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2778 qemu_deviceadd
($vmid, $devicefull);
2779 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2785 sub vm_deviceunplug
{
2786 my ($vmid, $conf, $deviceid) = @_;
2788 return 1 if !check_running
($vmid);
2790 if ($deviceid eq 'tablet') {
2791 qemu_devicedel
($vmid, $deviceid);
2795 return 1 if !$conf->{hotplug
};
2797 my $devices_list = vm_devices_list
($vmid);
2798 return 1 if !defined($devices_list->{$deviceid});
2800 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2802 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2803 qemu_devicedel
($vmid, $deviceid);
2804 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2805 return undef if !qemu_drivedel
($vmid, $deviceid);
2808 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2809 return undef if !qemu_devicedel
($vmid, $deviceid);
2812 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2813 return undef if !qemu_devicedel
($vmid, $deviceid);
2814 return undef if !qemu_drivedel
($vmid, $deviceid);
2817 if ($deviceid =~ m/^(net)(\d+)$/) {
2818 qemu_devicedel
($vmid, $deviceid);
2819 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2820 return undef if !qemu_netdevdel
($vmid, $deviceid);
2826 sub qemu_deviceadd
{
2827 my ($vmid, $devicefull) = @_;
2829 $devicefull = "driver=".$devicefull;
2830 my %options = split(/[=,]/, $devicefull);
2832 vm_mon_cmd
($vmid, "device_add" , %options);
2836 sub qemu_devicedel
{
2837 my($vmid, $deviceid) = @_;
2838 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2843 my($storecfg, $vmid, $device) = @_;
2845 my $drive = print_drive_full
($storecfg, $vmid, $device);
2846 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2847 # If the command succeeds qemu prints: "OK"
2848 if ($ret !~ m/OK/s) {
2849 syslog
("err", "adding drive failed: $ret");
2856 my($vmid, $deviceid) = @_;
2858 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2860 if ($ret =~ m/Device \'.*?\' not found/s) {
2861 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2863 elsif ($ret ne "") {
2864 syslog
("err", "deleting drive $deviceid failed : $ret");
2870 sub qemu_deviceaddverify
{
2871 my ($vmid,$deviceid) = @_;
2873 for (my $i = 0; $i <= 5; $i++) {
2874 my $devices_list = vm_devices_list
($vmid);
2875 return 1 if defined($devices_list->{$deviceid});
2878 syslog
("err", "error on hotplug device $deviceid");
2883 sub qemu_devicedelverify
{
2884 my ($vmid,$deviceid) = @_;
2886 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2887 for (my $i = 0; $i <= 5; $i++) {
2888 my $devices_list = vm_devices_list
($vmid);
2889 return 1 if !defined($devices_list->{$deviceid});
2892 syslog
("err", "error on hot-unplugging device $deviceid");
2896 sub qemu_findorcreatescsihw
{
2897 my ($storecfg, $conf, $vmid, $device) = @_;
2899 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2900 my $controller = int($device->{index} / $maxdev);
2901 my $scsihwid="scsihw$controller";
2902 my $devices_list = vm_devices_list
($vmid);
2904 if(!defined($devices_list->{$scsihwid})) {
2905 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2910 sub qemu_bridgeadd
{
2911 my ($storecfg, $conf, $vmid, $device) = @_;
2914 my $bridgeid = undef;
2915 print_pci_addr
($device, $bridges);
2917 while (my ($k, $v) = each %$bridges) {
2920 return if !$bridgeid || $bridgeid < 1;
2921 my $bridge = "pci.$bridgeid";
2922 my $devices_list = vm_devices_list
($vmid);
2924 if(!defined($devices_list->{$bridge})) {
2925 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2930 sub qemu_netdevadd
{
2931 my ($vmid, $conf, $device, $deviceid) = @_;
2933 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2934 my %options = split(/[=,]/, $netdev);
2936 vm_mon_cmd
($vmid, "netdev_add", %options);
2940 sub qemu_netdevdel
{
2941 my ($vmid, $deviceid) = @_;
2943 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2947 sub qemu_cpu_hotplug
{
2948 my ($vmid, $conf, $cores) = @_;
2950 die "new cores config is not defined" if !$cores;
2951 die "you can't add more cores than maxcpus"
2952 if $conf->{maxcpus
} && ($cores > $conf->{maxcpus
});
2953 return if !check_running
($vmid);
2955 my $currentcores = $conf->{cores
} if $conf->{cores
};
2956 die "current cores is not defined" if !$currentcores;
2957 die "maxcpus is not defined" if !$conf->{maxcpus
};
2958 raise_param_exc
({ 'cores' => "online cpu unplug is not yet possible" })
2959 if($cores < $currentcores);
2961 my $currentrunningcores = vm_mon_cmd
($vmid, "query-cpus");
2962 raise_param_exc
({ 'cores' => "cores number if running vm is different than configuration" })
2963 if scalar (@{$currentrunningcores}) != $currentcores;
2965 for(my $i = $currentcores; $i < $cores; $i++) {
2966 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
2970 sub qemu_block_set_io_throttle
{
2971 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2973 return if !check_running
($vmid) ;
2975 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));
2979 # old code, only used to shutdown old VM after update
2981 my ($fh, $timeout) = @_;
2983 my $sel = new IO
::Select
;
2990 while (scalar (@ready = $sel->can_read($timeout))) {
2992 if ($count = $fh->sysread($buf, 8192)) {
2993 if ($buf =~ /^(.*)\(qemu\) $/s) {
3000 if (!defined($count)) {
3007 die "monitor read timeout\n" if !scalar(@ready);
3012 # old code, only used to shutdown old VM after update
3013 sub vm_monitor_command
{
3014 my ($vmid, $cmdstr, $nocheck) = @_;
3019 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3021 my $sname = "${var_run_tmpdir}/$vmid.mon";
3023 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3024 die "unable to connect to VM $vmid socket - $!\n";
3028 # hack: migrate sometime blocks the monitor (when migrate_downtime
3030 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3031 $timeout = 60*60; # 1 hour
3035 my $data = __read_avail
($sock, $timeout);
3037 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3038 die "got unexpected qemu monitor banner\n";
3041 my $sel = new IO
::Select
;
3044 if (!scalar(my @ready = $sel->can_write($timeout))) {
3045 die "monitor write error - timeout";
3048 my $fullcmd = "$cmdstr\r";
3050 # syslog('info', "VM $vmid monitor command: $cmdstr");
3053 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3054 die "monitor write error - $!";
3057 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3061 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3062 $timeout = 60*60; # 1 hour
3063 } elsif ($cmdstr =~ m/^(eject|change)/) {
3064 $timeout = 60; # note: cdrom mount command is slow
3066 if ($res = __read_avail
($sock, $timeout)) {
3068 my @lines = split("\r?\n", $res);
3070 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3072 $res = join("\n", @lines);
3080 syslog
("err", "VM $vmid monitor command failed - $err");
3087 sub qemu_block_resize
{
3088 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3090 my $running = check_running
($vmid);
3092 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3094 return if !$running;
3096 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3100 sub qemu_volume_snapshot
{
3101 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3103 my $running = check_running
($vmid);
3105 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3107 return if !$running;
3109 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3113 sub qemu_volume_snapshot_delete
{
3114 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3116 my $running = check_running
($vmid);
3118 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3120 return if !$running;
3122 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3128 #need to impplement call to qemu-ga
3131 sub qga_unfreezefs
{
3134 #need to impplement call to qemu-ga
3137 sub set_migration_caps
{
3143 "auto-converge" => 1,
3145 "x-rdma-pin-all" => 0,
3149 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3151 for my $supported_capability (@$supported_capabilities) {
3152 if ($enabled_cap->{$supported_capability->{capability
}} eq 1) {
3154 capability
=> $supported_capability->{capability
},
3155 state => JSON
::true
,
3160 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3164 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3166 lock_config
($vmid, sub {
3167 my $conf = load_config
($vmid, $migratedfrom);
3169 die "you can't start a vm if it's a template\n" if is_template
($conf);
3171 check_lock
($conf) if !$skiplock;
3173 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3175 my $defaults = load_defaults
();
3177 # set environment variable useful inside network script
3178 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3180 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3182 my $migrate_port = 0;
3185 if ($statefile eq 'tcp') {
3186 my $localip = "localhost";
3187 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3188 if ($datacenterconf->{migration_unsecure
}) {
3189 my $nodename = PVE
::INotify
::nodename
();
3190 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3192 $migrate_port = PVE
::Tools
::next_migrate_port
();
3193 $migrate_uri = "tcp:${localip}:${migrate_port}";
3194 push @$cmd, '-incoming', $migrate_uri;
3197 push @$cmd, '-loadstate', $statefile;
3204 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3205 my $d = parse_hostpci
($conf->{"hostpci$i"});
3207 my $info = pci_device_info
("0000:$d->{pciid}");
3208 die "IOMMU not present\n" if !check_iommu_support
();
3209 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3210 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3211 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3214 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3216 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3219 die "start failed: $err" if $err;
3221 print "migration listens on $migrate_uri\n" if $migrate_uri;
3223 if ($statefile && $statefile ne 'tcp') {
3224 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3228 if ($migratedfrom) {
3231 PVE
::QemuServer
::set_migration_caps
($vmid);
3236 print "spice listens on port $spice_port\n";
3237 if ($spice_ticket) {
3238 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3239 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3245 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3246 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3247 if $conf->{balloon
};
3248 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3249 path
=> "machine/peripheral/balloon0",
3250 property
=> "guest-stats-polling-interval",
3258 my ($vmid, $execute, %params) = @_;
3260 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3261 vm_qmp_command
($vmid, $cmd);
3264 sub vm_mon_cmd_nocheck
{
3265 my ($vmid, $execute, %params) = @_;
3267 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3268 vm_qmp_command
($vmid, $cmd, 1);
3271 sub vm_qmp_command
{
3272 my ($vmid, $cmd, $nocheck) = @_;
3277 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3278 $timeout = $cmd->{arguments
}->{timeout
};
3279 delete $cmd->{arguments
}->{timeout
};
3283 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3284 my $sname = qmp_socket
($vmid);
3286 my $qmpclient = PVE
::QMPClient-
>new();
3288 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3289 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3290 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3291 if scalar(%{$cmd->{arguments
}});
3292 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3294 die "unable to open monitor socket\n";
3298 syslog
("err", "VM $vmid qmp command failed - $err");
3305 sub vm_human_monitor_command
{
3306 my ($vmid, $cmdline) = @_;
3311 execute
=> 'human-monitor-command',
3312 arguments
=> { 'command-line' => $cmdline},
3315 return vm_qmp_command
($vmid, $cmd);
3318 sub vm_commandline
{
3319 my ($storecfg, $vmid) = @_;
3321 my $conf = load_config
($vmid);
3323 my $defaults = load_defaults
();
3325 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3327 return join(' ', @$cmd);
3331 my ($vmid, $skiplock) = @_;
3333 lock_config
($vmid, sub {
3335 my $conf = load_config
($vmid);
3337 check_lock
($conf) if !$skiplock;
3339 vm_mon_cmd
($vmid, "system_reset");
3343 sub get_vm_volumes
{
3347 foreach_volid
($conf, sub {
3348 my ($volid, $is_cdrom) = @_;
3350 return if $volid =~ m
|^/|;
3352 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3355 push @$vollist, $volid;
3361 sub vm_stop_cleanup
{
3362 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3365 fairsched_rmnod
($vmid); # try to destroy group
3368 my $vollist = get_vm_volumes
($conf);
3369 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3372 foreach my $ext (qw(mon qmp pid vnc qga)) {
3373 unlink "/var/run/qemu-server/${vmid}.$ext";
3376 warn $@ if $@; # avoid errors - just warn
3379 # Note: use $nockeck to skip tests if VM configuration file exists.
3380 # We need that when migration VMs to other nodes (files already moved)
3381 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3383 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3385 $force = 1 if !defined($force) && !$shutdown;
3388 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3389 kill 15, $pid if $pid;
3390 my $conf = load_config
($vmid, $migratedfrom);
3391 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3395 lock_config
($vmid, sub {
3397 my $pid = check_running
($vmid, $nocheck);
3402 $conf = load_config
($vmid);
3403 check_lock
($conf) if !$skiplock;
3404 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3405 my $opts = parse_startup
($conf->{startup
});
3406 $timeout = $opts->{down
} if $opts->{down
};
3410 $timeout = 60 if !defined($timeout);
3414 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3417 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3424 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3429 if ($count >= $timeout) {
3431 warn "VM still running - terminating now with SIGTERM\n";
3434 die "VM quit/powerdown failed - got timeout\n";
3437 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3442 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3445 die "VM quit/powerdown failed\n";
3453 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3458 if ($count >= $timeout) {
3459 warn "VM still running - terminating now with SIGKILL\n";
3464 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3469 my ($vmid, $skiplock) = @_;
3471 lock_config
($vmid, sub {
3473 my $conf = load_config
($vmid);
3475 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3477 vm_mon_cmd
($vmid, "stop");
3482 my ($vmid, $skiplock) = @_;
3484 lock_config
($vmid, sub {
3486 my $conf = load_config
($vmid);
3488 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3490 vm_mon_cmd
($vmid, "cont");
3495 my ($vmid, $skiplock, $key) = @_;
3497 lock_config
($vmid, sub {
3499 my $conf = load_config
($vmid);
3501 # there is no qmp command, so we use the human monitor command
3502 vm_human_monitor_command
($vmid, "sendkey $key");
3507 my ($storecfg, $vmid, $skiplock) = @_;
3509 lock_config
($vmid, sub {
3511 my $conf = load_config
($vmid);
3513 check_lock
($conf) if !$skiplock;
3515 if (!check_running
($vmid)) {
3516 fairsched_rmnod
($vmid); # try to destroy group
3517 destroy_vm
($storecfg, $vmid);
3519 die "VM $vmid is running - destroy failed\n";
3527 my ($filename, $buf) = @_;
3529 my $fh = IO
::File-
>new($filename, "w");
3530 return undef if !$fh;
3532 my $res = print $fh $buf;
3539 sub pci_device_info
{
3544 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3545 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3547 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3548 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3550 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3551 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3553 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3554 return undef if !defined($product) || $product !~ s/^0x//;
3559 product
=> $product,
3565 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3574 my $name = $dev->{name
};
3576 my $fn = "$pcisysfs/devices/$name/reset";
3578 return file_write
($fn, "1");
3581 sub pci_dev_bind_to_stub
{
3584 my $name = $dev->{name
};
3586 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3587 return 1 if -d
$testdir;
3589 my $data = "$dev->{vendor} $dev->{product}";
3590 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3592 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3593 if (!file_write
($fn, $name)) {
3594 return undef if -f
$fn;
3597 $fn = "$pcisysfs/drivers/pci-stub/bind";
3598 if (! -d
$testdir) {
3599 return undef if !file_write
($fn, $name);
3605 sub print_pci_addr
{
3606 my ($id, $bridges) = @_;
3610 piix3
=> { bus
=> 0, addr
=> 1 },
3611 #addr2 : first videocard
3612 balloon0
=> { bus
=> 0, addr
=> 3 },
3613 watchdog
=> { bus
=> 0, addr
=> 4 },
3614 scsihw0
=> { bus
=> 0, addr
=> 5 },
3615 scsihw1
=> { bus
=> 0, addr
=> 6 },
3616 ahci0
=> { bus
=> 0, addr
=> 7 },
3617 qga0
=> { bus
=> 0, addr
=> 8 },
3618 spice
=> { bus
=> 0, addr
=> 9 },
3619 virtio0
=> { bus
=> 0, addr
=> 10 },
3620 virtio1
=> { bus
=> 0, addr
=> 11 },
3621 virtio2
=> { bus
=> 0, addr
=> 12 },
3622 virtio3
=> { bus
=> 0, addr
=> 13 },
3623 virtio4
=> { bus
=> 0, addr
=> 14 },
3624 virtio5
=> { bus
=> 0, addr
=> 15 },
3625 hostpci0
=> { bus
=> 0, addr
=> 16 },
3626 hostpci1
=> { bus
=> 0, addr
=> 17 },
3627 net0
=> { bus
=> 0, addr
=> 18 },
3628 net1
=> { bus
=> 0, addr
=> 19 },
3629 net2
=> { bus
=> 0, addr
=> 20 },
3630 net3
=> { bus
=> 0, addr
=> 21 },
3631 net4
=> { bus
=> 0, addr
=> 22 },
3632 net5
=> { bus
=> 0, addr
=> 23 },
3633 vga1
=> { bus
=> 0, addr
=> 24 },
3634 vga2
=> { bus
=> 0, addr
=> 25 },
3635 vga3
=> { bus
=> 0, addr
=> 26 },
3636 #addr29 : usb-host (pve-usb.cfg)
3637 'pci.1' => { bus
=> 0, addr
=> 30 },
3638 'pci.2' => { bus
=> 0, addr
=> 31 },
3639 'net6' => { bus
=> 1, addr
=> 1 },
3640 'net7' => { bus
=> 1, addr
=> 2 },
3641 'net8' => { bus
=> 1, addr
=> 3 },
3642 'net9' => { bus
=> 1, addr
=> 4 },
3643 'net10' => { bus
=> 1, addr
=> 5 },
3644 'net11' => { bus
=> 1, addr
=> 6 },
3645 'net12' => { bus
=> 1, addr
=> 7 },
3646 'net13' => { bus
=> 1, addr
=> 8 },
3647 'net14' => { bus
=> 1, addr
=> 9 },
3648 'net15' => { bus
=> 1, addr
=> 10 },
3649 'net16' => { bus
=> 1, addr
=> 11 },
3650 'net17' => { bus
=> 1, addr
=> 12 },
3651 'net18' => { bus
=> 1, addr
=> 13 },
3652 'net19' => { bus
=> 1, addr
=> 14 },
3653 'net20' => { bus
=> 1, addr
=> 15 },
3654 'net21' => { bus
=> 1, addr
=> 16 },
3655 'net22' => { bus
=> 1, addr
=> 17 },
3656 'net23' => { bus
=> 1, addr
=> 18 },
3657 'net24' => { bus
=> 1, addr
=> 19 },
3658 'net25' => { bus
=> 1, addr
=> 20 },
3659 'net26' => { bus
=> 1, addr
=> 21 },
3660 'net27' => { bus
=> 1, addr
=> 22 },
3661 'net28' => { bus
=> 1, addr
=> 23 },
3662 'net29' => { bus
=> 1, addr
=> 24 },
3663 'net30' => { bus
=> 1, addr
=> 25 },
3664 'net31' => { bus
=> 1, addr
=> 26 },
3665 'virtio6' => { bus
=> 2, addr
=> 1 },
3666 'virtio7' => { bus
=> 2, addr
=> 2 },
3667 'virtio8' => { bus
=> 2, addr
=> 3 },
3668 'virtio9' => { bus
=> 2, addr
=> 4 },
3669 'virtio10' => { bus
=> 2, addr
=> 5 },
3670 'virtio11' => { bus
=> 2, addr
=> 6 },
3671 'virtio12' => { bus
=> 2, addr
=> 7 },
3672 'virtio13' => { bus
=> 2, addr
=> 8 },
3673 'virtio14' => { bus
=> 2, addr
=> 9 },
3674 'virtio15' => { bus
=> 2, addr
=> 10 },
3677 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3678 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3679 my $bus = $devices->{$id}->{bus
};
3680 $res = ",bus=pci.$bus,addr=$addr";
3681 $bridges->{$bus} = 1 if $bridges;
3687 # vzdump restore implementaion
3689 sub tar_archive_read_firstfile
{
3690 my $archive = shift;
3692 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3694 # try to detect archive type first
3695 my $pid = open (TMP
, "tar tf '$archive'|") ||
3696 die "unable to open file '$archive'\n";
3697 my $firstfile = <TMP
>;
3701 die "ERROR: archive contaions no data\n" if !$firstfile;
3707 sub tar_restore_cleanup
{
3708 my ($storecfg, $statfile) = @_;
3710 print STDERR
"starting cleanup\n";
3712 if (my $fd = IO
::File-
>new($statfile, "r")) {
3713 while (defined(my $line = <$fd>)) {
3714 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3717 if ($volid =~ m
|^/|) {
3718 unlink $volid || die 'unlink failed\n';
3720 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3722 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3724 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3726 print STDERR
"unable to parse line in statfile - $line";
3733 sub restore_archive
{
3734 my ($archive, $vmid, $user, $opts) = @_;
3736 my $format = $opts->{format
};
3739 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3740 $format = 'tar' if !$format;
3742 } elsif ($archive =~ m/\.tar$/) {
3743 $format = 'tar' if !$format;
3744 } elsif ($archive =~ m/.tar.lzo$/) {
3745 $format = 'tar' if !$format;
3747 } elsif ($archive =~ m/\.vma$/) {
3748 $format = 'vma' if !$format;
3749 } elsif ($archive =~ m/\.vma\.gz$/) {
3750 $format = 'vma' if !$format;
3752 } elsif ($archive =~ m/\.vma\.lzo$/) {
3753 $format = 'vma' if !$format;
3756 $format = 'vma' if !$format; # default
3759 # try to detect archive format
3760 if ($format eq 'tar') {
3761 return restore_tar_archive
($archive, $vmid, $user, $opts);
3763 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3767 sub restore_update_config_line
{
3768 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3770 return if $line =~ m/^\#qmdump\#/;
3771 return if $line =~ m/^\#vzdump\#/;
3772 return if $line =~ m/^lock:/;
3773 return if $line =~ m/^unused\d+:/;
3774 return if $line =~ m/^parent:/;
3775 return if $line =~ m/^template:/; # restored VM is never a template
3777 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3778 # try to convert old 1.X settings
3779 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3780 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3781 my ($model, $macaddr) = split(/\=/, $devconfig);
3782 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3785 bridge
=> "vmbr$ind",
3786 macaddr
=> $macaddr,
3788 my $netstr = print_net
($net);
3790 print $outfd "net$cookie->{netcount}: $netstr\n";
3791 $cookie->{netcount
}++;
3793 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3794 my ($id, $netstr) = ($1, $2);
3795 my $net = parse_net
($netstr);
3796 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3797 $netstr = print_net
($net);
3798 print $outfd "$id: $netstr\n";
3799 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3802 if ($line =~ m/backup=no/) {
3803 print $outfd "#$line";
3804 } elsif ($virtdev && $map->{$virtdev}) {
3805 my $di = parse_drive
($virtdev, $value);
3806 delete $di->{format
}; # format can change on restore
3807 $di->{file
} = $map->{$virtdev};
3808 $value = print_drive
($vmid, $di);
3809 print $outfd "$virtdev: $value\n";
3819 my ($cfg, $vmid) = @_;
3821 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3823 my $volid_hash = {};
3824 foreach my $storeid (keys %$info) {
3825 foreach my $item (@{$info->{$storeid}}) {
3826 next if !($item->{volid
} && $item->{size
});
3827 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3828 $volid_hash->{$item->{volid
}} = $item;
3835 sub get_used_paths
{
3836 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3840 my $scan_config = sub {
3841 my ($cref, $snapname) = @_;
3843 foreach my $key (keys %$cref) {
3844 my $value = $cref->{$key};
3845 if (valid_drivename
($key)) {
3846 next if $skip_drive && $key eq $skip_drive;
3847 my $drive = parse_drive
($key, $value);
3848 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3849 if ($drive->{file
} =~ m!^/!) {
3850 $used_path->{$drive->{file
}}++; # = 1;
3852 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3854 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3856 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3857 $used_path->{$path}++; # = 1;
3863 &$scan_config($conf);
3867 if ($scan_snapshots) {
3868 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3869 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3876 sub update_disksize
{
3877 my ($vmid, $conf, $volid_hash) = @_;
3883 # Note: it is allowed to define multiple storages with same path (alias), so
3884 # we need to check both 'volid' and real 'path' (two different volid can point
3885 # to the same path).
3890 foreach my $opt (keys %$conf) {
3891 if (valid_drivename
($opt)) {
3892 my $drive = parse_drive
($opt, $conf->{$opt});
3893 my $volid = $drive->{file
};
3896 $used->{$volid} = 1;
3897 if ($volid_hash->{$volid} &&
3898 (my $path = $volid_hash->{$volid}->{path
})) {
3899 $usedpath->{$path} = 1;
3902 next if drive_is_cdrom
($drive);
3903 next if !$volid_hash->{$volid};
3905 $drive->{size
} = $volid_hash->{$volid}->{size
};
3906 my $new = print_drive
($vmid, $drive);
3907 if ($new ne $conf->{$opt}) {
3909 $conf->{$opt} = $new;
3914 # remove 'unusedX' entry if volume is used
3915 foreach my $opt (keys %$conf) {
3916 next if $opt !~ m/^unused\d+$/;
3917 my $volid = $conf->{$opt};
3918 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3919 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3921 delete $conf->{$opt};
3925 foreach my $volid (sort keys %$volid_hash) {
3926 next if $volid =~ m/vm-$vmid-state-/;
3927 next if $used->{$volid};
3928 my $path = $volid_hash->{$volid}->{path
};
3929 next if !$path; # just to be sure
3930 next if $usedpath->{$path};
3932 add_unused_volume
($conf, $volid);
3933 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3940 my ($vmid, $nolock) = @_;
3942 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3944 my $volid_hash = scan_volids
($cfg, $vmid);
3946 my $updatefn = sub {
3949 my $conf = load_config
($vmid);
3954 foreach my $volid (keys %$volid_hash) {
3955 my $info = $volid_hash->{$volid};
3956 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3959 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3961 update_config_nolock
($vmid, $conf, 1) if $changes;
3964 if (defined($vmid)) {
3968 lock_config
($vmid, $updatefn, $vmid);
3971 my $vmlist = config_list
();
3972 foreach my $vmid (keys %$vmlist) {
3976 lock_config
($vmid, $updatefn, $vmid);
3982 sub restore_vma_archive
{
3983 my ($archive, $vmid, $user, $opts, $comp) = @_;
3985 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3986 my $readfrom = $archive;
3991 my $qarchive = PVE
::Tools
::shellquote
($archive);
3992 if ($comp eq 'gzip') {
3993 $uncomp = "zcat $qarchive|";
3994 } elsif ($comp eq 'lzop') {
3995 $uncomp = "lzop -d -c $qarchive|";
3997 die "unknown compression method '$comp'\n";
4002 my $tmpdir = "/var/tmp/vzdumptmp$$";
4005 # disable interrupts (always do cleanups)
4006 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4007 warn "got interrupt - ignored\n";
4010 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4011 POSIX
::mkfifo
($mapfifo, 0600);
4014 my $openfifo = sub {
4015 open($fifofh, '>', $mapfifo) || die $!;
4018 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4025 my $rpcenv = PVE
::RPCEnvironment
::get
();
4027 my $conffile = config_file
($vmid);
4028 my $tmpfn = "$conffile.$$.tmp";
4030 # Note: $oldconf is undef if VM does not exists
4031 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4033 my $print_devmap = sub {
4034 my $virtdev_hash = {};
4036 my $cfgfn = "$tmpdir/qemu-server.conf";
4038 # we can read the config - that is already extracted
4039 my $fh = IO
::File-
>new($cfgfn, "r") ||
4040 "unable to read qemu-server.conf - $!\n";
4042 while (defined(my $line = <$fh>)) {
4043 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4044 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4045 die "archive does not contain data for drive '$virtdev'\n"
4046 if !$devinfo->{$devname};
4047 if (defined($opts->{storage
})) {
4048 $storeid = $opts->{storage
} || 'local';
4049 } elsif (!$storeid) {
4052 $format = 'raw' if !$format;
4053 $devinfo->{$devname}->{devname
} = $devname;
4054 $devinfo->{$devname}->{virtdev
} = $virtdev;
4055 $devinfo->{$devname}->{format
} = $format;
4056 $devinfo->{$devname}->{storeid
} = $storeid;
4058 # check permission on storage
4059 my $pool = $opts->{pool
}; # todo: do we need that?
4060 if ($user ne 'root@pam') {
4061 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4064 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4068 foreach my $devname (keys %$devinfo) {
4069 die "found no device mapping information for device '$devname'\n"
4070 if !$devinfo->{$devname}->{virtdev
};
4073 my $cfg = cfs_read_file
('storage.cfg');
4075 # create empty/temp config
4077 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4078 foreach_drive
($oldconf, sub {
4079 my ($ds, $drive) = @_;
4081 return if drive_is_cdrom
($drive);
4083 my $volid = $drive->{file
};
4085 return if !$volid || $volid =~ m
|^/|;
4087 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4088 return if !$path || !$owner || ($owner != $vmid);
4090 # Note: only delete disk we want to restore
4091 # other volumes will become unused
4092 if ($virtdev_hash->{$ds}) {
4093 PVE
::Storage
::vdisk_free
($cfg, $volid);
4099 foreach my $virtdev (sort keys %$virtdev_hash) {
4100 my $d = $virtdev_hash->{$virtdev};
4101 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4102 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4104 # test if requested format is supported
4105 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4106 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4107 $d->{format
} = $defFormat if !$supported;
4109 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4110 $d->{format
}, undef, $alloc_size);
4111 print STDERR
"new volume ID is '$volid'\n";
4112 $d->{volid
} = $volid;
4113 my $path = PVE
::Storage
::path
($cfg, $volid);
4115 my $write_zeros = 1;
4116 # fixme: what other storages types initialize volumes with zero?
4117 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4118 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4122 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4124 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4125 $map->{$virtdev} = $volid;
4128 $fh->seek(0, 0) || die "seek failed - $!\n";
4130 my $outfd = new IO
::File
($tmpfn, "w") ||
4131 die "unable to write config for VM $vmid\n";
4133 my $cookie = { netcount
=> 0 };
4134 while (defined(my $line = <$fh>)) {
4135 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4144 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4145 die "interrupted by signal\n";
4147 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4149 $oldtimeout = alarm($timeout);
4156 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4157 my ($dev_id, $size, $devname) = ($1, $2, $3);
4158 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4159 } elsif ($line =~ m/^CTIME: /) {
4161 print $fifofh "done\n";
4162 my $tmp = $oldtimeout || 0;
4163 $oldtimeout = undef;
4169 print "restore vma archive: $cmd\n";
4170 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4174 alarm($oldtimeout) if $oldtimeout;
4182 my $cfg = cfs_read_file
('storage.cfg');
4183 foreach my $devname (keys %$devinfo) {
4184 my $volid = $devinfo->{$devname}->{volid
};
4187 if ($volid =~ m
|^/|) {
4188 unlink $volid || die 'unlink failed\n';
4190 PVE
::Storage
::vdisk_free
($cfg, $volid);
4192 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4194 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4201 rename($tmpfn, $conffile) ||
4202 die "unable to commit configuration file '$conffile'\n";
4204 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4206 eval { rescan
($vmid, 1); };
4210 sub restore_tar_archive
{
4211 my ($archive, $vmid, $user, $opts) = @_;
4213 if ($archive ne '-') {
4214 my $firstfile = tar_archive_read_firstfile
($archive);
4215 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4216 if $firstfile ne 'qemu-server.conf';
4219 my $storecfg = cfs_read_file
('storage.cfg');
4221 # destroy existing data - keep empty config
4222 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4223 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4225 my $tocmd = "/usr/lib/qemu-server/qmextract";
4227 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4228 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4229 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4230 $tocmd .= ' --info' if $opts->{info
};
4232 # tar option "xf" does not autodetect compression when read from STDIN,
4233 # so we pipe to zcat
4234 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4235 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4237 my $tmpdir = "/var/tmp/vzdumptmp$$";
4240 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4241 local $ENV{VZDUMP_VMID
} = $vmid;
4242 local $ENV{VZDUMP_USER
} = $user;
4244 my $conffile = config_file
($vmid);
4245 my $tmpfn = "$conffile.$$.tmp";
4247 # disable interrupts (always do cleanups)
4248 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4249 print STDERR
"got interrupt - ignored\n";
4254 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4255 die "interrupted by signal\n";
4258 if ($archive eq '-') {
4259 print "extracting archive from STDIN\n";
4260 run_command
($cmd, input
=> "<&STDIN");
4262 print "extracting archive '$archive'\n";
4266 return if $opts->{info
};
4270 my $statfile = "$tmpdir/qmrestore.stat";
4271 if (my $fd = IO
::File-
>new($statfile, "r")) {
4272 while (defined (my $line = <$fd>)) {
4273 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4274 $map->{$1} = $2 if $1;
4276 print STDERR
"unable to parse line in statfile - $line\n";
4282 my $confsrc = "$tmpdir/qemu-server.conf";
4284 my $srcfd = new IO
::File
($confsrc, "r") ||
4285 die "unable to open file '$confsrc'\n";
4287 my $outfd = new IO
::File
($tmpfn, "w") ||
4288 die "unable to write config for VM $vmid\n";
4290 my $cookie = { netcount
=> 0 };
4291 while (defined (my $line = <$srcfd>)) {
4292 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4304 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4311 rename $tmpfn, $conffile ||
4312 die "unable to commit configuration file '$conffile'\n";
4314 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4316 eval { rescan
($vmid, 1); };
4321 # Internal snapshots
4323 # NOTE: Snapshot create/delete involves several non-atomic
4324 # action, and can take a long time.
4325 # So we try to avoid locking the file and use 'lock' variable
4326 # inside the config file instead.
4328 my $snapshot_copy_config = sub {
4329 my ($source, $dest) = @_;
4331 foreach my $k (keys %$source) {
4332 next if $k eq 'snapshots';
4333 next if $k eq 'snapstate';
4334 next if $k eq 'snaptime';
4335 next if $k eq 'vmstate';
4336 next if $k eq 'lock';
4337 next if $k eq 'digest';
4338 next if $k eq 'description';
4339 next if $k =~ m/^unused\d+$/;
4341 $dest->{$k} = $source->{$k};
4345 my $snapshot_apply_config = sub {
4346 my ($conf, $snap) = @_;
4348 # copy snapshot list
4350 snapshots
=> $conf->{snapshots
},
4353 # keep description and list of unused disks
4354 foreach my $k (keys %$conf) {
4355 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4356 $newconf->{$k} = $conf->{$k};
4359 &$snapshot_copy_config($snap, $newconf);
4364 sub foreach_writable_storage
{
4365 my ($conf, $func) = @_;
4369 foreach my $ds (keys %$conf) {
4370 next if !valid_drivename
($ds);
4372 my $drive = parse_drive
($ds, $conf->{$ds});
4374 next if drive_is_cdrom
($drive);
4376 my $volid = $drive->{file
};
4378 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4379 $sidhash->{$sid} = $sid if $sid;
4382 foreach my $sid (sort keys %$sidhash) {
4387 my $alloc_vmstate_volid = sub {
4388 my ($storecfg, $vmid, $conf, $snapname) = @_;
4390 # Note: we try to be smart when selecting a $target storage
4394 # search shared storage first
4395 foreach_writable_storage
($conf, sub {
4397 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4398 return if !$scfg->{shared
};
4400 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4404 # now search local storage
4405 foreach_writable_storage
($conf, sub {
4407 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4408 return if $scfg->{shared
};
4410 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4414 $target = 'local' if !$target;
4416 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4417 # we abort live save after $conf->{memory}, so we need at max twice that space
4418 my $size = $conf->{memory
}*2 + $driver_state_size;
4420 my $name = "vm-$vmid-state-$snapname";
4421 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4422 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4423 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4428 my $snapshot_prepare = sub {
4429 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4433 my $updatefn = sub {
4435 my $conf = load_config
($vmid);
4437 die "you can't take a snapshot if it's a template\n"
4438 if is_template
($conf);
4442 $conf->{lock} = 'snapshot';
4444 die "snapshot name '$snapname' already used\n"
4445 if defined($conf->{snapshots
}->{$snapname});
4447 my $storecfg = PVE
::Storage
::config
();
4448 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4450 $snap = $conf->{snapshots
}->{$snapname} = {};
4452 if ($save_vmstate && check_running
($vmid)) {
4453 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4456 &$snapshot_copy_config($conf, $snap);
4458 $snap->{snapstate
} = "prepare";
4459 $snap->{snaptime
} = time();
4460 $snap->{description
} = $comment if $comment;
4462 # always overwrite machine if we save vmstate. This makes sure we
4463 # can restore it later using correct machine type
4464 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4466 update_config_nolock
($vmid, $conf, 1);
4469 lock_config
($vmid, $updatefn);
4474 my $snapshot_commit = sub {
4475 my ($vmid, $snapname) = @_;
4477 my $updatefn = sub {
4479 my $conf = load_config
($vmid);
4481 die "missing snapshot lock\n"
4482 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4484 my $snap = $conf->{snapshots
}->{$snapname};
4486 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4488 die "wrong snapshot state\n"
4489 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4491 delete $snap->{snapstate
};
4492 delete $conf->{lock};
4494 my $newconf = &$snapshot_apply_config($conf, $snap);
4496 $newconf->{parent
} = $snapname;
4498 update_config_nolock
($vmid, $newconf, 1);
4501 lock_config
($vmid, $updatefn);
4504 sub snapshot_rollback
{
4505 my ($vmid, $snapname) = @_;
4511 my $storecfg = PVE
::Storage
::config
();
4513 my $updatefn = sub {
4515 my $conf = load_config
($vmid);
4517 die "you can't rollback if vm is a template\n" if is_template
($conf);
4519 $snap = $conf->{snapshots
}->{$snapname};
4521 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4523 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4524 if $snap->{snapstate
};
4528 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4531 die "unable to rollback vm $vmid: vm is running\n"
4532 if check_running
($vmid);
4535 $conf->{lock} = 'rollback';
4537 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4538 delete $conf->{lock};
4544 my $has_machine_config = defined($conf->{machine
});
4546 # copy snapshot config to current config
4547 $conf = &$snapshot_apply_config($conf, $snap);
4548 $conf->{parent
} = $snapname;
4550 # Note: old code did not store 'machine', so we try to be smart
4551 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4552 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4553 # we remove the 'machine' configuration if not explicitly specified
4554 # in the original config.
4555 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4558 update_config_nolock
($vmid, $conf, 1);
4560 if (!$prepare && $snap->{vmstate
}) {
4561 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4562 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4566 lock_config
($vmid, $updatefn);
4568 foreach_drive
($snap, sub {
4569 my ($ds, $drive) = @_;
4571 return if drive_is_cdrom
($drive);
4573 my $volid = $drive->{file
};
4574 my $device = "drive-$ds";
4576 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4580 lock_config
($vmid, $updatefn);
4583 my $savevm_wait = sub {
4587 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4588 if (!$stat->{status
}) {
4589 die "savevm not active\n";
4590 } elsif ($stat->{status
} eq 'active') {
4593 } elsif ($stat->{status
} eq 'completed') {
4596 die "query-savevm returned status '$stat->{status}'\n";
4601 sub snapshot_create
{
4602 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4604 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4606 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4610 my $running = check_running
($vmid);
4613 # create internal snapshots of all drives
4615 my $storecfg = PVE
::Storage
::config
();
4618 if ($snap->{vmstate
}) {
4619 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4620 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4621 &$savevm_wait($vmid);
4623 vm_mon_cmd
($vmid, "savevm-start");
4627 qga_freezefs
($vmid) if $running && $freezefs;
4629 foreach_drive
($snap, sub {
4630 my ($ds, $drive) = @_;
4632 return if drive_is_cdrom
($drive);
4634 my $volid = $drive->{file
};
4635 my $device = "drive-$ds";
4637 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4638 $drivehash->{$ds} = 1;
4643 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4646 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4650 warn "snapshot create failed: starting cleanup\n";
4651 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4656 &$snapshot_commit($vmid, $snapname);
4659 # Note: $drivehash is only set when called from snapshot_create.
4660 sub snapshot_delete
{
4661 my ($vmid, $snapname, $force, $drivehash) = @_;
4668 my $unlink_parent = sub {
4669 my ($confref, $new_parent) = @_;
4671 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4673 $confref->{parent
} = $new_parent;
4675 delete $confref->{parent
};
4680 my $updatefn = sub {
4681 my ($remove_drive) = @_;
4683 my $conf = load_config
($vmid);
4687 die "you can't delete a snapshot if vm is a template\n"
4688 if is_template
($conf);
4691 $snap = $conf->{snapshots
}->{$snapname};
4693 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4695 # remove parent refs
4696 &$unlink_parent($conf, $snap->{parent
});
4697 foreach my $sn (keys %{$conf->{snapshots
}}) {
4698 next if $sn eq $snapname;
4699 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4702 if ($remove_drive) {
4703 if ($remove_drive eq 'vmstate') {
4704 delete $snap->{$remove_drive};
4706 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4707 my $volid = $drive->{file
};
4708 delete $snap->{$remove_drive};
4709 add_unused_volume
($conf, $volid);
4714 $snap->{snapstate
} = 'delete';
4716 delete $conf->{snapshots
}->{$snapname};
4717 delete $conf->{lock} if $drivehash;
4718 foreach my $volid (@$unused) {
4719 add_unused_volume
($conf, $volid);
4723 update_config_nolock
($vmid, $conf, 1);
4726 lock_config
($vmid, $updatefn);
4728 # now remove vmstate file
4730 my $storecfg = PVE
::Storage
::config
();
4732 if ($snap->{vmstate
}) {
4733 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4735 die $err if !$force;
4738 # save changes (remove vmstate from snapshot)
4739 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4742 # now remove all internal snapshots
4743 foreach_drive
($snap, sub {
4744 my ($ds, $drive) = @_;
4746 return if drive_is_cdrom
($drive);
4748 my $volid = $drive->{file
};
4749 my $device = "drive-$ds";
4751 if (!$drivehash || $drivehash->{$ds}) {
4752 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4754 die $err if !$force;
4759 # save changes (remove drive fron snapshot)
4760 lock_config
($vmid, $updatefn, $ds) if !$force;
4761 push @$unused, $volid;
4764 # now cleanup config
4766 lock_config
($vmid, $updatefn);
4770 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4773 foreach_drive
($conf, sub {
4774 my ($ds, $drive) = @_;
4776 return if drive_is_cdrom
($drive);
4777 my $volid = $drive->{file
};
4778 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4781 return $err ?
0 : 1;
4784 sub template_create
{
4785 my ($vmid, $conf, $disk) = @_;
4787 my $storecfg = PVE
::Storage
::config
();
4789 foreach_drive
($conf, sub {
4790 my ($ds, $drive) = @_;
4792 return if drive_is_cdrom
($drive);
4793 return if $disk && $ds ne $disk;
4795 my $volid = $drive->{file
};
4796 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4798 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4799 $drive->{file
} = $voliddst;
4800 $conf->{$ds} = print_drive
($vmid, $drive);
4801 update_config_nolock
($vmid, $conf, 1);
4808 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4811 sub qemu_img_convert
{
4812 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4814 my $storecfg = PVE
::Storage
::config
();
4815 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4816 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4818 if ($src_storeid && $dst_storeid) {
4819 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4820 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4822 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4823 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4825 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4826 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4829 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4830 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4831 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4835 if($line =~ m/\((\S+)\/100\
%\)/){
4837 my $transferred = int($size * $percent / 100);
4838 my $remaining = $size - $transferred;
4840 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4845 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4847 die "copy failed: $err" if $err;
4851 sub qemu_img_format
{
4852 my ($scfg, $volname) = @_;
4854 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4856 } elsif ($scfg->{type
} eq 'iscsi') {
4857 return "host_device";
4863 sub qemu_drive_mirror
{
4864 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4870 my $storecfg = PVE
::Storage
::config
();
4871 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4874 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4877 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4881 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4884 #fixme : sometime drive-mirror timeout, but works fine after.
4885 # (I have see the problem with big volume > 200GB), so we need to eval
4886 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4887 sync
=> "full", target
=> $dst_path, format
=> $format); };
4889 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4890 sync
=> "full", target
=> $dst_path); };
4895 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4896 my $stat = @$stats[0];
4897 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4898 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4900 my $transferred = $stat->{offset
};
4901 my $total = $stat->{len
};
4902 my $remaining = $total - $transferred;
4903 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4905 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4907 last if ($stat->{len
} == $stat->{offset
});
4908 if ($old_len == $stat->{offset
}) {
4909 if ($maxwait && $count > $maxwait) {
4910 # if writes to disk occurs the disk needs to be freezed
4911 # to be able to complete the migration
4912 vm_suspend
($vmid,1);
4916 $count++ unless $frozen;
4922 $old_len = $stat->{offset
};
4926 if ($vmiddst == $vmid) {
4927 # switch the disk if source and destination are on the same guest
4928 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4932 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4933 die "mirroring error: $err";
4936 if ($vmiddst != $vmid) {
4937 # if we clone a disk for a new target vm, we don't switch the disk
4938 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4944 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4945 $newvmid, $storage, $format, $full, $newvollist) = @_;
4950 print "create linked clone of drive $drivename ($drive->{file})\n";
4951 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4952 push @$newvollist, $newvolid;
4954 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4955 $storeid = $storage if $storage;
4957 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4959 $format = $drive->{format
} || $defFormat;
4962 # test if requested format is supported - else use default
4963 my $supported = grep { $_ eq $format } @$validFormats;
4964 $format = $defFormat if !$supported;
4966 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4968 print "create full clone of drive $drivename ($drive->{file})\n";
4969 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4970 push @$newvollist, $newvolid;
4972 if (!$running || $snapname) {
4973 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4975 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4979 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4982 $disk->{format
} = undef;
4983 $disk->{file
} = $newvolid;
4984 $disk->{size
} = $size;
4989 # this only works if VM is running
4990 sub get_current_qemu_machine
{
4993 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4994 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4996 my ($current, $default);
4997 foreach my $e (@$res) {
4998 $default = $e->{name
} if $e->{'is-default'};
4999 $current = $e->{name
} if $e->{'is-current'};
5002 # fallback to the default machine if current is not supported by qemu
5003 return $current || $default || 'pc';