1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
36 # Note about locking: we use flock on the config file protect
37 # against concurent actions.
38 # Aditionaly, we have a 'lock' setting in the config file. This
39 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
40 # allowed when such lock is set. But you can ignore this kind of
41 # lock with the --skiplock flag.
43 cfs_register_file
('/qemu-server/',
47 PVE
::JSONSchema
::register_standard_option
('skiplock', {
48 description
=> "Ignore locks - only root is allowed to use this option.",
53 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
54 description
=> "Some command save/restore state from this location.",
60 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
61 description
=> "The name of the snapshot.",
62 type
=> 'string', format
=> 'pve-configid',
66 #no warnings 'redefine';
68 unless(defined(&_VZSYSCALLS_H_
)) {
69 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
70 require 'sys/syscall.ph';
71 if(defined(&__x86_64__
)) {
72 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
73 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
74 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
75 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
76 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
77 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
78 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
79 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
81 elsif(defined( &__i386__
) ) {
82 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
83 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
84 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
85 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
86 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
87 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
88 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
89 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
91 die("no fairsched syscall for this arch");
93 require 'asm/ioctl.ph';
94 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
98 my ($parent, $weight, $desired) = @_;
100 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
103 sub fairsched_rmnod
{
106 return syscall(&__NR_fairsched_rmnod
, int($id));
110 my ($pid, $newid) = @_;
112 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
115 sub fairsched_vcpus
{
116 my ($id, $vcpus) = @_;
118 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
122 my ($id, $op, $rate) = @_;
124 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
127 use constant FAIRSCHED_SET_RATE
=> 0;
128 use constant FAIRSCHED_DROP_RATE
=> 1;
129 use constant FAIRSCHED_GET_RATE
=> 2;
131 sub fairsched_cpulimit
{
132 my ($id, $limit) = @_;
134 my $cpulim1024 = int($limit * 1024 / 100);
135 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
137 return fairsched_rate
($id, $op, $cpulim1024);
140 my $nodename = PVE
::INotify
::nodename
();
142 mkdir "/etc/pve/nodes/$nodename";
143 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
146 my $var_run_tmpdir = "/var/run/qemu-server";
147 mkdir $var_run_tmpdir;
149 my $lock_dir = "/var/lock/qemu-server";
152 my $pcisysfs = "/sys/bus/pci";
158 description
=> "Specifies whether a VM will be started during system bootup.",
164 description
=> "Automatic restart after crash (currently ignored).",
170 description
=> "Allow hotplug for disk and network device",
176 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
182 description
=> "Lock/unlock the VM.",
183 enum
=> [qw(migrate backup snapshot rollback)],
188 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
195 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
203 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
210 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
216 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
224 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
225 enum
=> PVE
::Tools
::kvmkeymaplist
(),
230 type
=> 'string', format
=> 'dns-name',
231 description
=> "Set a name for the VM. Only used on the configuration web interface.",
236 description
=> "scsi controller model",
237 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)],
243 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
248 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
249 description
=> <<EODESC,
250 Used to enable special optimization/features for specific
253 other => unspecified OS
254 wxp => Microsoft Windows XP
255 w2k => Microsoft Windows 2000
256 w2k3 => Microsoft Windows 2003
257 w2k8 => Microsoft Windows 2008
258 wvista => Microsoft Windows Vista
259 win7 => Microsoft Windows 7
260 win8 => Microsoft Windows 8/2012
261 l24 => Linux 2.4 Kernel
262 l26 => Linux 2.6/3.X Kernel
263 solaris => solaris/opensolaris/openindiania kernel
265 other|l24|l26|solaris ... no special behaviour
266 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
272 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
273 pattern
=> '[acdn]{1,4}',
278 type
=> 'string', format
=> 'pve-qm-bootdisk',
279 description
=> "Enable booting from specified disk.",
280 pattern
=> '(ide|sata|scsi|virtio)\d+',
285 description
=> "The number of CPUs. Please use option -sockets instead.",
292 description
=> "The number of CPU sockets.",
299 description
=> "The number of cores per socket.",
306 description
=> "Maximum cpus for hotplug.",
313 description
=> "Enable/disable ACPI.",
319 description
=> "Enable/disable Qemu GuestAgent.",
325 description
=> "Enable/disable KVM hardware virtualization.",
331 description
=> "Enable/disable time drift fix.",
337 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
342 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
347 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
348 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
352 type
=> 'string', format
=> 'pve-qm-watchdog',
353 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
354 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
359 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
360 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
361 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
366 type
=> 'string', format
=> 'pve-qm-startup',
367 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
368 description
=> "Startup and shutdown behavior. Order is a non-negative number defining the general startup order. Shutdown in done with reverse ordering. Additionally you can set the 'up' or 'down' delay in seconds, which specifies a delay to wait before the next VM is started or stopped.",
373 description
=> "Enable/disable Template.",
379 description
=> <<EODESCR,
380 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
382 args: -no-reboot -no-hpet
389 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
394 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
398 migrate_downtime
=> {
401 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
407 type
=> 'string', format
=> 'pve-qm-drive',
408 typetext
=> 'volume',
409 description
=> "This is an alias for option -ide2",
413 description
=> "Emulated CPU type.",
415 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
418 parent
=> get_standard_option
('pve-snapshot-name', {
420 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
424 description
=> "Timestamp for snapshots.",
430 type
=> 'string', format
=> 'pve-volume-id',
431 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
434 description
=> "Specific the Qemu machine type.",
436 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
442 # what about other qemu settings ?
444 #machine => 'string',
457 ##soundhw => 'string',
459 while (my ($k, $v) = each %$confdesc) {
460 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
463 my $MAX_IDE_DISKS = 4;
464 my $MAX_SCSI_DISKS = 14;
465 my $MAX_VIRTIO_DISKS = 16;
466 my $MAX_SATA_DISKS = 6;
467 my $MAX_USB_DEVICES = 5;
469 my $MAX_UNUSED_DISKS = 8;
470 my $MAX_HOSTPCI_DEVICES = 2;
471 my $MAX_SERIAL_PORTS = 4;
472 my $MAX_PARALLEL_PORTS = 3;
474 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
475 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3'];
476 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
480 type
=> 'string', format
=> 'pve-qm-net',
481 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
482 description
=> <<EODESCR,
483 Specify network devices.
485 MODEL is one of: $nic_model_list_txt
487 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
488 automatically generated if not specified.
490 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
492 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
494 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
500 The DHCP server assign addresses to the guest starting from 10.0.2.15.
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
506 for (my $i = 0; $i < $MAX_NETS; $i++) {
507 $confdesc->{"net$i"} = $netdesc;
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
516 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
524 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
530 type
=> 'string', format
=> 'pve-qm-drive',
531 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
532 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
534 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
538 type
=> 'string', format
=> 'pve-qm-drive',
539 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
540 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
542 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
546 type
=> 'string', format
=> 'pve-qm-usb-device',
547 typetext
=> 'host=HOSTUSBDEVICE|spice',
548 description
=> <<EODESCR,
549 Configure an USB device (n is 0 to 4). This can be used to
550 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
552 'bus-port(.port)*' (decimal numbers) or
553 'vendor_id:product_id' (hexadeciaml numbers)
555 You can use the 'lsusb -t' command to list existing usb devices.
557 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
559 The value 'spice' can be used to add a usb redirection devices for spice.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
567 type
=> 'string', format
=> 'pve-qm-hostpci',
568 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]",
569 description
=> <<EODESCR,
570 Map host pci devices. HOSTPCIDEVICE syntax is:
572 'bus:dev.func' (hexadecimal numbers)
574 You can us the 'lspci' command to list existing pci devices.
576 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
578 The 'driver' option is currently ignored.
580 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
582 Experimental: user reported problems with this option.
585 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
590 pattern
=> '(/dev/ttyS\d+|socket)',
591 description
=> <<EODESCR,
592 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
594 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
596 Experimental: user reported problems with this option.
603 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
604 description
=> <<EODESCR,
605 Map host parallel devices (n is 0 to 2).
607 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
609 Experimental: user reported problems with this option.
613 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
614 $confdesc->{"parallel$i"} = $paralleldesc;
617 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
618 $confdesc->{"serial$i"} = $serialdesc;
621 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
622 $confdesc->{"hostpci$i"} = $hostpcidesc;
625 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
626 $drivename_hash->{"ide$i"} = 1;
627 $confdesc->{"ide$i"} = $idedesc;
630 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
631 $drivename_hash->{"sata$i"} = 1;
632 $confdesc->{"sata$i"} = $satadesc;
635 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
636 $drivename_hash->{"scsi$i"} = 1;
637 $confdesc->{"scsi$i"} = $scsidesc ;
640 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
641 $drivename_hash->{"virtio$i"} = 1;
642 $confdesc->{"virtio$i"} = $virtiodesc;
645 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
646 $confdesc->{"usb$i"} = $usbdesc;
651 type
=> 'string', format
=> 'pve-volume-id',
652 description
=> "Reference to unused volumes.",
655 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
656 $confdesc->{"unused$i"} = $unuseddesc;
659 my $kvm_api_version = 0;
663 return $kvm_api_version if $kvm_api_version;
665 my $fh = IO
::File-
>new("</dev/kvm") ||
668 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
669 $kvm_api_version = $v;
674 return $kvm_api_version;
677 my $kvm_user_version;
679 sub kvm_user_version
{
681 return $kvm_user_version if $kvm_user_version;
683 $kvm_user_version = 'unknown';
685 my $tmp = `kvm -help 2>/dev/null`;
687 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
688 $kvm_user_version = $2;
691 return $kvm_user_version;
695 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
698 # order is important - used to autoselect boot disk
699 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
700 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
701 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
702 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
705 sub valid_drivename
{
708 return defined($drivename_hash->{$dev});
713 return defined($confdesc->{$key});
717 return $nic_model_list;
720 sub os_list_description
{
725 w2k
=> 'Windows 2000',
726 w2k3
=>, 'Windows 2003',
727 w2k8
=> 'Windows 2008',
728 wvista
=> 'Windows Vista',
730 win8
=> 'Windows 8/2012',
740 return $cdrom_path if $cdrom_path;
742 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
743 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
744 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
748 my ($storecfg, $vmid, $cdrom) = @_;
750 if ($cdrom eq 'cdrom') {
751 return get_cdrom_path
();
752 } elsif ($cdrom eq 'none') {
754 } elsif ($cdrom =~ m
|^/|) {
757 return PVE
::Storage
::path
($storecfg, $cdrom);
761 # try to convert old style file names to volume IDs
762 sub filename_to_volume_id
{
763 my ($vmid, $file, $media) = @_;
765 if (!($file eq 'none' || $file eq 'cdrom' ||
766 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
768 return undef if $file =~ m
|/|;
770 if ($media && $media eq 'cdrom') {
771 $file = "local:iso/$file";
773 $file = "local:$vmid/$file";
780 sub verify_media_type
{
781 my ($opt, $vtype, $media) = @_;
786 if ($media eq 'disk') {
788 } elsif ($media eq 'cdrom') {
791 die "internal error";
794 return if ($vtype eq $etype);
796 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
799 sub cleanup_drive_path
{
800 my ($opt, $storecfg, $drive) = @_;
802 # try to convert filesystem paths to volume IDs
804 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
805 ($drive->{file
} !~ m
|^/dev/.+|) &&
806 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
807 ($drive->{file
} !~ m/^\d+$/)) {
808 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
809 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
810 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
811 verify_media_type
($opt, $vtype, $drive->{media
});
812 $drive->{file
} = $volid;
815 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
818 sub create_conf_nolock
{
819 my ($vmid, $settings) = @_;
821 my $filename = config_file
($vmid);
823 die "configuration file '$filename' already exists\n" if -f
$filename;
825 my $defaults = load_defaults
();
827 $settings->{name
} = "vm$vmid" if !$settings->{name
};
828 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
831 foreach my $opt (keys %$settings) {
832 next if !$confdesc->{$opt};
834 my $value = $settings->{$opt};
837 $data .= "$opt: $value\n";
840 PVE
::Tools
::file_set_contents
($filename, $data);
843 my $parse_size = sub {
846 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
847 my ($size, $unit) = ($1, $3);
850 $size = $size * 1024;
851 } elsif ($unit eq 'M') {
852 $size = $size * 1024 * 1024;
853 } elsif ($unit eq 'G') {
854 $size = $size * 1024 * 1024 * 1024;
860 my $format_size = sub {
865 my $kb = int($size/1024);
866 return $size if $kb*1024 != $size;
868 my $mb = int($kb/1024);
869 return "${kb}K" if $mb*1024 != $kb;
871 my $gb = int($mb/1024);
872 return "${mb}M" if $gb*1024 != $mb;
877 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
878 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
879 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
880 # [,aio=native|threads][,discard=ignore|on]
883 my ($key, $data) = @_;
887 # $key may be undefined - used to verify JSON parameters
888 if (!defined($key)) {
889 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
891 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
892 $res->{interface
} = $1;
898 foreach my $p (split (/,/, $data)) {
899 next if $p =~ m/^\s*$/;
901 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
902 my ($k, $v) = ($1, $2);
904 $k = 'file' if $k eq 'volume';
906 return undef if defined $res->{$k};
908 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
909 return undef if !$v || $v !~ m/^\d+/;
911 $v = sprintf("%.3f", $v / (1024*1024));
915 if (!$res->{file
} && $p !~ m/=/) {
923 return undef if !$res->{file
};
925 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
929 return undef if $res->{cache
} &&
930 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
931 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
932 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
933 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
934 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
935 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
936 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
937 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
938 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
939 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
940 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
941 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
942 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
944 return undef if $res->{mbps_rd
} && $res->{mbps
};
945 return undef if $res->{mbps_wr
} && $res->{mbps
};
947 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
949 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
951 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{iops_rd
} && $res->{iops
};
955 return undef if $res->{iops_wr
} && $res->{iops
};
958 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
959 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
960 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
961 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
962 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
963 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
967 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
970 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
971 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
972 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
973 return undef if $res->{interface
} eq 'virtio';
976 # rerror does not work with scsi drives
977 if ($res->{rerror
}) {
978 return undef if $res->{interface
} eq 'scsi';
984 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
987 my ($vmid, $drive) = @_;
990 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
991 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
994 if ($drive->{size
}) {
995 $opts .= ",size=" . &$format_size($drive->{size
});
998 return "$drive->{file}$opts";
1002 my($fh, $noerr) = @_;
1005 my $SG_GET_VERSION_NUM = 0x2282;
1007 my $versionbuf = "\x00" x
8;
1008 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1010 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1013 my $version = unpack("I", $versionbuf);
1014 if ($version < 30000) {
1015 die "scsi generic interface too old\n" if !$noerr;
1019 my $buf = "\x00" x
36;
1020 my $sensebuf = "\x00" x
8;
1021 my $cmd = pack("C x3 C x1", 0x12, 36);
1023 # see /usr/include/scsi/sg.h
1024 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1026 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1027 length($sensebuf), 0, length($buf), $buf,
1028 $cmd, $sensebuf, 6000);
1030 $ret = ioctl($fh, $SG_IO, $packet);
1032 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1036 my @res = unpack($sg_io_hdr_t, $packet);
1037 if ($res[17] || $res[18]) {
1038 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1043 (my $byte0, my $byte1, $res->{vendor
},
1044 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1046 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1047 $res->{type
} = $byte0 & 31;
1055 my $fh = IO
::File-
>new("+<$path") || return undef;
1056 my $res = scsi_inquiry
($fh, 1);
1062 sub print_drivedevice_full
{
1063 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1068 if ($drive->{interface
} eq 'virtio') {
1069 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1070 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1071 } elsif ($drive->{interface
} eq 'scsi') {
1072 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1073 my $controller = int($drive->{index} / $maxdev);
1074 my $unit = $drive->{index} % $maxdev;
1075 my $devicetype = 'hd';
1077 if (drive_is_cdrom
($drive)) {
1080 if ($drive->{file
} =~ m
|^/|) {
1081 $path = $drive->{file
};
1083 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1086 if($path =~ m/^iscsi\:\/\
//){
1087 $devicetype = 'generic';
1089 if (my $info = path_is_scsi
($path)) {
1090 if ($info->{type
} == 0) {
1091 $devicetype = 'block';
1092 } elsif ($info->{type
} == 1) { # tape
1093 $devicetype = 'generic';
1099 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1100 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1102 $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1105 } elsif ($drive->{interface
} eq 'ide'){
1107 my $controller = int($drive->{index} / $maxdev);
1108 my $unit = $drive->{index} % $maxdev;
1109 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1111 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1112 } elsif ($drive->{interface
} eq 'sata'){
1113 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1114 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1115 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1116 } elsif ($drive->{interface
} eq 'usb') {
1118 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1120 die "unsupported interface type";
1123 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1128 sub print_drive_full
{
1129 my ($storecfg, $vmid, $drive) = @_;
1132 foreach my $o (@qemu_drive_options) {
1133 next if $o eq 'bootindex';
1134 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1137 foreach my $o (qw(bps bps_rd bps_wr)) {
1138 my $v = $drive->{"m$o"};
1139 $opts .= ",$o=" . int($v*1024*1024) if $v;
1142 # use linux-aio by default (qemu default is threads)
1143 $opts .= ",aio=native" if !$drive->{aio
};
1146 my $volid = $drive->{file
};
1147 if (drive_is_cdrom
($drive)) {
1148 $path = get_iso_path
($storecfg, $vmid, $volid);
1150 if ($volid =~ m
|^/|) {
1153 $path = PVE
::Storage
::path
($storecfg, $volid);
1157 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1159 my $pathinfo = $path ?
"file=$path," : '';
1161 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1164 sub print_netdevice_full
{
1165 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1167 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1169 my $device = $net->{model
};
1170 if ($net->{model
} eq 'virtio') {
1171 $device = 'virtio-net-pci';
1174 # qemu > 0.15 always try to boot from network - we disable that by
1175 # not loading the pxe rom file
1176 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1177 my $pciaddr = print_pci_addr
("$netid", $bridges);
1178 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1179 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1183 sub print_netdev_full
{
1184 my ($vmid, $conf, $net, $netid) = @_;
1187 if ($netid =~ m/^net(\d+)$/) {
1191 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1193 my $ifname = "tap${vmid}i$i";
1195 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1196 die "interface name '$ifname' is too long (max 15 character)\n"
1197 if length($ifname) >= 16;
1199 my $vhostparam = '';
1200 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1202 my $vmname = $conf->{name
} || "vm$vmid";
1204 if ($net->{bridge
}) {
1205 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1207 return "type=user,id=$netid,hostname=$vmname";
1211 sub drive_is_cdrom
{
1214 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1221 return undef if !$value;
1224 my @list = split(/,/, $value);
1228 foreach my $kv (@list) {
1230 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) {
1233 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1234 $res->{driver
} = $1;
1235 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1236 $res->{rombar
} = $1;
1238 warn "unknown hostpci setting '$kv'\n";
1242 return undef if !$found;
1247 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1253 foreach my $kvp (split(/,/, $data)) {
1255 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1257 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1258 $res->{model
} = $model;
1259 $res->{macaddr
} = $mac;
1260 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1261 $res->{bridge
} = $1;
1262 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1264 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1272 return undef if !$res->{model
};
1280 my $res = "$net->{model}";
1281 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1282 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1283 $res .= ",rate=$net->{rate}" if $net->{rate
};
1284 $res .= ",tag=$net->{tag}" if $net->{tag
};
1289 sub add_random_macs
{
1290 my ($settings) = @_;
1292 foreach my $opt (keys %$settings) {
1293 next if $opt !~ m/^net(\d+)$/;
1294 my $net = parse_net
($settings->{$opt});
1296 $settings->{$opt} = print_net
($net);
1300 sub add_unused_volume
{
1301 my ($config, $volid) = @_;
1304 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1305 my $test = "unused$ind";
1306 if (my $vid = $config->{$test}) {
1307 return if $vid eq $volid; # do not add duplicates
1313 die "To many unused volume - please delete them first.\n" if !$key;
1315 $config->{$key} = $volid;
1320 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1321 sub verify_bootdisk
{
1322 my ($value, $noerr) = @_;
1324 return $value if valid_drivename
($value);
1326 return undef if $noerr;
1328 die "invalid boot disk '$value'\n";
1331 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1333 my ($value, $noerr) = @_;
1335 return $value if parse_net
($value);
1337 return undef if $noerr;
1339 die "unable to parse network options\n";
1342 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1344 my ($value, $noerr) = @_;
1346 return $value if parse_drive
(undef, $value);
1348 return undef if $noerr;
1350 die "unable to parse drive options\n";
1353 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1354 sub verify_hostpci
{
1355 my ($value, $noerr) = @_;
1357 return $value if parse_hostpci
($value);
1359 return undef if $noerr;
1361 die "unable to parse pci id\n";
1364 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1365 sub verify_watchdog
{
1366 my ($value, $noerr) = @_;
1368 return $value if parse_watchdog
($value);
1370 return undef if $noerr;
1372 die "unable to parse watchdog options\n";
1375 sub parse_watchdog
{
1378 return undef if !$value;
1382 foreach my $p (split(/,/, $value)) {
1383 next if $p =~ m/^\s*$/;
1385 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1387 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1388 $res->{action
} = $2;
1397 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1398 sub verify_startup
{
1399 my ($value, $noerr) = @_;
1401 return $value if parse_startup
($value);
1403 return undef if $noerr;
1405 die "unable to parse startup options\n";
1411 return undef if !$value;
1415 foreach my $p (split(/,/, $value)) {
1416 next if $p =~ m/^\s*$/;
1418 if ($p =~ m/^(order=)?(\d+)$/) {
1420 } elsif ($p =~ m/^up=(\d+)$/) {
1422 } elsif ($p =~ m/^down=(\d+)$/) {
1432 sub parse_usb_device
{
1435 return undef if !$value;
1437 my @dl = split(/,/, $value);
1441 foreach my $v (@dl) {
1442 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1444 $res->{vendorid
} = $2;
1445 $res->{productid
} = $4;
1446 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1448 $res->{hostbus
} = $1;
1449 $res->{hostport
} = $2;
1450 } elsif ($v =~ m/^spice$/) {
1457 return undef if !$found;
1462 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1463 sub verify_usb_device
{
1464 my ($value, $noerr) = @_;
1466 return $value if parse_usb_device
($value);
1468 return undef if $noerr;
1470 die "unable to parse usb device\n";
1473 # add JSON properties for create and set function
1474 sub json_config_properties
{
1477 foreach my $opt (keys %$confdesc) {
1478 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1479 $prop->{$opt} = $confdesc->{$opt};
1486 my ($key, $value) = @_;
1488 die "unknown setting '$key'\n" if !$confdesc->{$key};
1490 my $type = $confdesc->{$key}->{type
};
1492 if (!defined($value)) {
1493 die "got undefined value\n";
1496 if ($value =~ m/[\n\r]/) {
1497 die "property contains a line feed\n";
1500 if ($type eq 'boolean') {
1501 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1502 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1503 die "type check ('boolean') failed - got '$value'\n";
1504 } elsif ($type eq 'integer') {
1505 return int($1) if $value =~ m/^(\d+)$/;
1506 die "type check ('integer') failed - got '$value'\n";
1507 } elsif ($type eq 'number') {
1508 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1509 die "type check ('number') failed - got '$value'\n";
1510 } elsif ($type eq 'string') {
1511 if (my $fmt = $confdesc->{$key}->{format
}) {
1512 if ($fmt eq 'pve-qm-drive') {
1513 # special case - we need to pass $key to parse_drive()
1514 my $drive = parse_drive
($key, $value);
1515 return $value if $drive;
1516 die "unable to parse drive options\n";
1518 PVE
::JSONSchema
::check_format
($fmt, $value);
1521 $value =~ s/^\"(.*)\"$/$1/;
1524 die "internal error"
1528 sub lock_config_full
{
1529 my ($vmid, $timeout, $code, @param) = @_;
1531 my $filename = config_file_lock
($vmid);
1533 my $res = lock_file
($filename, $timeout, $code, @param);
1540 sub lock_config_mode
{
1541 my ($vmid, $timeout, $shared, $code, @param) = @_;
1543 my $filename = config_file_lock
($vmid);
1545 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1553 my ($vmid, $code, @param) = @_;
1555 return lock_config_full
($vmid, 10, $code, @param);
1558 sub cfs_config_path
{
1559 my ($vmid, $node) = @_;
1561 $node = $nodename if !$node;
1562 return "nodes/$node/qemu-server/$vmid.conf";
1565 sub check_iommu_support
{
1566 #fixme : need to check IOMMU support
1567 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1575 my ($vmid, $node) = @_;
1577 my $cfspath = cfs_config_path
($vmid, $node);
1578 return "/etc/pve/$cfspath";
1581 sub config_file_lock
{
1584 return "$lock_dir/lock-$vmid.conf";
1590 my $conf = config_file
($vmid);
1591 utime undef, undef, $conf;
1595 my ($storecfg, $vmid, $keep_empty_config) = @_;
1597 my $conffile = config_file
($vmid);
1599 my $conf = load_config
($vmid);
1603 # only remove disks owned by this VM
1604 foreach_drive
($conf, sub {
1605 my ($ds, $drive) = @_;
1607 return if drive_is_cdrom
($drive);
1609 my $volid = $drive->{file
};
1611 return if !$volid || $volid =~ m
|^/|;
1613 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1614 return if !$path || !$owner || ($owner != $vmid);
1616 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1619 if ($keep_empty_config) {
1620 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1625 # also remove unused disk
1627 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1630 PVE
::Storage
::foreach_volid
($dl, sub {
1631 my ($volid, $sid, $volname, $d) = @_;
1632 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1642 my ($vmid, $node) = @_;
1644 my $cfspath = cfs_config_path
($vmid, $node);
1646 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1648 die "no such VM ('$vmid')\n" if !defined($conf);
1653 sub parse_vm_config
{
1654 my ($filename, $raw) = @_;
1656 return undef if !defined($raw);
1659 digest
=> Digest
::SHA
::sha1_hex
($raw),
1663 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1664 || die "got strange filename '$filename'";
1671 my @lines = split(/\n/, $raw);
1672 foreach my $line (@lines) {
1673 next if $line =~ m/^\s*$/;
1675 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1677 $conf->{description
} = $descr if $descr;
1679 $conf = $res->{snapshots
}->{$snapname} = {};
1683 if ($line =~ m/^\#(.*)\s*$/) {
1684 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1688 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1689 $descr .= PVE
::Tools
::decode_text
($2);
1690 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1691 $conf->{snapstate
} = $1;
1692 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1695 $conf->{$key} = $value;
1696 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1699 eval { $value = check_type
($key, $value); };
1701 warn "vm $vmid - unable to parse value of '$key' - $@";
1703 my $fmt = $confdesc->{$key}->{format
};
1704 if ($fmt && $fmt eq 'pve-qm-drive') {
1705 my $v = parse_drive
($key, $value);
1706 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1707 $v->{file
} = $volid;
1708 $value = print_drive
($vmid, $v);
1710 warn "vm $vmid - unable to parse value of '$key'\n";
1715 if ($key eq 'cdrom') {
1716 $conf->{ide2
} = $value;
1718 $conf->{$key} = $value;
1724 $conf->{description
} = $descr if $descr;
1726 delete $res->{snapstate
}; # just to be sure
1731 sub write_vm_config
{
1732 my ($filename, $conf) = @_;
1734 delete $conf->{snapstate
}; # just to be sure
1736 if ($conf->{cdrom
}) {
1737 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1738 $conf->{ide2
} = $conf->{cdrom
};
1739 delete $conf->{cdrom
};
1742 # we do not use 'smp' any longer
1743 if ($conf->{sockets
}) {
1744 delete $conf->{smp
};
1745 } elsif ($conf->{smp
}) {
1746 $conf->{sockets
} = $conf->{smp
};
1747 delete $conf->{cores
};
1748 delete $conf->{smp
};
1751 if ($conf->{maxcpus
} && $conf->{sockets
}){
1752 delete $conf->{sockets
};
1754 my $used_volids = {};
1756 my $cleanup_config = sub {
1757 my ($cref, $snapname) = @_;
1759 foreach my $key (keys %$cref) {
1760 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1761 $key eq 'snapstate';
1762 my $value = $cref->{$key};
1763 eval { $value = check_type
($key, $value); };
1764 die "unable to parse value of '$key' - $@" if $@;
1766 $cref->{$key} = $value;
1768 if (!$snapname && valid_drivename
($key)) {
1769 my $drive = parse_drive
($key, $value);
1770 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1775 &$cleanup_config($conf);
1776 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1777 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1780 # remove 'unusedX' settings if we re-add a volume
1781 foreach my $key (keys %$conf) {
1782 my $value = $conf->{$key};
1783 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1784 delete $conf->{$key};
1788 my $generate_raw_config = sub {
1793 # add description as comment to top of file
1794 my $descr = $conf->{description
} || '';
1795 foreach my $cl (split(/\n/, $descr)) {
1796 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1799 foreach my $key (sort keys %$conf) {
1800 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1801 $raw .= "$key: $conf->{$key}\n";
1806 my $raw = &$generate_raw_config($conf);
1807 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1808 $raw .= "\n[$snapname]\n";
1809 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1815 sub update_config_nolock
{
1816 my ($vmid, $conf, $skiplock) = @_;
1818 check_lock
($conf) if !$skiplock;
1820 my $cfspath = cfs_config_path
($vmid);
1822 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1826 my ($vmid, $conf, $skiplock) = @_;
1828 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1835 # we use static defaults from our JSON schema configuration
1836 foreach my $key (keys %$confdesc) {
1837 if (defined(my $default = $confdesc->{$key}->{default})) {
1838 $res->{$key} = $default;
1842 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1843 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1849 my $vmlist = PVE
::Cluster
::get_vmlist
();
1851 return $res if !$vmlist || !$vmlist->{ids
};
1852 my $ids = $vmlist->{ids
};
1854 foreach my $vmid (keys %$ids) {
1855 my $d = $ids->{$vmid};
1856 next if !$d->{node
} || $d->{node
} ne $nodename;
1857 next if !$d->{type
} || $d->{type
} ne 'qemu';
1858 $res->{$vmid}->{exists} = 1;
1863 # test if VM uses local resources (to prevent migration)
1864 sub check_local_resources
{
1865 my ($conf, $noerr) = @_;
1869 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1870 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1872 foreach my $k (keys %$conf) {
1873 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1874 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1877 die "VM uses local resources\n" if $loc_res && !$noerr;
1882 # check if used storages are available on all nodes (use by migrate)
1883 sub check_storage_availability
{
1884 my ($storecfg, $conf, $node) = @_;
1886 foreach_drive
($conf, sub {
1887 my ($ds, $drive) = @_;
1889 my $volid = $drive->{file
};
1892 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1895 # check if storage is available on both nodes
1896 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1897 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1901 # list nodes where all VM images are available (used by has_feature API)
1903 my ($conf, $storecfg) = @_;
1905 my $nodelist = PVE
::Cluster
::get_nodelist
();
1906 my $nodehash = { map { $_ => 1 } @$nodelist };
1907 my $nodename = PVE
::INotify
::nodename
();
1909 foreach_drive
($conf, sub {
1910 my ($ds, $drive) = @_;
1912 my $volid = $drive->{file
};
1915 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1917 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1918 if ($scfg->{disable
}) {
1920 } elsif (my $avail = $scfg->{nodes
}) {
1921 foreach my $node (keys %$nodehash) {
1922 delete $nodehash->{$node} if !$avail->{$node};
1924 } elsif (!$scfg->{shared
}) {
1925 foreach my $node (keys %$nodehash) {
1926 delete $nodehash->{$node} if $node ne $nodename
1938 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1942 my ($pidfile, $pid) = @_;
1944 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1948 return undef if !$line;
1949 my @param = split(/\0/, $line);
1951 my $cmd = $param[0];
1952 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1954 for (my $i = 0; $i < scalar (@param); $i++) {
1957 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1958 my $p = $param[$i+1];
1959 return 1 if $p && ($p eq $pidfile);
1968 my ($vmid, $nocheck, $node) = @_;
1970 my $filename = config_file
($vmid, $node);
1972 die "unable to find configuration file for VM $vmid - no such machine\n"
1973 if !$nocheck && ! -f
$filename;
1975 my $pidfile = pidfile_name
($vmid);
1977 if (my $fd = IO
::File-
>new("<$pidfile")) {
1982 my $mtime = $st->mtime;
1983 if ($mtime > time()) {
1984 warn "file '$filename' modified in future\n";
1987 if ($line =~ m/^(\d+)$/) {
1989 if (check_cmdline
($pidfile, $pid)) {
1990 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2002 my $vzlist = config_list
();
2004 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2006 while (defined(my $de = $fd->read)) {
2007 next if $de !~ m/^(\d+)\.pid$/;
2009 next if !defined($vzlist->{$vmid});
2010 if (my $pid = check_running
($vmid)) {
2011 $vzlist->{$vmid}->{pid
} = $pid;
2019 my ($storecfg, $conf) = @_;
2021 my $bootdisk = $conf->{bootdisk
};
2022 return undef if !$bootdisk;
2023 return undef if !valid_drivename
($bootdisk);
2025 return undef if !$conf->{$bootdisk};
2027 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2028 return undef if !defined($drive);
2030 return undef if drive_is_cdrom
($drive);
2032 my $volid = $drive->{file
};
2033 return undef if !$volid;
2035 return $drive->{size
};
2038 my $last_proc_pid_stat;
2040 # get VM status information
2041 # This must be fast and should not block ($full == false)
2042 # We only query KVM using QMP if $full == true (this can be slow)
2044 my ($opt_vmid, $full) = @_;
2048 my $storecfg = PVE
::Storage
::config
();
2050 my $list = vzlist
();
2051 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2053 my $cpucount = $cpuinfo->{cpus
} || 1;
2055 foreach my $vmid (keys %$list) {
2056 next if $opt_vmid && ($vmid ne $opt_vmid);
2058 my $cfspath = cfs_config_path
($vmid);
2059 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2062 $d->{pid
} = $list->{$vmid}->{pid
};
2064 # fixme: better status?
2065 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2067 my $size = disksize
($storecfg, $conf);
2068 if (defined($size)) {
2069 $d->{disk
} = 0; # no info available
2070 $d->{maxdisk
} = $size;
2076 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2077 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2079 $d->{name
} = $conf->{name
} || "VM $vmid";
2080 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2082 if ($conf->{balloon
}) {
2083 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2084 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2095 $d->{diskwrite
} = 0;
2097 $d->{template
} = is_template
($conf);
2102 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2103 foreach my $dev (keys %$netdev) {
2104 next if $dev !~ m/^tap([1-9]\d*)i/;
2106 my $d = $res->{$vmid};
2109 $d->{netout
} += $netdev->{$dev}->{receive
};
2110 $d->{netin
} += $netdev->{$dev}->{transmit
};
2113 my $ctime = gettimeofday
;
2115 foreach my $vmid (keys %$list) {
2117 my $d = $res->{$vmid};
2118 my $pid = $d->{pid
};
2121 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2122 next if !$pstat; # not running
2124 my $used = $pstat->{utime} + $pstat->{stime
};
2126 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2128 if ($pstat->{vsize
}) {
2129 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2132 my $old = $last_proc_pid_stat->{$pid};
2134 $last_proc_pid_stat->{$pid} = {
2142 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2144 if ($dtime > 1000) {
2145 my $dutime = $used - $old->{used
};
2147 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2148 $last_proc_pid_stat->{$pid} = {
2154 $d->{cpu
} = $old->{cpu
};
2158 return $res if !$full;
2160 my $qmpclient = PVE
::QMPClient-
>new();
2162 my $ballooncb = sub {
2163 my ($vmid, $resp) = @_;
2165 my $info = $resp->{'return'};
2166 return if !$info->{max_mem
};
2168 my $d = $res->{$vmid};
2170 # use memory assigned to VM
2171 $d->{maxmem
} = $info->{max_mem
};
2172 $d->{balloon
} = $info->{actual
};
2174 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2175 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2176 $d->{freemem
} = $info->{free_mem
};
2181 my $blockstatscb = sub {
2182 my ($vmid, $resp) = @_;
2183 my $data = $resp->{'return'} || [];
2184 my $totalrdbytes = 0;
2185 my $totalwrbytes = 0;
2186 for my $blockstat (@$data) {
2187 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2188 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2190 $res->{$vmid}->{diskread
} = $totalrdbytes;
2191 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2194 my $statuscb = sub {
2195 my ($vmid, $resp) = @_;
2197 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2198 # this fails if ballon driver is not loaded, so this must be
2199 # the last commnand (following command are aborted if this fails).
2200 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2202 my $status = 'unknown';
2203 if (!defined($status = $resp->{'return'}->{status
})) {
2204 warn "unable to get VM status\n";
2208 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2211 foreach my $vmid (keys %$list) {
2212 next if $opt_vmid && ($vmid ne $opt_vmid);
2213 next if !$res->{$vmid}->{pid
}; # not running
2214 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2217 $qmpclient->queue_execute();
2219 foreach my $vmid (keys %$list) {
2220 next if $opt_vmid && ($vmid ne $opt_vmid);
2221 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2228 my ($conf, $func) = @_;
2230 foreach my $ds (keys %$conf) {
2231 next if !valid_drivename
($ds);
2233 my $drive = parse_drive
($ds, $conf->{$ds});
2236 &$func($ds, $drive);
2241 my ($conf, $func) = @_;
2245 my $test_volid = sub {
2246 my ($volid, $is_cdrom) = @_;
2250 $volhash->{$volid} = $is_cdrom || 0;
2253 foreach_drive
($conf, sub {
2254 my ($ds, $drive) = @_;
2255 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2258 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2259 my $snap = $conf->{snapshots
}->{$snapname};
2260 &$test_volid($snap->{vmstate
}, 0);
2261 foreach_drive
($snap, sub {
2262 my ($ds, $drive) = @_;
2263 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2267 foreach my $volid (keys %$volhash) {
2268 &$func($volid, $volhash->{$volid});
2272 sub vga_conf_has_spice
{
2275 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2280 sub config_to_command
{
2281 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2284 my $globalFlags = [];
2285 my $machineFlags = [];
2291 my $kvmver = kvm_user_version
();
2292 my $vernum = 0; # unknown
2293 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2294 $vernum = $1*1000000+$2*1000;
2295 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2296 $vernum = $1*1000000+$2*1000+$3;
2299 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2301 my $have_ovz = -f
'/proc/vz/vestat';
2303 push @$cmd, '/usr/bin/kvm';
2305 push @$cmd, '-id', $vmid;
2309 my $qmpsocket = qmp_socket
($vmid);
2310 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2311 push @$cmd, '-mon', "chardev=qmp,mode=control";
2313 my $socket = vnc_socket
($vmid);
2314 push @$cmd, '-vnc', "unix:$socket,x509,password";
2316 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2318 push @$cmd, '-daemonize';
2320 $pciaddr = print_pci_addr
("piix3", $bridges);
2321 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2324 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2325 next if !$conf->{"usb$i"};
2328 # include usb device config
2329 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2331 my $vga = $conf->{vga
};
2333 my $qxlnum = vga_conf_has_spice
($vga);
2334 $vga = 'qxl' if $qxlnum;
2337 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2338 $conf->{ostype
} eq 'win7' ||
2339 $conf->{ostype
} eq 'w2k8')) {
2346 # enable absolute mouse coordinates (needed by vnc)
2348 if (defined($conf->{tablet
})) {
2349 $tablet = $conf->{tablet
};
2351 $tablet = $defaults->{tablet
};
2352 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2353 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2356 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2359 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2360 my $d = parse_hostpci
($conf->{"hostpci$i"});
2362 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2363 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2364 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar";
2368 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2369 my $d = parse_usb_device
($conf->{"usb$i"});
2371 if ($d->{vendorid
} && $d->{productid
}) {
2372 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2373 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2374 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2375 } elsif ($d->{spice
}) {
2376 # usb redir support for spice
2377 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2378 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2383 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2384 if (my $path = $conf->{"serial$i"}) {
2385 if ($path eq 'socket') {
2386 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2387 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2388 push @$devices, '-device', "isa-serial,chardev=serial$i";
2390 die "no such serial device\n" if ! -c
$path;
2391 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2392 push @$devices, '-device', "isa-serial,chardev=serial$i";
2398 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2399 if (my $path = $conf->{"parallel$i"}) {
2400 die "no such parallel device\n" if ! -c
$path;
2401 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2402 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2403 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2407 my $vmname = $conf->{name
} || "vm$vmid";
2409 push @$cmd, '-name', $vmname;
2412 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2413 $sockets = $conf->{sockets
} if $conf->{sockets
};
2415 my $cores = $conf->{cores
} || 1;
2416 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2419 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2421 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2424 push @$cmd, '-nodefaults';
2426 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2428 my $bootindex_hash = {};
2430 foreach my $o (split(//, $bootorder)) {
2431 $bootindex_hash->{$o} = $i*100;
2435 push @$cmd, '-boot', "menu=on";
2437 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2439 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2441 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2444 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2446 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2447 my $useLocaltime = $conf->{localtime};
2449 if (my $ost = $conf->{ostype
}) {
2450 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2452 if ($ost =~ m/^w/) { # windows
2453 $useLocaltime = 1 if !defined($conf->{localtime});
2455 # use time drift fix when acpi is enabled
2456 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2457 $tdf = 1 if !defined($conf->{tdf
});
2461 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2463 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2464 push @$cmd, '-no-hpet';
2465 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2466 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2469 if ($ost eq 'win7' || $ost eq 'win8') {
2470 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2474 push @$rtcFlags, 'driftfix=slew' if $tdf;
2477 push @$machineFlags, 'accel=tcg';
2479 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2482 my $machine_type = $forcemachine || $conf->{machine
};
2483 if ($machine_type) {
2484 push @$machineFlags, "type=${machine_type}";
2487 if ($conf->{startdate
}) {
2488 push @$rtcFlags, "base=$conf->{startdate}";
2489 } elsif ($useLocaltime) {
2490 push @$rtcFlags, 'base=localtime';
2493 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2494 $cpu = $conf->{cpu
} if $conf->{cpu
};
2496 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2498 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2500 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2502 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2504 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2506 push @$cmd, '-cpu', $cpu;
2508 push @$cmd, '-S' if $conf->{freeze
};
2510 # set keyboard layout
2511 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2512 push @$cmd, '-k', $kb if $kb;
2515 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2516 #push @$cmd, '-soundhw', 'es1370';
2517 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2519 if($conf->{agent
}) {
2520 my $qgasocket = qga_socket
($vmid);
2521 my $pciaddr = print_pci_addr
("qga0", $bridges);
2522 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2523 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2524 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2531 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2532 for(my $i = 1; $i < $qxlnum; $i++){
2533 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2534 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2537 # assume other OS works like Linux
2538 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2539 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2543 my $pciaddr = print_pci_addr
("spice", $bridges);
2545 $spice_port = PVE
::Tools
::next_spice_port
();
2547 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2549 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2550 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2551 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2554 # enable balloon by default, unless explicitly disabled
2555 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2556 $pciaddr = print_pci_addr
("balloon0", $bridges);
2557 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2560 if ($conf->{watchdog
}) {
2561 my $wdopts = parse_watchdog
($conf->{watchdog
});
2562 $pciaddr = print_pci_addr
("watchdog", $bridges);
2563 my $watchdog = $wdopts->{model
} || 'i6300esb';
2564 push @$devices, '-device', "$watchdog$pciaddr";
2565 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2569 my $scsicontroller = {};
2570 my $ahcicontroller = {};
2571 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2573 foreach_drive
($conf, sub {
2574 my ($ds, $drive) = @_;
2576 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2577 push @$vollist, $drive->{file
};
2580 $use_virtio = 1 if $ds =~ m/^virtio/;
2582 if (drive_is_cdrom
($drive)) {
2583 if ($bootindex_hash->{d
}) {
2584 $drive->{bootindex
} = $bootindex_hash->{d
};
2585 $bootindex_hash->{d
} += 1;
2588 if ($bootindex_hash->{c
}) {
2589 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2590 $bootindex_hash->{c
} += 1;
2594 if ($drive->{interface
} eq 'scsi') {
2596 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2597 my $controller = int($drive->{index} / $maxdev);
2598 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2599 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2600 $scsicontroller->{$controller}=1;
2603 if ($drive->{interface
} eq 'sata') {
2604 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2605 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2606 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2607 $ahcicontroller->{$controller}=1;
2610 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2611 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2614 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2616 for (my $i = 0; $i < $MAX_NETS; $i++) {
2617 next if !$conf->{"net$i"};
2618 my $d = parse_net
($conf->{"net$i"});
2621 $use_virtio = 1 if $d->{model
} eq 'virtio';
2623 if ($bootindex_hash->{n
}) {
2624 $d->{bootindex
} = $bootindex_hash->{n
};
2625 $bootindex_hash->{n
} += 1;
2628 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2629 push @$devices, '-netdev', $netdevfull;
2631 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2632 push @$devices, '-device', $netdevicefull;
2636 while (my ($k, $v) = each %$bridges) {
2637 $pciaddr = print_pci_addr
("pci.$k");
2638 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2642 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2643 # when the VM uses virtio devices.
2644 if (!$use_virtio && $have_ovz) {
2646 my $cpuunits = defined($conf->{cpuunits
}) ?
2647 $conf->{cpuunits
} : $defaults->{cpuunits
};
2649 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2651 # fixme: cpulimit is currently ignored
2652 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2656 if ($conf->{args
}) {
2657 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2661 push @$cmd, @$devices;
2662 push @$cmd, '-rtc', join(',', @$rtcFlags)
2663 if scalar(@$rtcFlags);
2664 push @$cmd, '-machine', join(',', @$machineFlags)
2665 if scalar(@$machineFlags);
2666 push @$cmd, '-global', join(',', @$globalFlags)
2667 if scalar(@$globalFlags);
2669 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2674 return "${var_run_tmpdir}/$vmid.vnc";
2680 my $res = vm_mon_cmd
($vmid, 'query-spice');
2682 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2687 return "${var_run_tmpdir}/$vmid.qmp";
2692 return "${var_run_tmpdir}/$vmid.qga";
2697 return "${var_run_tmpdir}/$vmid.pid";
2700 sub vm_devices_list
{
2703 my $res = vm_mon_cmd
($vmid, 'query-pci');
2706 foreach my $pcibus (@$res) {
2707 foreach my $device (@{$pcibus->{devices
}}) {
2708 next if !$device->{'qdev_id'};
2709 $devices->{$device->{'qdev_id'}} = $device;
2717 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2719 return 1 if !check_running
($vmid);
2721 if ($deviceid eq 'tablet') {
2722 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2723 qemu_deviceadd
($vmid, $devicefull);
2727 return 1 if !$conf->{hotplug
};
2729 my $devices_list = vm_devices_list
($vmid);
2730 return 1 if defined($devices_list->{$deviceid});
2732 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2734 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2735 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2736 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2737 qemu_deviceadd
($vmid, $devicefull);
2738 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2739 qemu_drivedel
($vmid, $deviceid);
2744 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2745 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2746 my $pciaddr = print_pci_addr
($deviceid);
2747 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2748 qemu_deviceadd
($vmid, $devicefull);
2749 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2752 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2753 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2754 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2755 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2756 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2757 if(!qemu_deviceadd
($vmid, $devicefull)) {
2758 qemu_drivedel
($vmid, $deviceid);
2763 if ($deviceid =~ m/^(net)(\d+)$/) {
2764 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2765 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2766 qemu_deviceadd
($vmid, $netdevicefull);
2767 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2768 qemu_netdevdel
($vmid, $deviceid);
2773 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2775 my $pciaddr = print_pci_addr
($deviceid);
2776 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2777 qemu_deviceadd
($vmid, $devicefull);
2778 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2784 sub vm_deviceunplug
{
2785 my ($vmid, $conf, $deviceid) = @_;
2787 return 1 if !check_running
($vmid);
2789 if ($deviceid eq 'tablet') {
2790 qemu_devicedel
($vmid, $deviceid);
2794 return 1 if !$conf->{hotplug
};
2796 my $devices_list = vm_devices_list
($vmid);
2797 return 1 if !defined($devices_list->{$deviceid});
2799 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2801 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2802 qemu_devicedel
($vmid, $deviceid);
2803 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2804 return undef if !qemu_drivedel
($vmid, $deviceid);
2807 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2808 return undef if !qemu_devicedel
($vmid, $deviceid);
2811 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2812 return undef if !qemu_devicedel
($vmid, $deviceid);
2813 return undef if !qemu_drivedel
($vmid, $deviceid);
2816 if ($deviceid =~ m/^(net)(\d+)$/) {
2817 qemu_devicedel
($vmid, $deviceid);
2818 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2819 return undef if !qemu_netdevdel
($vmid, $deviceid);
2825 sub qemu_deviceadd
{
2826 my ($vmid, $devicefull) = @_;
2828 $devicefull = "driver=".$devicefull;
2829 my %options = split(/[=,]/, $devicefull);
2831 vm_mon_cmd
($vmid, "device_add" , %options);
2835 sub qemu_devicedel
{
2836 my($vmid, $deviceid) = @_;
2837 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2842 my($storecfg, $vmid, $device) = @_;
2844 my $drive = print_drive_full
($storecfg, $vmid, $device);
2845 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2846 # If the command succeeds qemu prints: "OK"
2847 if ($ret !~ m/OK/s) {
2848 syslog
("err", "adding drive failed: $ret");
2855 my($vmid, $deviceid) = @_;
2857 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2859 if ($ret =~ m/Device \'.*?\' not found/s) {
2860 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2862 elsif ($ret ne "") {
2863 syslog
("err", "deleting drive $deviceid failed : $ret");
2869 sub qemu_deviceaddverify
{
2870 my ($vmid,$deviceid) = @_;
2872 for (my $i = 0; $i <= 5; $i++) {
2873 my $devices_list = vm_devices_list
($vmid);
2874 return 1 if defined($devices_list->{$deviceid});
2877 syslog
("err", "error on hotplug device $deviceid");
2882 sub qemu_devicedelverify
{
2883 my ($vmid,$deviceid) = @_;
2885 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2886 for (my $i = 0; $i <= 5; $i++) {
2887 my $devices_list = vm_devices_list
($vmid);
2888 return 1 if !defined($devices_list->{$deviceid});
2891 syslog
("err", "error on hot-unplugging device $deviceid");
2895 sub qemu_findorcreatescsihw
{
2896 my ($storecfg, $conf, $vmid, $device) = @_;
2898 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2899 my $controller = int($device->{index} / $maxdev);
2900 my $scsihwid="scsihw$controller";
2901 my $devices_list = vm_devices_list
($vmid);
2903 if(!defined($devices_list->{$scsihwid})) {
2904 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2909 sub qemu_bridgeadd
{
2910 my ($storecfg, $conf, $vmid, $device) = @_;
2913 my $bridgeid = undef;
2914 print_pci_addr
($device, $bridges);
2916 while (my ($k, $v) = each %$bridges) {
2919 return if !$bridgeid || $bridgeid < 1;
2920 my $bridge = "pci.$bridgeid";
2921 my $devices_list = vm_devices_list
($vmid);
2923 if(!defined($devices_list->{$bridge})) {
2924 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2929 sub qemu_netdevadd
{
2930 my ($vmid, $conf, $device, $deviceid) = @_;
2932 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2933 my %options = split(/[=,]/, $netdev);
2935 vm_mon_cmd
($vmid, "netdev_add", %options);
2939 sub qemu_netdevdel
{
2940 my ($vmid, $deviceid) = @_;
2942 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2946 sub qemu_cpu_hotplug
{
2947 my ($vmid, $conf, $cores) = @_;
2949 die "new cores config is not defined" if !$cores;
2950 die "you can't add more cores than maxcpus" if $conf->{maxcpus
} && ($cores > $conf->{maxcpus
});
2951 return if !check_running
($vmid);
2953 my $currentcores = $conf->{cores
} if $conf->{cores
};
2954 die "current cores is not defined" if !$currentcores;
2955 die "maxcpus is not defined" if !$conf->{maxcpus
};
2956 raise_param_exc
({ 'cores' => "online cpu unplug is not yet possible" }) if($cores < $currentcores);
2958 my $currentrunningcores = vm_mon_cmd
($vmid, "query-cpus");
2959 raise_param_exc
({ 'cores' => "cores number if running vm is different than configuration" }) if scalar (@{$currentrunningcores}) != $currentcores;
2961 for(my $i = $currentcores; $i < $cores; $i++){
2962 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
2966 sub qemu_block_set_io_throttle
{
2967 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2969 return if !check_running
($vmid) ;
2971 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));
2975 # old code, only used to shutdown old VM after update
2977 my ($fh, $timeout) = @_;
2979 my $sel = new IO
::Select
;
2986 while (scalar (@ready = $sel->can_read($timeout))) {
2988 if ($count = $fh->sysread($buf, 8192)) {
2989 if ($buf =~ /^(.*)\(qemu\) $/s) {
2996 if (!defined($count)) {
3003 die "monitor read timeout\n" if !scalar(@ready);
3008 # old code, only used to shutdown old VM after update
3009 sub vm_monitor_command
{
3010 my ($vmid, $cmdstr, $nocheck) = @_;
3015 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3017 my $sname = "${var_run_tmpdir}/$vmid.mon";
3019 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3020 die "unable to connect to VM $vmid socket - $!\n";
3024 # hack: migrate sometime blocks the monitor (when migrate_downtime
3026 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3027 $timeout = 60*60; # 1 hour
3031 my $data = __read_avail
($sock, $timeout);
3033 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3034 die "got unexpected qemu monitor banner\n";
3037 my $sel = new IO
::Select
;
3040 if (!scalar(my @ready = $sel->can_write($timeout))) {
3041 die "monitor write error - timeout";
3044 my $fullcmd = "$cmdstr\r";
3046 # syslog('info', "VM $vmid monitor command: $cmdstr");
3049 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3050 die "monitor write error - $!";
3053 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3057 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3058 $timeout = 60*60; # 1 hour
3059 } elsif ($cmdstr =~ m/^(eject|change)/) {
3060 $timeout = 60; # note: cdrom mount command is slow
3062 if ($res = __read_avail
($sock, $timeout)) {
3064 my @lines = split("\r?\n", $res);
3066 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3068 $res = join("\n", @lines);
3076 syslog
("err", "VM $vmid monitor command failed - $err");
3083 sub qemu_block_resize
{
3084 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3086 my $running = check_running
($vmid);
3088 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3090 return if !$running;
3092 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3096 sub qemu_volume_snapshot
{
3097 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3099 my $running = check_running
($vmid);
3101 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3103 return if !$running;
3105 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3109 sub qemu_volume_snapshot_delete
{
3110 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3112 my $running = check_running
($vmid);
3114 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3116 return if !$running;
3118 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3124 #need to impplement call to qemu-ga
3127 sub qga_unfreezefs
{
3130 #need to impplement call to qemu-ga
3133 sub set_migration_caps
{
3139 "auto-converge" => 1,
3141 "x-rdma-pin-all" => 0,
3145 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3147 for my $supported_capability (@$supported_capabilities) {
3148 if ($enabled_cap->{$supported_capability->{capability
}} eq 1) {
3150 capability
=> $supported_capability->{capability
},
3151 state => JSON
::true
,
3156 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3160 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3162 lock_config
($vmid, sub {
3163 my $conf = load_config
($vmid, $migratedfrom);
3165 die "you can't start a vm if it's a template\n" if is_template
($conf);
3167 check_lock
($conf) if !$skiplock;
3169 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3171 my $defaults = load_defaults
();
3173 # set environment variable useful inside network script
3174 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3176 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3178 my $migrate_port = 0;
3181 if ($statefile eq 'tcp') {
3182 my $localip = "localhost";
3183 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3184 if ($datacenterconf->{migration_unsecure
}) {
3185 my $nodename = PVE
::INotify
::nodename
();
3186 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3188 $migrate_port = PVE
::Tools
::next_migrate_port
();
3189 $migrate_uri = "tcp:${localip}:${migrate_port}";
3190 push @$cmd, '-incoming', $migrate_uri;
3193 push @$cmd, '-loadstate', $statefile;
3200 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3201 my $d = parse_hostpci
($conf->{"hostpci$i"});
3203 my $info = pci_device_info
("0000:$d->{pciid}");
3204 die "IOMMU not present\n" if !check_iommu_support
();
3205 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3206 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3207 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3210 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3212 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3215 die "start failed: $err" if $err;
3217 print "migration listens on $migrate_uri\n" if $migrate_uri;
3219 if ($statefile && $statefile ne 'tcp') {
3220 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3224 if ($migratedfrom) {
3227 PVE
::QemuServer
::set_migration_caps
($vmid);
3232 print "spice listens on port $spice_port\n";
3233 if ($spice_ticket) {
3234 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3235 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3241 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3242 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3243 if $conf->{balloon
};
3244 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3245 path
=> "machine/peripheral/balloon0",
3246 property
=> "guest-stats-polling-interval",
3254 my ($vmid, $execute, %params) = @_;
3256 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3257 vm_qmp_command
($vmid, $cmd);
3260 sub vm_mon_cmd_nocheck
{
3261 my ($vmid, $execute, %params) = @_;
3263 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3264 vm_qmp_command
($vmid, $cmd, 1);
3267 sub vm_qmp_command
{
3268 my ($vmid, $cmd, $nocheck) = @_;
3273 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3274 $timeout = $cmd->{arguments
}->{timeout
};
3275 delete $cmd->{arguments
}->{timeout
};
3279 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3280 my $sname = qmp_socket
($vmid);
3282 my $qmpclient = PVE
::QMPClient-
>new();
3284 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3285 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3286 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3287 if scalar(%{$cmd->{arguments
}});
3288 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3290 die "unable to open monitor socket\n";
3294 syslog
("err", "VM $vmid qmp command failed - $err");
3301 sub vm_human_monitor_command
{
3302 my ($vmid, $cmdline) = @_;
3307 execute
=> 'human-monitor-command',
3308 arguments
=> { 'command-line' => $cmdline},
3311 return vm_qmp_command
($vmid, $cmd);
3314 sub vm_commandline
{
3315 my ($storecfg, $vmid) = @_;
3317 my $conf = load_config
($vmid);
3319 my $defaults = load_defaults
();
3321 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3323 return join(' ', @$cmd);
3327 my ($vmid, $skiplock) = @_;
3329 lock_config
($vmid, sub {
3331 my $conf = load_config
($vmid);
3333 check_lock
($conf) if !$skiplock;
3335 vm_mon_cmd
($vmid, "system_reset");
3339 sub get_vm_volumes
{
3343 foreach_volid
($conf, sub {
3344 my ($volid, $is_cdrom) = @_;
3346 return if $volid =~ m
|^/|;
3348 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3351 push @$vollist, $volid;
3357 sub vm_stop_cleanup
{
3358 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3361 fairsched_rmnod
($vmid); # try to destroy group
3364 my $vollist = get_vm_volumes
($conf);
3365 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3368 foreach my $ext (qw(mon qmp pid vnc qga)) {
3369 unlink "/var/run/qemu-server/${vmid}.$ext";
3372 warn $@ if $@; # avoid errors - just warn
3375 # Note: use $nockeck to skip tests if VM configuration file exists.
3376 # We need that when migration VMs to other nodes (files already moved)
3377 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3379 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3381 $force = 1 if !defined($force) && !$shutdown;
3384 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3385 kill 15, $pid if $pid;
3386 my $conf = load_config
($vmid, $migratedfrom);
3387 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3391 lock_config
($vmid, sub {
3393 my $pid = check_running
($vmid, $nocheck);
3398 $conf = load_config
($vmid);
3399 check_lock
($conf) if !$skiplock;
3400 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3401 my $opts = parse_startup
($conf->{startup
});
3402 $timeout = $opts->{down
} if $opts->{down
};
3406 $timeout = 60 if !defined($timeout);
3410 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3413 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3420 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3425 if ($count >= $timeout) {
3427 warn "VM still running - terminating now with SIGTERM\n";
3430 die "VM quit/powerdown failed - got timeout\n";
3433 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3438 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3441 die "VM quit/powerdown failed\n";
3449 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3454 if ($count >= $timeout) {
3455 warn "VM still running - terminating now with SIGKILL\n";
3460 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3465 my ($vmid, $skiplock) = @_;
3467 lock_config
($vmid, sub {
3469 my $conf = load_config
($vmid);
3471 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3473 vm_mon_cmd
($vmid, "stop");
3478 my ($vmid, $skiplock) = @_;
3480 lock_config
($vmid, sub {
3482 my $conf = load_config
($vmid);
3484 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3486 vm_mon_cmd
($vmid, "cont");
3491 my ($vmid, $skiplock, $key) = @_;
3493 lock_config
($vmid, sub {
3495 my $conf = load_config
($vmid);
3497 # there is no qmp command, so we use the human monitor command
3498 vm_human_monitor_command
($vmid, "sendkey $key");
3503 my ($storecfg, $vmid, $skiplock) = @_;
3505 lock_config
($vmid, sub {
3507 my $conf = load_config
($vmid);
3509 check_lock
($conf) if !$skiplock;
3511 if (!check_running
($vmid)) {
3512 fairsched_rmnod
($vmid); # try to destroy group
3513 destroy_vm
($storecfg, $vmid);
3515 die "VM $vmid is running - destroy failed\n";
3523 my ($filename, $buf) = @_;
3525 my $fh = IO
::File-
>new($filename, "w");
3526 return undef if !$fh;
3528 my $res = print $fh $buf;
3535 sub pci_device_info
{
3540 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3541 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3543 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3544 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3546 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3547 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3549 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3550 return undef if !defined($product) || $product !~ s/^0x//;
3555 product
=> $product,
3561 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3570 my $name = $dev->{name
};
3572 my $fn = "$pcisysfs/devices/$name/reset";
3574 return file_write
($fn, "1");
3577 sub pci_dev_bind_to_stub
{
3580 my $name = $dev->{name
};
3582 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3583 return 1 if -d
$testdir;
3585 my $data = "$dev->{vendor} $dev->{product}";
3586 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3588 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3589 if (!file_write
($fn, $name)) {
3590 return undef if -f
$fn;
3593 $fn = "$pcisysfs/drivers/pci-stub/bind";
3594 if (! -d
$testdir) {
3595 return undef if !file_write
($fn, $name);
3601 sub print_pci_addr
{
3602 my ($id, $bridges) = @_;
3606 piix3
=> { bus
=> 0, addr
=> 1 },
3607 #addr2 : first videocard
3608 balloon0
=> { bus
=> 0, addr
=> 3 },
3609 watchdog
=> { bus
=> 0, addr
=> 4 },
3610 scsihw0
=> { bus
=> 0, addr
=> 5 },
3611 scsihw1
=> { bus
=> 0, addr
=> 6 },
3612 ahci0
=> { bus
=> 0, addr
=> 7 },
3613 qga0
=> { bus
=> 0, addr
=> 8 },
3614 spice
=> { bus
=> 0, addr
=> 9 },
3615 virtio0
=> { bus
=> 0, addr
=> 10 },
3616 virtio1
=> { bus
=> 0, addr
=> 11 },
3617 virtio2
=> { bus
=> 0, addr
=> 12 },
3618 virtio3
=> { bus
=> 0, addr
=> 13 },
3619 virtio4
=> { bus
=> 0, addr
=> 14 },
3620 virtio5
=> { bus
=> 0, addr
=> 15 },
3621 hostpci0
=> { bus
=> 0, addr
=> 16 },
3622 hostpci1
=> { bus
=> 0, addr
=> 17 },
3623 net0
=> { bus
=> 0, addr
=> 18 },
3624 net1
=> { bus
=> 0, addr
=> 19 },
3625 net2
=> { bus
=> 0, addr
=> 20 },
3626 net3
=> { bus
=> 0, addr
=> 21 },
3627 net4
=> { bus
=> 0, addr
=> 22 },
3628 net5
=> { bus
=> 0, addr
=> 23 },
3629 vga1
=> { bus
=> 0, addr
=> 24 },
3630 vga2
=> { bus
=> 0, addr
=> 25 },
3631 vga3
=> { bus
=> 0, addr
=> 26 },
3632 #addr29 : usb-host (pve-usb.cfg)
3633 'pci.1' => { bus
=> 0, addr
=> 30 },
3634 'pci.2' => { bus
=> 0, addr
=> 31 },
3635 'net6' => { bus
=> 1, addr
=> 1 },
3636 'net7' => { bus
=> 1, addr
=> 2 },
3637 'net8' => { bus
=> 1, addr
=> 3 },
3638 'net9' => { bus
=> 1, addr
=> 4 },
3639 'net10' => { bus
=> 1, addr
=> 5 },
3640 'net11' => { bus
=> 1, addr
=> 6 },
3641 'net12' => { bus
=> 1, addr
=> 7 },
3642 'net13' => { bus
=> 1, addr
=> 8 },
3643 'net14' => { bus
=> 1, addr
=> 9 },
3644 'net15' => { bus
=> 1, addr
=> 10 },
3645 'net16' => { bus
=> 1, addr
=> 11 },
3646 'net17' => { bus
=> 1, addr
=> 12 },
3647 'net18' => { bus
=> 1, addr
=> 13 },
3648 'net19' => { bus
=> 1, addr
=> 14 },
3649 'net20' => { bus
=> 1, addr
=> 15 },
3650 'net21' => { bus
=> 1, addr
=> 16 },
3651 'net22' => { bus
=> 1, addr
=> 17 },
3652 'net23' => { bus
=> 1, addr
=> 18 },
3653 'net24' => { bus
=> 1, addr
=> 19 },
3654 'net25' => { bus
=> 1, addr
=> 20 },
3655 'net26' => { bus
=> 1, addr
=> 21 },
3656 'net27' => { bus
=> 1, addr
=> 22 },
3657 'net28' => { bus
=> 1, addr
=> 23 },
3658 'net29' => { bus
=> 1, addr
=> 24 },
3659 'net30' => { bus
=> 1, addr
=> 25 },
3660 'net31' => { bus
=> 1, addr
=> 26 },
3661 'virtio6' => { bus
=> 2, addr
=> 1 },
3662 'virtio7' => { bus
=> 2, addr
=> 2 },
3663 'virtio8' => { bus
=> 2, addr
=> 3 },
3664 'virtio9' => { bus
=> 2, addr
=> 4 },
3665 'virtio10' => { bus
=> 2, addr
=> 5 },
3666 'virtio11' => { bus
=> 2, addr
=> 6 },
3667 'virtio12' => { bus
=> 2, addr
=> 7 },
3668 'virtio13' => { bus
=> 2, addr
=> 8 },
3669 'virtio14' => { bus
=> 2, addr
=> 9 },
3670 'virtio15' => { bus
=> 2, addr
=> 10 },
3673 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3674 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3675 my $bus = $devices->{$id}->{bus
};
3676 $res = ",bus=pci.$bus,addr=$addr";
3677 $bridges->{$bus} = 1 if $bridges;
3683 # vzdump restore implementaion
3685 sub tar_archive_read_firstfile
{
3686 my $archive = shift;
3688 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3690 # try to detect archive type first
3691 my $pid = open (TMP
, "tar tf '$archive'|") ||
3692 die "unable to open file '$archive'\n";
3693 my $firstfile = <TMP
>;
3697 die "ERROR: archive contaions no data\n" if !$firstfile;
3703 sub tar_restore_cleanup
{
3704 my ($storecfg, $statfile) = @_;
3706 print STDERR
"starting cleanup\n";
3708 if (my $fd = IO
::File-
>new($statfile, "r")) {
3709 while (defined(my $line = <$fd>)) {
3710 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3713 if ($volid =~ m
|^/|) {
3714 unlink $volid || die 'unlink failed\n';
3716 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3718 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3720 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3722 print STDERR
"unable to parse line in statfile - $line";
3729 sub restore_archive
{
3730 my ($archive, $vmid, $user, $opts) = @_;
3732 my $format = $opts->{format
};
3735 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3736 $format = 'tar' if !$format;
3738 } elsif ($archive =~ m/\.tar$/) {
3739 $format = 'tar' if !$format;
3740 } elsif ($archive =~ m/.tar.lzo$/) {
3741 $format = 'tar' if !$format;
3743 } elsif ($archive =~ m/\.vma$/) {
3744 $format = 'vma' if !$format;
3745 } elsif ($archive =~ m/\.vma\.gz$/) {
3746 $format = 'vma' if !$format;
3748 } elsif ($archive =~ m/\.vma\.lzo$/) {
3749 $format = 'vma' if !$format;
3752 $format = 'vma' if !$format; # default
3755 # try to detect archive format
3756 if ($format eq 'tar') {
3757 return restore_tar_archive
($archive, $vmid, $user, $opts);
3759 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3763 sub restore_update_config_line
{
3764 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3766 return if $line =~ m/^\#qmdump\#/;
3767 return if $line =~ m/^\#vzdump\#/;
3768 return if $line =~ m/^lock:/;
3769 return if $line =~ m/^unused\d+:/;
3770 return if $line =~ m/^parent:/;
3771 return if $line =~ m/^template:/; # restored VM is never a template
3773 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3774 # try to convert old 1.X settings
3775 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3776 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3777 my ($model, $macaddr) = split(/\=/, $devconfig);
3778 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3781 bridge
=> "vmbr$ind",
3782 macaddr
=> $macaddr,
3784 my $netstr = print_net
($net);
3786 print $outfd "net$cookie->{netcount}: $netstr\n";
3787 $cookie->{netcount
}++;
3789 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3790 my ($id, $netstr) = ($1, $2);
3791 my $net = parse_net
($netstr);
3792 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3793 $netstr = print_net
($net);
3794 print $outfd "$id: $netstr\n";
3795 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3798 if ($line =~ m/backup=no/) {
3799 print $outfd "#$line";
3800 } elsif ($virtdev && $map->{$virtdev}) {
3801 my $di = parse_drive
($virtdev, $value);
3802 delete $di->{format
}; # format can change on restore
3803 $di->{file
} = $map->{$virtdev};
3804 $value = print_drive
($vmid, $di);
3805 print $outfd "$virtdev: $value\n";
3815 my ($cfg, $vmid) = @_;
3817 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3819 my $volid_hash = {};
3820 foreach my $storeid (keys %$info) {
3821 foreach my $item (@{$info->{$storeid}}) {
3822 next if !($item->{volid
} && $item->{size
});
3823 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3824 $volid_hash->{$item->{volid
}} = $item;
3831 sub get_used_paths
{
3832 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3836 my $scan_config = sub {
3837 my ($cref, $snapname) = @_;
3839 foreach my $key (keys %$cref) {
3840 my $value = $cref->{$key};
3841 if (valid_drivename
($key)) {
3842 next if $skip_drive && $key eq $skip_drive;
3843 my $drive = parse_drive
($key, $value);
3844 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3845 if ($drive->{file
} =~ m!^/!) {
3846 $used_path->{$drive->{file
}}++; # = 1;
3848 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3850 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3852 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3853 $used_path->{$path}++; # = 1;
3859 &$scan_config($conf);
3863 if ($scan_snapshots) {
3864 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3865 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3872 sub update_disksize
{
3873 my ($vmid, $conf, $volid_hash) = @_;
3879 # Note: it is allowed to define multiple storages with same path (alias), so
3880 # we need to check both 'volid' and real 'path' (two different volid can point
3881 # to the same path).
3886 foreach my $opt (keys %$conf) {
3887 if (valid_drivename
($opt)) {
3888 my $drive = parse_drive
($opt, $conf->{$opt});
3889 my $volid = $drive->{file
};
3892 $used->{$volid} = 1;
3893 if ($volid_hash->{$volid} &&
3894 (my $path = $volid_hash->{$volid}->{path
})) {
3895 $usedpath->{$path} = 1;
3898 next if drive_is_cdrom
($drive);
3899 next if !$volid_hash->{$volid};
3901 $drive->{size
} = $volid_hash->{$volid}->{size
};
3902 my $new = print_drive
($vmid, $drive);
3903 if ($new ne $conf->{$opt}) {
3905 $conf->{$opt} = $new;
3910 # remove 'unusedX' entry if volume is used
3911 foreach my $opt (keys %$conf) {
3912 next if $opt !~ m/^unused\d+$/;
3913 my $volid = $conf->{$opt};
3914 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3915 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3917 delete $conf->{$opt};
3921 foreach my $volid (sort keys %$volid_hash) {
3922 next if $volid =~ m/vm-$vmid-state-/;
3923 next if $used->{$volid};
3924 my $path = $volid_hash->{$volid}->{path
};
3925 next if !$path; # just to be sure
3926 next if $usedpath->{$path};
3928 add_unused_volume
($conf, $volid);
3929 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3936 my ($vmid, $nolock) = @_;
3938 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3940 my $volid_hash = scan_volids
($cfg, $vmid);
3942 my $updatefn = sub {
3945 my $conf = load_config
($vmid);
3950 foreach my $volid (keys %$volid_hash) {
3951 my $info = $volid_hash->{$volid};
3952 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3955 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3957 update_config_nolock
($vmid, $conf, 1) if $changes;
3960 if (defined($vmid)) {
3964 lock_config
($vmid, $updatefn, $vmid);
3967 my $vmlist = config_list
();
3968 foreach my $vmid (keys %$vmlist) {
3972 lock_config
($vmid, $updatefn, $vmid);
3978 sub restore_vma_archive
{
3979 my ($archive, $vmid, $user, $opts, $comp) = @_;
3981 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3982 my $readfrom = $archive;
3987 my $qarchive = PVE
::Tools
::shellquote
($archive);
3988 if ($comp eq 'gzip') {
3989 $uncomp = "zcat $qarchive|";
3990 } elsif ($comp eq 'lzop') {
3991 $uncomp = "lzop -d -c $qarchive|";
3993 die "unknown compression method '$comp'\n";
3998 my $tmpdir = "/var/tmp/vzdumptmp$$";
4001 # disable interrupts (always do cleanups)
4002 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4003 warn "got interrupt - ignored\n";
4006 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4007 POSIX
::mkfifo
($mapfifo, 0600);
4010 my $openfifo = sub {
4011 open($fifofh, '>', $mapfifo) || die $!;
4014 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4021 my $rpcenv = PVE
::RPCEnvironment
::get
();
4023 my $conffile = config_file
($vmid);
4024 my $tmpfn = "$conffile.$$.tmp";
4026 # Note: $oldconf is undef if VM does not exists
4027 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4029 my $print_devmap = sub {
4030 my $virtdev_hash = {};
4032 my $cfgfn = "$tmpdir/qemu-server.conf";
4034 # we can read the config - that is already extracted
4035 my $fh = IO
::File-
>new($cfgfn, "r") ||
4036 "unable to read qemu-server.conf - $!\n";
4038 while (defined(my $line = <$fh>)) {
4039 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4040 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4041 die "archive does not contain data for drive '$virtdev'\n"
4042 if !$devinfo->{$devname};
4043 if (defined($opts->{storage
})) {
4044 $storeid = $opts->{storage
} || 'local';
4045 } elsif (!$storeid) {
4048 $format = 'raw' if !$format;
4049 $devinfo->{$devname}->{devname
} = $devname;
4050 $devinfo->{$devname}->{virtdev
} = $virtdev;
4051 $devinfo->{$devname}->{format
} = $format;
4052 $devinfo->{$devname}->{storeid
} = $storeid;
4054 # check permission on storage
4055 my $pool = $opts->{pool
}; # todo: do we need that?
4056 if ($user ne 'root@pam') {
4057 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4060 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4064 foreach my $devname (keys %$devinfo) {
4065 die "found no device mapping information for device '$devname'\n"
4066 if !$devinfo->{$devname}->{virtdev
};
4069 my $cfg = cfs_read_file
('storage.cfg');
4071 # create empty/temp config
4073 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4074 foreach_drive
($oldconf, sub {
4075 my ($ds, $drive) = @_;
4077 return if drive_is_cdrom
($drive);
4079 my $volid = $drive->{file
};
4081 return if !$volid || $volid =~ m
|^/|;
4083 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4084 return if !$path || !$owner || ($owner != $vmid);
4086 # Note: only delete disk we want to restore
4087 # other volumes will become unused
4088 if ($virtdev_hash->{$ds}) {
4089 PVE
::Storage
::vdisk_free
($cfg, $volid);
4095 foreach my $virtdev (sort keys %$virtdev_hash) {
4096 my $d = $virtdev_hash->{$virtdev};
4097 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4098 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4100 # test if requested format is supported
4101 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4102 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4103 $d->{format
} = $defFormat if !$supported;
4105 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4106 $d->{format
}, undef, $alloc_size);
4107 print STDERR
"new volume ID is '$volid'\n";
4108 $d->{volid
} = $volid;
4109 my $path = PVE
::Storage
::path
($cfg, $volid);
4111 my $write_zeros = 1;
4112 # fixme: what other storages types initialize volumes with zero?
4113 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4114 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4118 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4120 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4121 $map->{$virtdev} = $volid;
4124 $fh->seek(0, 0) || die "seek failed - $!\n";
4126 my $outfd = new IO
::File
($tmpfn, "w") ||
4127 die "unable to write config for VM $vmid\n";
4129 my $cookie = { netcount
=> 0 };
4130 while (defined(my $line = <$fh>)) {
4131 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4140 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4141 die "interrupted by signal\n";
4143 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4145 $oldtimeout = alarm($timeout);
4152 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4153 my ($dev_id, $size, $devname) = ($1, $2, $3);
4154 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4155 } elsif ($line =~ m/^CTIME: /) {
4157 print $fifofh "done\n";
4158 my $tmp = $oldtimeout || 0;
4159 $oldtimeout = undef;
4165 print "restore vma archive: $cmd\n";
4166 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4170 alarm($oldtimeout) if $oldtimeout;
4178 my $cfg = cfs_read_file
('storage.cfg');
4179 foreach my $devname (keys %$devinfo) {
4180 my $volid = $devinfo->{$devname}->{volid
};
4183 if ($volid =~ m
|^/|) {
4184 unlink $volid || die 'unlink failed\n';
4186 PVE
::Storage
::vdisk_free
($cfg, $volid);
4188 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4190 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4197 rename($tmpfn, $conffile) ||
4198 die "unable to commit configuration file '$conffile'\n";
4200 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4202 eval { rescan
($vmid, 1); };
4206 sub restore_tar_archive
{
4207 my ($archive, $vmid, $user, $opts) = @_;
4209 if ($archive ne '-') {
4210 my $firstfile = tar_archive_read_firstfile
($archive);
4211 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4212 if $firstfile ne 'qemu-server.conf';
4215 my $storecfg = cfs_read_file
('storage.cfg');
4217 # destroy existing data - keep empty config
4218 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4219 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4221 my $tocmd = "/usr/lib/qemu-server/qmextract";
4223 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4224 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4225 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4226 $tocmd .= ' --info' if $opts->{info
};
4228 # tar option "xf" does not autodetect compression when read from STDIN,
4229 # so we pipe to zcat
4230 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4231 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4233 my $tmpdir = "/var/tmp/vzdumptmp$$";
4236 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4237 local $ENV{VZDUMP_VMID
} = $vmid;
4238 local $ENV{VZDUMP_USER
} = $user;
4240 my $conffile = config_file
($vmid);
4241 my $tmpfn = "$conffile.$$.tmp";
4243 # disable interrupts (always do cleanups)
4244 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4245 print STDERR
"got interrupt - ignored\n";
4250 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4251 die "interrupted by signal\n";
4254 if ($archive eq '-') {
4255 print "extracting archive from STDIN\n";
4256 run_command
($cmd, input
=> "<&STDIN");
4258 print "extracting archive '$archive'\n";
4262 return if $opts->{info
};
4266 my $statfile = "$tmpdir/qmrestore.stat";
4267 if (my $fd = IO
::File-
>new($statfile, "r")) {
4268 while (defined (my $line = <$fd>)) {
4269 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4270 $map->{$1} = $2 if $1;
4272 print STDERR
"unable to parse line in statfile - $line\n";
4278 my $confsrc = "$tmpdir/qemu-server.conf";
4280 my $srcfd = new IO
::File
($confsrc, "r") ||
4281 die "unable to open file '$confsrc'\n";
4283 my $outfd = new IO
::File
($tmpfn, "w") ||
4284 die "unable to write config for VM $vmid\n";
4286 my $cookie = { netcount
=> 0 };
4287 while (defined (my $line = <$srcfd>)) {
4288 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4300 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4307 rename $tmpfn, $conffile ||
4308 die "unable to commit configuration file '$conffile'\n";
4310 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4312 eval { rescan
($vmid, 1); };
4317 # Internal snapshots
4319 # NOTE: Snapshot create/delete involves several non-atomic
4320 # action, and can take a long time.
4321 # So we try to avoid locking the file and use 'lock' variable
4322 # inside the config file instead.
4324 my $snapshot_copy_config = sub {
4325 my ($source, $dest) = @_;
4327 foreach my $k (keys %$source) {
4328 next if $k eq 'snapshots';
4329 next if $k eq 'snapstate';
4330 next if $k eq 'snaptime';
4331 next if $k eq 'vmstate';
4332 next if $k eq 'lock';
4333 next if $k eq 'digest';
4334 next if $k eq 'description';
4335 next if $k =~ m/^unused\d+$/;
4337 $dest->{$k} = $source->{$k};
4341 my $snapshot_apply_config = sub {
4342 my ($conf, $snap) = @_;
4344 # copy snapshot list
4346 snapshots
=> $conf->{snapshots
},
4349 # keep description and list of unused disks
4350 foreach my $k (keys %$conf) {
4351 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4352 $newconf->{$k} = $conf->{$k};
4355 &$snapshot_copy_config($snap, $newconf);
4360 sub foreach_writable_storage
{
4361 my ($conf, $func) = @_;
4365 foreach my $ds (keys %$conf) {
4366 next if !valid_drivename
($ds);
4368 my $drive = parse_drive
($ds, $conf->{$ds});
4370 next if drive_is_cdrom
($drive);
4372 my $volid = $drive->{file
};
4374 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4375 $sidhash->{$sid} = $sid if $sid;
4378 foreach my $sid (sort keys %$sidhash) {
4383 my $alloc_vmstate_volid = sub {
4384 my ($storecfg, $vmid, $conf, $snapname) = @_;
4386 # Note: we try to be smart when selecting a $target storage
4390 # search shared storage first
4391 foreach_writable_storage
($conf, sub {
4393 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4394 return if !$scfg->{shared
};
4396 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4400 # now search local storage
4401 foreach_writable_storage
($conf, sub {
4403 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4404 return if $scfg->{shared
};
4406 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4410 $target = 'local' if !$target;
4412 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4413 # we abort live save after $conf->{memory}, so we need at max twice that space
4414 my $size = $conf->{memory
}*2 + $driver_state_size;
4416 my $name = "vm-$vmid-state-$snapname";
4417 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4418 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4419 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4424 my $snapshot_prepare = sub {
4425 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4429 my $updatefn = sub {
4431 my $conf = load_config
($vmid);
4433 die "you can't take a snapshot if it's a template\n"
4434 if is_template
($conf);
4438 $conf->{lock} = 'snapshot';
4440 die "snapshot name '$snapname' already used\n"
4441 if defined($conf->{snapshots
}->{$snapname});
4443 my $storecfg = PVE
::Storage
::config
();
4444 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4446 $snap = $conf->{snapshots
}->{$snapname} = {};
4448 if ($save_vmstate && check_running
($vmid)) {
4449 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4452 &$snapshot_copy_config($conf, $snap);
4454 $snap->{snapstate
} = "prepare";
4455 $snap->{snaptime
} = time();
4456 $snap->{description
} = $comment if $comment;
4458 # always overwrite machine if we save vmstate. This makes sure we
4459 # can restore it later using correct machine type
4460 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4462 update_config_nolock
($vmid, $conf, 1);
4465 lock_config
($vmid, $updatefn);
4470 my $snapshot_commit = sub {
4471 my ($vmid, $snapname) = @_;
4473 my $updatefn = sub {
4475 my $conf = load_config
($vmid);
4477 die "missing snapshot lock\n"
4478 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4480 my $snap = $conf->{snapshots
}->{$snapname};
4482 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4484 die "wrong snapshot state\n"
4485 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4487 delete $snap->{snapstate
};
4488 delete $conf->{lock};
4490 my $newconf = &$snapshot_apply_config($conf, $snap);
4492 $newconf->{parent
} = $snapname;
4494 update_config_nolock
($vmid, $newconf, 1);
4497 lock_config
($vmid, $updatefn);
4500 sub snapshot_rollback
{
4501 my ($vmid, $snapname) = @_;
4507 my $storecfg = PVE
::Storage
::config
();
4509 my $updatefn = sub {
4511 my $conf = load_config
($vmid);
4513 die "you can't rollback if vm is a template\n" if is_template
($conf);
4515 $snap = $conf->{snapshots
}->{$snapname};
4517 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4519 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4520 if $snap->{snapstate
};
4524 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4527 die "unable to rollback vm $vmid: vm is running\n"
4528 if check_running
($vmid);
4531 $conf->{lock} = 'rollback';
4533 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4534 delete $conf->{lock};
4540 my $has_machine_config = defined($conf->{machine
});
4542 # copy snapshot config to current config
4543 $conf = &$snapshot_apply_config($conf, $snap);
4544 $conf->{parent
} = $snapname;
4546 # Note: old code did not store 'machine', so we try to be smart
4547 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4548 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4549 # we remove the 'machine' configuration if not explicitly specified
4550 # in the original config.
4551 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4554 update_config_nolock
($vmid, $conf, 1);
4556 if (!$prepare && $snap->{vmstate
}) {
4557 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4558 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4562 lock_config
($vmid, $updatefn);
4564 foreach_drive
($snap, sub {
4565 my ($ds, $drive) = @_;
4567 return if drive_is_cdrom
($drive);
4569 my $volid = $drive->{file
};
4570 my $device = "drive-$ds";
4572 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4576 lock_config
($vmid, $updatefn);
4579 my $savevm_wait = sub {
4583 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4584 if (!$stat->{status
}) {
4585 die "savevm not active\n";
4586 } elsif ($stat->{status
} eq 'active') {
4589 } elsif ($stat->{status
} eq 'completed') {
4592 die "query-savevm returned status '$stat->{status}'\n";
4597 sub snapshot_create
{
4598 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4600 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4602 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4606 my $running = check_running
($vmid);
4609 # create internal snapshots of all drives
4611 my $storecfg = PVE
::Storage
::config
();
4614 if ($snap->{vmstate
}) {
4615 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4616 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4617 &$savevm_wait($vmid);
4619 vm_mon_cmd
($vmid, "savevm-start");
4623 qga_freezefs
($vmid) if $running && $freezefs;
4625 foreach_drive
($snap, sub {
4626 my ($ds, $drive) = @_;
4628 return if drive_is_cdrom
($drive);
4630 my $volid = $drive->{file
};
4631 my $device = "drive-$ds";
4633 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4634 $drivehash->{$ds} = 1;
4639 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4642 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4646 warn "snapshot create failed: starting cleanup\n";
4647 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4652 &$snapshot_commit($vmid, $snapname);
4655 # Note: $drivehash is only set when called from snapshot_create.
4656 sub snapshot_delete
{
4657 my ($vmid, $snapname, $force, $drivehash) = @_;
4664 my $unlink_parent = sub {
4665 my ($confref, $new_parent) = @_;
4667 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4669 $confref->{parent
} = $new_parent;
4671 delete $confref->{parent
};
4676 my $updatefn = sub {
4677 my ($remove_drive) = @_;
4679 my $conf = load_config
($vmid);
4683 die "you can't delete a snapshot if vm is a template\n"
4684 if is_template
($conf);
4687 $snap = $conf->{snapshots
}->{$snapname};
4689 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4691 # remove parent refs
4692 &$unlink_parent($conf, $snap->{parent
});
4693 foreach my $sn (keys %{$conf->{snapshots
}}) {
4694 next if $sn eq $snapname;
4695 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4698 if ($remove_drive) {
4699 if ($remove_drive eq 'vmstate') {
4700 delete $snap->{$remove_drive};
4702 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4703 my $volid = $drive->{file
};
4704 delete $snap->{$remove_drive};
4705 add_unused_volume
($conf, $volid);
4710 $snap->{snapstate
} = 'delete';
4712 delete $conf->{snapshots
}->{$snapname};
4713 delete $conf->{lock} if $drivehash;
4714 foreach my $volid (@$unused) {
4715 add_unused_volume
($conf, $volid);
4719 update_config_nolock
($vmid, $conf, 1);
4722 lock_config
($vmid, $updatefn);
4724 # now remove vmstate file
4726 my $storecfg = PVE
::Storage
::config
();
4728 if ($snap->{vmstate
}) {
4729 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4731 die $err if !$force;
4734 # save changes (remove vmstate from snapshot)
4735 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4738 # now remove all internal snapshots
4739 foreach_drive
($snap, sub {
4740 my ($ds, $drive) = @_;
4742 return if drive_is_cdrom
($drive);
4744 my $volid = $drive->{file
};
4745 my $device = "drive-$ds";
4747 if (!$drivehash || $drivehash->{$ds}) {
4748 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4750 die $err if !$force;
4755 # save changes (remove drive fron snapshot)
4756 lock_config
($vmid, $updatefn, $ds) if !$force;
4757 push @$unused, $volid;
4760 # now cleanup config
4762 lock_config
($vmid, $updatefn);
4766 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4769 foreach_drive
($conf, sub {
4770 my ($ds, $drive) = @_;
4772 return if drive_is_cdrom
($drive);
4773 my $volid = $drive->{file
};
4774 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4777 return $err ?
0 : 1;
4780 sub template_create
{
4781 my ($vmid, $conf, $disk) = @_;
4783 my $storecfg = PVE
::Storage
::config
();
4785 foreach_drive
($conf, sub {
4786 my ($ds, $drive) = @_;
4788 return if drive_is_cdrom
($drive);
4789 return if $disk && $ds ne $disk;
4791 my $volid = $drive->{file
};
4792 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4794 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4795 $drive->{file
} = $voliddst;
4796 $conf->{$ds} = print_drive
($vmid, $drive);
4797 update_config_nolock
($vmid, $conf, 1);
4804 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4807 sub qemu_img_convert
{
4808 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4810 my $storecfg = PVE
::Storage
::config
();
4811 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4812 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4814 if ($src_storeid && $dst_storeid) {
4815 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4816 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4818 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4819 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4821 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4822 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4825 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4826 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4827 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4831 if($line =~ m/\((\S+)\/100\
%\)/){
4833 my $transferred = int($size * $percent / 100);
4834 my $remaining = $size - $transferred;
4836 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4841 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4843 die "copy failed: $err" if $err;
4847 sub qemu_img_format
{
4848 my ($scfg, $volname) = @_;
4850 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4852 } elsif ($scfg->{type
} eq 'iscsi') {
4853 return "host_device";
4859 sub qemu_drive_mirror
{
4860 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4866 my $storecfg = PVE
::Storage
::config
();
4867 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4870 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4873 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4877 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4880 #fixme : sometime drive-mirror timeout, but works fine after.
4881 # (I have see the problem with big volume > 200GB), so we need to eval
4882 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4883 sync
=> "full", target
=> $dst_path, format
=> $format); };
4885 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4886 sync
=> "full", target
=> $dst_path); };
4891 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4892 my $stat = @$stats[0];
4893 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4894 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4896 my $transferred = $stat->{offset
};
4897 my $total = $stat->{len
};
4898 my $remaining = $total - $transferred;
4899 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4901 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4903 last if ($stat->{len
} == $stat->{offset
});
4904 if ($old_len == $stat->{offset
}) {
4905 if ($maxwait && $count > $maxwait) {
4906 # if writes to disk occurs the disk needs to be freezed
4907 # to be able to complete the migration
4908 vm_suspend
($vmid,1);
4912 $count++ unless $frozen;
4918 $old_len = $stat->{offset
};
4922 if ($vmiddst == $vmid) {
4923 # switch the disk if source and destination are on the same guest
4924 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4928 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4929 die "mirroring error: $err";
4932 if ($vmiddst != $vmid) {
4933 # if we clone a disk for a new target vm, we don't switch the disk
4934 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4940 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4941 $newvmid, $storage, $format, $full, $newvollist) = @_;
4946 print "create linked clone of drive $drivename ($drive->{file})\n";
4947 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4948 push @$newvollist, $newvolid;
4950 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4951 $storeid = $storage if $storage;
4953 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4955 $format = $drive->{format
} || $defFormat;
4958 # test if requested format is supported - else use default
4959 my $supported = grep { $_ eq $format } @$validFormats;
4960 $format = $defFormat if !$supported;
4962 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4964 print "create full clone of drive $drivename ($drive->{file})\n";
4965 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4966 push @$newvollist, $newvolid;
4968 if (!$running || $snapname) {
4969 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4971 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4975 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4978 $disk->{format
} = undef;
4979 $disk->{file
} = $newvolid;
4980 $disk->{size
} = $size;
4985 # this only works if VM is running
4986 sub get_current_qemu_machine
{
4989 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4990 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4992 my ($current, $default);
4993 foreach my $e (@$res) {
4994 $default = $e->{name
} if $e->{'is-default'};
4995 $current = $e->{name
} if $e->{'is-current'};
4998 # fallback to the default machine if current is not supported by qemu
4999 return $current || $default || 'pc';