1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
36 # Note about locking: we use flock on the config file protect
37 # against concurent actions.
38 # Aditionaly, we have a 'lock' setting in the config file. This
39 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
40 # allowed when such lock is set. But you can ignore this kind of
41 # lock with the --skiplock flag.
43 cfs_register_file
('/qemu-server/',
47 PVE
::JSONSchema
::register_standard_option
('skiplock', {
48 description
=> "Ignore locks - only root is allowed to use this option.",
53 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
54 description
=> "Some command save/restore state from this location.",
60 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
61 description
=> "The name of the snapshot.",
62 type
=> 'string', format
=> 'pve-configid',
66 #no warnings 'redefine';
68 unless(defined(&_VZSYSCALLS_H_
)) {
69 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
70 require 'sys/syscall.ph';
71 if(defined(&__x86_64__
)) {
72 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
73 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
74 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
75 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
76 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
77 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
78 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
79 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
81 elsif(defined( &__i386__
) ) {
82 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
83 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
84 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
85 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
86 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
87 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
88 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
89 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
91 die("no fairsched syscall for this arch");
93 require 'asm/ioctl.ph';
94 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
98 my ($parent, $weight, $desired) = @_;
100 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
103 sub fairsched_rmnod
{
106 return syscall(&__NR_fairsched_rmnod
, int($id));
110 my ($pid, $newid) = @_;
112 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
115 sub fairsched_vcpus
{
116 my ($id, $vcpus) = @_;
118 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
122 my ($id, $op, $rate) = @_;
124 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
127 use constant FAIRSCHED_SET_RATE
=> 0;
128 use constant FAIRSCHED_DROP_RATE
=> 1;
129 use constant FAIRSCHED_GET_RATE
=> 2;
131 sub fairsched_cpulimit
{
132 my ($id, $limit) = @_;
134 my $cpulim1024 = int($limit * 1024 / 100);
135 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
137 return fairsched_rate
($id, $op, $cpulim1024);
140 my $nodename = PVE
::INotify
::nodename
();
142 mkdir "/etc/pve/nodes/$nodename";
143 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
146 my $var_run_tmpdir = "/var/run/qemu-server";
147 mkdir $var_run_tmpdir;
149 my $lock_dir = "/var/lock/qemu-server";
152 my $pcisysfs = "/sys/bus/pci";
158 description
=> "Specifies whether a VM will be started during system bootup.",
164 description
=> "Automatic restart after crash (currently ignored).",
170 description
=> "Allow hotplug for disk and network device",
176 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
182 description
=> "Lock/unlock the VM.",
183 enum
=> [qw(migrate backup snapshot rollback)],
188 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
195 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
203 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
210 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
216 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
224 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
225 enum
=> PVE
::Tools
::kvmkeymaplist
(),
230 type
=> 'string', format
=> 'dns-name',
231 description
=> "Set a name for the VM. Only used on the configuration web interface.",
236 description
=> "scsi controller model",
237 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)],
243 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
248 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
249 description
=> <<EODESC,
250 Used to enable special optimization/features for specific
253 other => unspecified OS
254 wxp => Microsoft Windows XP
255 w2k => Microsoft Windows 2000
256 w2k3 => Microsoft Windows 2003
257 w2k8 => Microsoft Windows 2008
258 wvista => Microsoft Windows Vista
259 win7 => Microsoft Windows 7
260 win8 => Microsoft Windows 8/2012
261 l24 => Linux 2.4 Kernel
262 l26 => Linux 2.6/3.X Kernel
263 solaris => solaris/opensolaris/openindiania kernel
265 other|l24|l26|solaris ... no special behaviour
266 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
272 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
273 pattern
=> '[acdn]{1,4}',
278 type
=> 'string', format
=> 'pve-qm-bootdisk',
279 description
=> "Enable booting from specified disk.",
280 pattern
=> '(ide|sata|scsi|virtio)\d+',
285 description
=> "The number of CPUs. Please use option -sockets instead.",
292 description
=> "The number of CPU sockets.",
299 description
=> "The number of cores per socket.",
306 description
=> "Maximum cpus for hotplug.",
313 description
=> "Enable/disable ACPI.",
319 description
=> "Enable/disable Qemu GuestAgent.",
325 description
=> "Enable/disable KVM hardware virtualization.",
331 description
=> "Enable/disable time drift fix.",
337 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
342 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
347 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
348 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
352 type
=> 'string', format
=> 'pve-qm-watchdog',
353 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
354 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
359 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
360 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
361 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
366 type
=> 'string', format
=> 'pve-qm-startup',
367 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
368 description
=> "Startup and shutdown behavior. Order is a non-negative number defining the general startup order. Shutdown in done with reverse ordering. Additionally you can set the 'up' or 'down' delay in seconds, which specifies a delay to wait before the next VM is started or stopped.",
373 description
=> "Enable/disable Template.",
379 description
=> <<EODESCR,
380 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
382 args: -no-reboot -no-hpet
389 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
394 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
398 migrate_downtime
=> {
401 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
407 type
=> 'string', format
=> 'pve-qm-drive',
408 typetext
=> 'volume',
409 description
=> "This is an alias for option -ide2",
413 description
=> "Emulated CPU type.",
415 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
418 parent
=> get_standard_option
('pve-snapshot-name', {
420 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
424 description
=> "Timestamp for snapshots.",
430 type
=> 'string', format
=> 'pve-volume-id',
431 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
434 description
=> "Specific the Qemu machine type.",
436 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
442 # what about other qemu settings ?
444 #machine => 'string',
457 ##soundhw => 'string',
459 while (my ($k, $v) = each %$confdesc) {
460 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
463 my $MAX_IDE_DISKS = 4;
464 my $MAX_SCSI_DISKS = 14;
465 my $MAX_VIRTIO_DISKS = 16;
466 my $MAX_SATA_DISKS = 6;
467 my $MAX_USB_DEVICES = 5;
469 my $MAX_UNUSED_DISKS = 8;
470 my $MAX_HOSTPCI_DEVICES = 2;
471 my $MAX_SERIAL_PORTS = 4;
472 my $MAX_PARALLEL_PORTS = 3;
474 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
475 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3'];
476 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
480 type
=> 'string', format
=> 'pve-qm-net',
481 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>][,firewall=0|1]",
482 description
=> <<EODESCR,
483 Specify network devices.
485 MODEL is one of: $nic_model_list_txt
487 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
488 automatically generated if not specified.
490 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
492 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
494 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
500 The DHCP server assign addresses to the guest starting from 10.0.2.15.
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
506 for (my $i = 0; $i < $MAX_NETS; $i++) {
507 $confdesc->{"net$i"} = $netdesc;
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
516 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
524 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
530 type
=> 'string', format
=> 'pve-qm-drive',
531 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
532 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
534 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
538 type
=> 'string', format
=> 'pve-qm-drive',
539 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
540 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
542 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
546 type
=> 'string', format
=> 'pve-qm-usb-device',
547 typetext
=> 'host=HOSTUSBDEVICE|spice',
548 description
=> <<EODESCR,
549 Configure an USB device (n is 0 to 4). This can be used to
550 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
552 'bus-port(.port)*' (decimal numbers) or
553 'vendor_id:product_id' (hexadeciaml numbers)
555 You can use the 'lsusb -t' command to list existing usb devices.
557 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
559 The value 'spice' can be used to add a usb redirection devices for spice.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
567 type
=> 'string', format
=> 'pve-qm-hostpci',
568 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]",
569 description
=> <<EODESCR,
570 Map host pci devices. HOSTPCIDEVICE syntax is:
572 'bus:dev.func' (hexadecimal numbers)
574 You can us the 'lspci' command to list existing pci devices.
576 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
578 The 'driver' option is currently ignored.
580 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
582 Experimental: user reported problems with this option.
585 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
590 pattern
=> '(/dev/ttyS\d+|socket)',
591 description
=> <<EODESCR,
592 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
594 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
596 Experimental: user reported problems with this option.
603 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
604 description
=> <<EODESCR,
605 Map host parallel devices (n is 0 to 2).
607 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
609 Experimental: user reported problems with this option.
613 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
614 $confdesc->{"parallel$i"} = $paralleldesc;
617 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
618 $confdesc->{"serial$i"} = $serialdesc;
621 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
622 $confdesc->{"hostpci$i"} = $hostpcidesc;
625 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
626 $drivename_hash->{"ide$i"} = 1;
627 $confdesc->{"ide$i"} = $idedesc;
630 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
631 $drivename_hash->{"sata$i"} = 1;
632 $confdesc->{"sata$i"} = $satadesc;
635 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
636 $drivename_hash->{"scsi$i"} = 1;
637 $confdesc->{"scsi$i"} = $scsidesc ;
640 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
641 $drivename_hash->{"virtio$i"} = 1;
642 $confdesc->{"virtio$i"} = $virtiodesc;
645 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
646 $confdesc->{"usb$i"} = $usbdesc;
651 type
=> 'string', format
=> 'pve-volume-id',
652 description
=> "Reference to unused volumes.",
655 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
656 $confdesc->{"unused$i"} = $unuseddesc;
659 my $kvm_api_version = 0;
663 return $kvm_api_version if $kvm_api_version;
665 my $fh = IO
::File-
>new("</dev/kvm") ||
668 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
669 $kvm_api_version = $v;
674 return $kvm_api_version;
677 my $kvm_user_version;
679 sub kvm_user_version
{
681 return $kvm_user_version if $kvm_user_version;
683 $kvm_user_version = 'unknown';
685 my $tmp = `kvm -help 2>/dev/null`;
687 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
688 $kvm_user_version = $2;
691 return $kvm_user_version;
695 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
698 # order is important - used to autoselect boot disk
699 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
700 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
701 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
702 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
705 sub valid_drivename
{
708 return defined($drivename_hash->{$dev});
713 return defined($confdesc->{$key});
717 return $nic_model_list;
720 sub os_list_description
{
725 w2k
=> 'Windows 2000',
726 w2k3
=>, 'Windows 2003',
727 w2k8
=> 'Windows 2008',
728 wvista
=> 'Windows Vista',
730 win8
=> 'Windows 8/2012',
740 return $cdrom_path if $cdrom_path;
742 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
743 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
744 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
748 my ($storecfg, $vmid, $cdrom) = @_;
750 if ($cdrom eq 'cdrom') {
751 return get_cdrom_path
();
752 } elsif ($cdrom eq 'none') {
754 } elsif ($cdrom =~ m
|^/|) {
757 return PVE
::Storage
::path
($storecfg, $cdrom);
761 # try to convert old style file names to volume IDs
762 sub filename_to_volume_id
{
763 my ($vmid, $file, $media) = @_;
765 if (!($file eq 'none' || $file eq 'cdrom' ||
766 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
768 return undef if $file =~ m
|/|;
770 if ($media && $media eq 'cdrom') {
771 $file = "local:iso/$file";
773 $file = "local:$vmid/$file";
780 sub verify_media_type
{
781 my ($opt, $vtype, $media) = @_;
786 if ($media eq 'disk') {
788 } elsif ($media eq 'cdrom') {
791 die "internal error";
794 return if ($vtype eq $etype);
796 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
799 sub cleanup_drive_path
{
800 my ($opt, $storecfg, $drive) = @_;
802 # try to convert filesystem paths to volume IDs
804 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
805 ($drive->{file
} !~ m
|^/dev/.+|) &&
806 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
807 ($drive->{file
} !~ m/^\d+$/)) {
808 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
809 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
810 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
811 verify_media_type
($opt, $vtype, $drive->{media
});
812 $drive->{file
} = $volid;
815 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
818 sub create_conf_nolock
{
819 my ($vmid, $settings) = @_;
821 my $filename = config_file
($vmid);
823 die "configuration file '$filename' already exists\n" if -f
$filename;
825 my $defaults = load_defaults
();
827 $settings->{name
} = "vm$vmid" if !$settings->{name
};
828 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
831 foreach my $opt (keys %$settings) {
832 next if !$confdesc->{$opt};
834 my $value = $settings->{$opt};
837 $data .= "$opt: $value\n";
840 PVE
::Tools
::file_set_contents
($filename, $data);
843 my $parse_size = sub {
846 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
847 my ($size, $unit) = ($1, $3);
850 $size = $size * 1024;
851 } elsif ($unit eq 'M') {
852 $size = $size * 1024 * 1024;
853 } elsif ($unit eq 'G') {
854 $size = $size * 1024 * 1024 * 1024;
860 my $format_size = sub {
865 my $kb = int($size/1024);
866 return $size if $kb*1024 != $size;
868 my $mb = int($kb/1024);
869 return "${kb}K" if $mb*1024 != $kb;
871 my $gb = int($mb/1024);
872 return "${mb}M" if $gb*1024 != $mb;
877 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
878 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
879 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
880 # [,aio=native|threads][,discard=ignore|on]
883 my ($key, $data) = @_;
887 # $key may be undefined - used to verify JSON parameters
888 if (!defined($key)) {
889 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
891 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
892 $res->{interface
} = $1;
898 foreach my $p (split (/,/, $data)) {
899 next if $p =~ m/^\s*$/;
901 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
902 my ($k, $v) = ($1, $2);
904 $k = 'file' if $k eq 'volume';
906 return undef if defined $res->{$k};
908 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
909 return undef if !$v || $v !~ m/^\d+/;
911 $v = sprintf("%.3f", $v / (1024*1024));
915 if (!$res->{file
} && $p !~ m/=/) {
923 return undef if !$res->{file
};
925 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
929 return undef if $res->{cache
} &&
930 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
931 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
932 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
933 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
934 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
935 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
936 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
937 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
938 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
939 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
940 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
941 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
942 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
944 return undef if $res->{mbps_rd
} && $res->{mbps
};
945 return undef if $res->{mbps_wr
} && $res->{mbps
};
947 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
948 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
949 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
950 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
951 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
952 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
954 return undef if $res->{iops_rd
} && $res->{iops
};
955 return undef if $res->{iops_wr
} && $res->{iops
};
958 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
959 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
960 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
961 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
962 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
963 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
967 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
970 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
971 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
972 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
973 return undef if $res->{interface
} eq 'virtio';
976 # rerror does not work with scsi drives
977 if ($res->{rerror
}) {
978 return undef if $res->{interface
} eq 'scsi';
984 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
987 my ($vmid, $drive) = @_;
990 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
991 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
994 if ($drive->{size
}) {
995 $opts .= ",size=" . &$format_size($drive->{size
});
998 return "$drive->{file}$opts";
1002 my($fh, $noerr) = @_;
1005 my $SG_GET_VERSION_NUM = 0x2282;
1007 my $versionbuf = "\x00" x
8;
1008 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1010 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1013 my $version = unpack("I", $versionbuf);
1014 if ($version < 30000) {
1015 die "scsi generic interface too old\n" if !$noerr;
1019 my $buf = "\x00" x
36;
1020 my $sensebuf = "\x00" x
8;
1021 my $cmd = pack("C x3 C x1", 0x12, 36);
1023 # see /usr/include/scsi/sg.h
1024 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
1026 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1027 length($sensebuf), 0, length($buf), $buf,
1028 $cmd, $sensebuf, 6000);
1030 $ret = ioctl($fh, $SG_IO, $packet);
1032 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1036 my @res = unpack($sg_io_hdr_t, $packet);
1037 if ($res[17] || $res[18]) {
1038 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1043 (my $byte0, my $byte1, $res->{vendor
},
1044 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1046 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1047 $res->{type
} = $byte0 & 31;
1055 my $fh = IO
::File-
>new("+<$path") || return undef;
1056 my $res = scsi_inquiry
($fh, 1);
1062 sub print_drivedevice_full
{
1063 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1068 if ($drive->{interface
} eq 'virtio') {
1069 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1070 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1071 } elsif ($drive->{interface
} eq 'scsi') {
1072 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1073 my $controller = int($drive->{index} / $maxdev);
1074 my $unit = $drive->{index} % $maxdev;
1075 my $devicetype = 'hd';
1077 if (drive_is_cdrom
($drive)) {
1080 if ($drive->{file
} =~ m
|^/|) {
1081 $path = $drive->{file
};
1083 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1086 if($path =~ m/^iscsi\:\/\
//){
1087 $devicetype = 'generic';
1089 if (my $info = path_is_scsi
($path)) {
1090 if ($info->{type
} == 0) {
1091 $devicetype = 'block';
1092 } elsif ($info->{type
} == 1) { # tape
1093 $devicetype = 'generic';
1099 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1100 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1102 $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1105 } elsif ($drive->{interface
} eq 'ide'){
1107 my $controller = int($drive->{index} / $maxdev);
1108 my $unit = $drive->{index} % $maxdev;
1109 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1111 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1112 } elsif ($drive->{interface
} eq 'sata'){
1113 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1114 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1115 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1116 } elsif ($drive->{interface
} eq 'usb') {
1118 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1120 die "unsupported interface type";
1123 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1128 sub print_drive_full
{
1129 my ($storecfg, $vmid, $drive) = @_;
1132 foreach my $o (@qemu_drive_options) {
1133 next if $o eq 'bootindex';
1134 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1137 foreach my $o (qw(bps bps_rd bps_wr)) {
1138 my $v = $drive->{"m$o"};
1139 $opts .= ",$o=" . int($v*1024*1024) if $v;
1142 # use linux-aio by default (qemu default is threads)
1143 $opts .= ",aio=native" if !$drive->{aio
};
1146 my $volid = $drive->{file
};
1147 if (drive_is_cdrom
($drive)) {
1148 $path = get_iso_path
($storecfg, $vmid, $volid);
1150 if ($volid =~ m
|^/|) {
1153 $path = PVE
::Storage
::path
($storecfg, $volid);
1157 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1159 my $pathinfo = $path ?
"file=$path," : '';
1161 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1164 sub print_netdevice_full
{
1165 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1167 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1169 my $device = $net->{model
};
1170 if ($net->{model
} eq 'virtio') {
1171 $device = 'virtio-net-pci';
1174 # qemu > 0.15 always try to boot from network - we disable that by
1175 # not loading the pxe rom file
1176 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1177 my $pciaddr = print_pci_addr
("$netid", $bridges);
1178 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1179 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1183 sub print_netdev_full
{
1184 my ($vmid, $conf, $net, $netid) = @_;
1187 if ($netid =~ m/^net(\d+)$/) {
1191 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1193 my $ifname = "tap${vmid}i$i";
1195 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1196 die "interface name '$ifname' is too long (max 15 character)\n"
1197 if length($ifname) >= 16;
1199 my $vhostparam = '';
1200 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1202 my $vmname = $conf->{name
} || "vm$vmid";
1204 if ($net->{bridge
}) {
1205 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1207 return "type=user,id=$netid,hostname=$vmname";
1211 sub drive_is_cdrom
{
1214 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1221 return undef if !$value;
1224 my @list = split(/,/, $value);
1228 foreach my $kv (@list) {
1230 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) {
1233 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1234 $res->{driver
} = $1;
1235 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1236 $res->{rombar
} = $1;
1238 warn "unknown hostpci setting '$kv'\n";
1242 return undef if !$found;
1247 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1253 foreach my $kvp (split(/,/, $data)) {
1255 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1257 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1258 $res->{model
} = $model;
1259 $res->{macaddr
} = $mac;
1260 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1261 $res->{bridge
} = $1;
1262 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1264 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1266 } elsif ($kvp =~ m/^firewall=(\d+)$/) {
1267 $res->{firewall
} = $1;
1274 return undef if !$res->{model
};
1282 my $res = "$net->{model}";
1283 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1284 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1285 $res .= ",rate=$net->{rate}" if $net->{rate
};
1286 $res .= ",tag=$net->{tag}" if $net->{tag
};
1287 $res .= ",firewall=$net->{firewall}" if $net->{firewall
};
1292 sub add_random_macs
{
1293 my ($settings) = @_;
1295 foreach my $opt (keys %$settings) {
1296 next if $opt !~ m/^net(\d+)$/;
1297 my $net = parse_net
($settings->{$opt});
1299 $settings->{$opt} = print_net
($net);
1303 sub add_unused_volume
{
1304 my ($config, $volid) = @_;
1307 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1308 my $test = "unused$ind";
1309 if (my $vid = $config->{$test}) {
1310 return if $vid eq $volid; # do not add duplicates
1316 die "To many unused volume - please delete them first.\n" if !$key;
1318 $config->{$key} = $volid;
1323 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1324 sub verify_bootdisk
{
1325 my ($value, $noerr) = @_;
1327 return $value if valid_drivename
($value);
1329 return undef if $noerr;
1331 die "invalid boot disk '$value'\n";
1334 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1336 my ($value, $noerr) = @_;
1338 return $value if parse_net
($value);
1340 return undef if $noerr;
1342 die "unable to parse network options\n";
1345 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1347 my ($value, $noerr) = @_;
1349 return $value if parse_drive
(undef, $value);
1351 return undef if $noerr;
1353 die "unable to parse drive options\n";
1356 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1357 sub verify_hostpci
{
1358 my ($value, $noerr) = @_;
1360 return $value if parse_hostpci
($value);
1362 return undef if $noerr;
1364 die "unable to parse pci id\n";
1367 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1368 sub verify_watchdog
{
1369 my ($value, $noerr) = @_;
1371 return $value if parse_watchdog
($value);
1373 return undef if $noerr;
1375 die "unable to parse watchdog options\n";
1378 sub parse_watchdog
{
1381 return undef if !$value;
1385 foreach my $p (split(/,/, $value)) {
1386 next if $p =~ m/^\s*$/;
1388 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1390 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1391 $res->{action
} = $2;
1400 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1401 sub verify_startup
{
1402 my ($value, $noerr) = @_;
1404 return $value if parse_startup
($value);
1406 return undef if $noerr;
1408 die "unable to parse startup options\n";
1414 return undef if !$value;
1418 foreach my $p (split(/,/, $value)) {
1419 next if $p =~ m/^\s*$/;
1421 if ($p =~ m/^(order=)?(\d+)$/) {
1423 } elsif ($p =~ m/^up=(\d+)$/) {
1425 } elsif ($p =~ m/^down=(\d+)$/) {
1435 sub parse_usb_device
{
1438 return undef if !$value;
1440 my @dl = split(/,/, $value);
1444 foreach my $v (@dl) {
1445 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1447 $res->{vendorid
} = $2;
1448 $res->{productid
} = $4;
1449 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1451 $res->{hostbus
} = $1;
1452 $res->{hostport
} = $2;
1453 } elsif ($v =~ m/^spice$/) {
1460 return undef if !$found;
1465 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1466 sub verify_usb_device
{
1467 my ($value, $noerr) = @_;
1469 return $value if parse_usb_device
($value);
1471 return undef if $noerr;
1473 die "unable to parse usb device\n";
1476 # add JSON properties for create and set function
1477 sub json_config_properties
{
1480 foreach my $opt (keys %$confdesc) {
1481 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1482 $prop->{$opt} = $confdesc->{$opt};
1489 my ($key, $value) = @_;
1491 die "unknown setting '$key'\n" if !$confdesc->{$key};
1493 my $type = $confdesc->{$key}->{type
};
1495 if (!defined($value)) {
1496 die "got undefined value\n";
1499 if ($value =~ m/[\n\r]/) {
1500 die "property contains a line feed\n";
1503 if ($type eq 'boolean') {
1504 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1505 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1506 die "type check ('boolean') failed - got '$value'\n";
1507 } elsif ($type eq 'integer') {
1508 return int($1) if $value =~ m/^(\d+)$/;
1509 die "type check ('integer') failed - got '$value'\n";
1510 } elsif ($type eq 'number') {
1511 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1512 die "type check ('number') failed - got '$value'\n";
1513 } elsif ($type eq 'string') {
1514 if (my $fmt = $confdesc->{$key}->{format
}) {
1515 if ($fmt eq 'pve-qm-drive') {
1516 # special case - we need to pass $key to parse_drive()
1517 my $drive = parse_drive
($key, $value);
1518 return $value if $drive;
1519 die "unable to parse drive options\n";
1521 PVE
::JSONSchema
::check_format
($fmt, $value);
1524 $value =~ s/^\"(.*)\"$/$1/;
1527 die "internal error"
1531 sub lock_config_full
{
1532 my ($vmid, $timeout, $code, @param) = @_;
1534 my $filename = config_file_lock
($vmid);
1536 my $res = lock_file
($filename, $timeout, $code, @param);
1543 sub lock_config_mode
{
1544 my ($vmid, $timeout, $shared, $code, @param) = @_;
1546 my $filename = config_file_lock
($vmid);
1548 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1556 my ($vmid, $code, @param) = @_;
1558 return lock_config_full
($vmid, 10, $code, @param);
1561 sub cfs_config_path
{
1562 my ($vmid, $node) = @_;
1564 $node = $nodename if !$node;
1565 return "nodes/$node/qemu-server/$vmid.conf";
1568 sub check_iommu_support
{
1569 #fixme : need to check IOMMU support
1570 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1578 my ($vmid, $node) = @_;
1580 my $cfspath = cfs_config_path
($vmid, $node);
1581 return "/etc/pve/$cfspath";
1584 sub config_file_lock
{
1587 return "$lock_dir/lock-$vmid.conf";
1593 my $conf = config_file
($vmid);
1594 utime undef, undef, $conf;
1598 my ($storecfg, $vmid, $keep_empty_config) = @_;
1600 my $conffile = config_file
($vmid);
1602 my $conf = load_config
($vmid);
1606 # only remove disks owned by this VM
1607 foreach_drive
($conf, sub {
1608 my ($ds, $drive) = @_;
1610 return if drive_is_cdrom
($drive);
1612 my $volid = $drive->{file
};
1614 return if !$volid || $volid =~ m
|^/|;
1616 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1617 return if !$path || !$owner || ($owner != $vmid);
1619 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1622 if ($keep_empty_config) {
1623 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1628 # also remove unused disk
1630 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1633 PVE
::Storage
::foreach_volid
($dl, sub {
1634 my ($volid, $sid, $volname, $d) = @_;
1635 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1645 my ($vmid, $node) = @_;
1647 my $cfspath = cfs_config_path
($vmid, $node);
1649 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1651 die "no such VM ('$vmid')\n" if !defined($conf);
1656 sub parse_vm_config
{
1657 my ($filename, $raw) = @_;
1659 return undef if !defined($raw);
1662 digest
=> Digest
::SHA
::sha1_hex
($raw),
1666 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1667 || die "got strange filename '$filename'";
1674 my @lines = split(/\n/, $raw);
1675 foreach my $line (@lines) {
1676 next if $line =~ m/^\s*$/;
1678 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1680 $conf->{description
} = $descr if $descr;
1682 $conf = $res->{snapshots
}->{$snapname} = {};
1686 if ($line =~ m/^\#(.*)\s*$/) {
1687 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1691 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1692 $descr .= PVE
::Tools
::decode_text
($2);
1693 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1694 $conf->{snapstate
} = $1;
1695 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1698 $conf->{$key} = $value;
1699 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1702 eval { $value = check_type
($key, $value); };
1704 warn "vm $vmid - unable to parse value of '$key' - $@";
1706 my $fmt = $confdesc->{$key}->{format
};
1707 if ($fmt && $fmt eq 'pve-qm-drive') {
1708 my $v = parse_drive
($key, $value);
1709 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1710 $v->{file
} = $volid;
1711 $value = print_drive
($vmid, $v);
1713 warn "vm $vmid - unable to parse value of '$key'\n";
1718 if ($key eq 'cdrom') {
1719 $conf->{ide2
} = $value;
1721 $conf->{$key} = $value;
1727 $conf->{description
} = $descr if $descr;
1729 delete $res->{snapstate
}; # just to be sure
1734 sub write_vm_config
{
1735 my ($filename, $conf) = @_;
1737 delete $conf->{snapstate
}; # just to be sure
1739 if ($conf->{cdrom
}) {
1740 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1741 $conf->{ide2
} = $conf->{cdrom
};
1742 delete $conf->{cdrom
};
1745 # we do not use 'smp' any longer
1746 if ($conf->{sockets
}) {
1747 delete $conf->{smp
};
1748 } elsif ($conf->{smp
}) {
1749 $conf->{sockets
} = $conf->{smp
};
1750 delete $conf->{cores
};
1751 delete $conf->{smp
};
1754 if ($conf->{maxcpus
} && $conf->{sockets
}) {
1755 delete $conf->{sockets
};
1758 my $used_volids = {};
1760 my $cleanup_config = sub {
1761 my ($cref, $snapname) = @_;
1763 foreach my $key (keys %$cref) {
1764 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1765 $key eq 'snapstate';
1766 my $value = $cref->{$key};
1767 eval { $value = check_type
($key, $value); };
1768 die "unable to parse value of '$key' - $@" if $@;
1770 $cref->{$key} = $value;
1772 if (!$snapname && valid_drivename
($key)) {
1773 my $drive = parse_drive
($key, $value);
1774 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1779 &$cleanup_config($conf);
1780 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1781 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1784 # remove 'unusedX' settings if we re-add a volume
1785 foreach my $key (keys %$conf) {
1786 my $value = $conf->{$key};
1787 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1788 delete $conf->{$key};
1792 my $generate_raw_config = sub {
1797 # add description as comment to top of file
1798 my $descr = $conf->{description
} || '';
1799 foreach my $cl (split(/\n/, $descr)) {
1800 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1803 foreach my $key (sort keys %$conf) {
1804 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1805 $raw .= "$key: $conf->{$key}\n";
1810 my $raw = &$generate_raw_config($conf);
1811 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1812 $raw .= "\n[$snapname]\n";
1813 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1819 sub update_config_nolock
{
1820 my ($vmid, $conf, $skiplock) = @_;
1822 check_lock
($conf) if !$skiplock;
1824 my $cfspath = cfs_config_path
($vmid);
1826 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1830 my ($vmid, $conf, $skiplock) = @_;
1832 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1839 # we use static defaults from our JSON schema configuration
1840 foreach my $key (keys %$confdesc) {
1841 if (defined(my $default = $confdesc->{$key}->{default})) {
1842 $res->{$key} = $default;
1846 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1847 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1853 my $vmlist = PVE
::Cluster
::get_vmlist
();
1855 return $res if !$vmlist || !$vmlist->{ids
};
1856 my $ids = $vmlist->{ids
};
1858 foreach my $vmid (keys %$ids) {
1859 my $d = $ids->{$vmid};
1860 next if !$d->{node
} || $d->{node
} ne $nodename;
1861 next if !$d->{type
} || $d->{type
} ne 'qemu';
1862 $res->{$vmid}->{exists} = 1;
1867 # test if VM uses local resources (to prevent migration)
1868 sub check_local_resources
{
1869 my ($conf, $noerr) = @_;
1873 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1874 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1876 foreach my $k (keys %$conf) {
1877 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1878 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1881 die "VM uses local resources\n" if $loc_res && !$noerr;
1886 # check if used storages are available on all nodes (use by migrate)
1887 sub check_storage_availability
{
1888 my ($storecfg, $conf, $node) = @_;
1890 foreach_drive
($conf, sub {
1891 my ($ds, $drive) = @_;
1893 my $volid = $drive->{file
};
1896 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1899 # check if storage is available on both nodes
1900 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1901 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1905 # list nodes where all VM images are available (used by has_feature API)
1907 my ($conf, $storecfg) = @_;
1909 my $nodelist = PVE
::Cluster
::get_nodelist
();
1910 my $nodehash = { map { $_ => 1 } @$nodelist };
1911 my $nodename = PVE
::INotify
::nodename
();
1913 foreach_drive
($conf, sub {
1914 my ($ds, $drive) = @_;
1916 my $volid = $drive->{file
};
1919 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1921 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1922 if ($scfg->{disable
}) {
1924 } elsif (my $avail = $scfg->{nodes
}) {
1925 foreach my $node (keys %$nodehash) {
1926 delete $nodehash->{$node} if !$avail->{$node};
1928 } elsif (!$scfg->{shared
}) {
1929 foreach my $node (keys %$nodehash) {
1930 delete $nodehash->{$node} if $node ne $nodename
1942 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1946 my ($pidfile, $pid) = @_;
1948 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1952 return undef if !$line;
1953 my @param = split(/\0/, $line);
1955 my $cmd = $param[0];
1956 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1958 for (my $i = 0; $i < scalar (@param); $i++) {
1961 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1962 my $p = $param[$i+1];
1963 return 1 if $p && ($p eq $pidfile);
1972 my ($vmid, $nocheck, $node) = @_;
1974 my $filename = config_file
($vmid, $node);
1976 die "unable to find configuration file for VM $vmid - no such machine\n"
1977 if !$nocheck && ! -f
$filename;
1979 my $pidfile = pidfile_name
($vmid);
1981 if (my $fd = IO
::File-
>new("<$pidfile")) {
1986 my $mtime = $st->mtime;
1987 if ($mtime > time()) {
1988 warn "file '$filename' modified in future\n";
1991 if ($line =~ m/^(\d+)$/) {
1993 if (check_cmdline
($pidfile, $pid)) {
1994 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2006 my $vzlist = config_list
();
2008 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2010 while (defined(my $de = $fd->read)) {
2011 next if $de !~ m/^(\d+)\.pid$/;
2013 next if !defined($vzlist->{$vmid});
2014 if (my $pid = check_running
($vmid)) {
2015 $vzlist->{$vmid}->{pid
} = $pid;
2023 my ($storecfg, $conf) = @_;
2025 my $bootdisk = $conf->{bootdisk
};
2026 return undef if !$bootdisk;
2027 return undef if !valid_drivename
($bootdisk);
2029 return undef if !$conf->{$bootdisk};
2031 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2032 return undef if !defined($drive);
2034 return undef if drive_is_cdrom
($drive);
2036 my $volid = $drive->{file
};
2037 return undef if !$volid;
2039 return $drive->{size
};
2042 my $last_proc_pid_stat;
2044 # get VM status information
2045 # This must be fast and should not block ($full == false)
2046 # We only query KVM using QMP if $full == true (this can be slow)
2048 my ($opt_vmid, $full) = @_;
2052 my $storecfg = PVE
::Storage
::config
();
2054 my $list = vzlist
();
2055 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2057 my $cpucount = $cpuinfo->{cpus
} || 1;
2059 foreach my $vmid (keys %$list) {
2060 next if $opt_vmid && ($vmid ne $opt_vmid);
2062 my $cfspath = cfs_config_path
($vmid);
2063 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2066 $d->{pid
} = $list->{$vmid}->{pid
};
2068 # fixme: better status?
2069 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2071 my $size = disksize
($storecfg, $conf);
2072 if (defined($size)) {
2073 $d->{disk
} = 0; # no info available
2074 $d->{maxdisk
} = $size;
2080 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2081 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2083 $d->{name
} = $conf->{name
} || "VM $vmid";
2084 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2086 if ($conf->{balloon
}) {
2087 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2088 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2099 $d->{diskwrite
} = 0;
2101 $d->{template
} = is_template
($conf);
2106 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2107 foreach my $dev (keys %$netdev) {
2108 next if $dev !~ m/^tap([1-9]\d*)i/;
2110 my $d = $res->{$vmid};
2113 $d->{netout
} += $netdev->{$dev}->{receive
};
2114 $d->{netin
} += $netdev->{$dev}->{transmit
};
2117 my $ctime = gettimeofday
;
2119 foreach my $vmid (keys %$list) {
2121 my $d = $res->{$vmid};
2122 my $pid = $d->{pid
};
2125 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2126 next if !$pstat; # not running
2128 my $used = $pstat->{utime} + $pstat->{stime
};
2130 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2132 if ($pstat->{vsize
}) {
2133 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2136 my $old = $last_proc_pid_stat->{$pid};
2138 $last_proc_pid_stat->{$pid} = {
2146 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2148 if ($dtime > 1000) {
2149 my $dutime = $used - $old->{used
};
2151 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2152 $last_proc_pid_stat->{$pid} = {
2158 $d->{cpu
} = $old->{cpu
};
2162 return $res if !$full;
2164 my $qmpclient = PVE
::QMPClient-
>new();
2166 my $ballooncb = sub {
2167 my ($vmid, $resp) = @_;
2169 my $info = $resp->{'return'};
2170 return if !$info->{max_mem
};
2172 my $d = $res->{$vmid};
2174 # use memory assigned to VM
2175 $d->{maxmem
} = $info->{max_mem
};
2176 $d->{balloon
} = $info->{actual
};
2178 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2179 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2180 $d->{freemem
} = $info->{free_mem
};
2185 my $blockstatscb = sub {
2186 my ($vmid, $resp) = @_;
2187 my $data = $resp->{'return'} || [];
2188 my $totalrdbytes = 0;
2189 my $totalwrbytes = 0;
2190 for my $blockstat (@$data) {
2191 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2192 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2194 $res->{$vmid}->{diskread
} = $totalrdbytes;
2195 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2198 my $statuscb = sub {
2199 my ($vmid, $resp) = @_;
2201 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2202 # this fails if ballon driver is not loaded, so this must be
2203 # the last commnand (following command are aborted if this fails).
2204 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2206 my $status = 'unknown';
2207 if (!defined($status = $resp->{'return'}->{status
})) {
2208 warn "unable to get VM status\n";
2212 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2215 foreach my $vmid (keys %$list) {
2216 next if $opt_vmid && ($vmid ne $opt_vmid);
2217 next if !$res->{$vmid}->{pid
}; # not running
2218 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2221 $qmpclient->queue_execute();
2223 foreach my $vmid (keys %$list) {
2224 next if $opt_vmid && ($vmid ne $opt_vmid);
2225 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2232 my ($conf, $func) = @_;
2234 foreach my $ds (keys %$conf) {
2235 next if !valid_drivename
($ds);
2237 my $drive = parse_drive
($ds, $conf->{$ds});
2240 &$func($ds, $drive);
2245 my ($conf, $func) = @_;
2249 my $test_volid = sub {
2250 my ($volid, $is_cdrom) = @_;
2254 $volhash->{$volid} = $is_cdrom || 0;
2257 foreach_drive
($conf, sub {
2258 my ($ds, $drive) = @_;
2259 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2262 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2263 my $snap = $conf->{snapshots
}->{$snapname};
2264 &$test_volid($snap->{vmstate
}, 0);
2265 foreach_drive
($snap, sub {
2266 my ($ds, $drive) = @_;
2267 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2271 foreach my $volid (keys %$volhash) {
2272 &$func($volid, $volhash->{$volid});
2276 sub vga_conf_has_spice
{
2279 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2284 sub config_to_command
{
2285 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2288 my $globalFlags = [];
2289 my $machineFlags = [];
2295 my $kvmver = kvm_user_version
();
2296 my $vernum = 0; # unknown
2297 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2298 $vernum = $1*1000000+$2*1000;
2299 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2300 $vernum = $1*1000000+$2*1000+$3;
2303 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2305 my $have_ovz = -f
'/proc/vz/vestat';
2307 push @$cmd, '/usr/bin/kvm';
2309 push @$cmd, '-id', $vmid;
2313 my $qmpsocket = qmp_socket
($vmid);
2314 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2315 push @$cmd, '-mon', "chardev=qmp,mode=control";
2317 my $socket = vnc_socket
($vmid);
2318 push @$cmd, '-vnc', "unix:$socket,x509,password";
2320 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2322 push @$cmd, '-daemonize';
2324 $pciaddr = print_pci_addr
("piix3", $bridges);
2325 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2328 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2329 next if !$conf->{"usb$i"};
2332 # include usb device config
2333 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2335 my $vga = $conf->{vga
};
2337 my $qxlnum = vga_conf_has_spice
($vga);
2338 $vga = 'qxl' if $qxlnum;
2341 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2342 $conf->{ostype
} eq 'win7' ||
2343 $conf->{ostype
} eq 'w2k8')) {
2350 # enable absolute mouse coordinates (needed by vnc)
2352 if (defined($conf->{tablet
})) {
2353 $tablet = $conf->{tablet
};
2355 $tablet = $defaults->{tablet
};
2356 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2357 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2360 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2363 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2364 my $d = parse_hostpci
($conf->{"hostpci$i"});
2366 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2367 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2368 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar";
2372 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2373 my $d = parse_usb_device
($conf->{"usb$i"});
2375 if ($d->{vendorid
} && $d->{productid
}) {
2376 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2377 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2378 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2379 } elsif ($d->{spice
}) {
2380 # usb redir support for spice
2381 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2382 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2387 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2388 if (my $path = $conf->{"serial$i"}) {
2389 if ($path eq 'socket') {
2390 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2391 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2392 push @$devices, '-device', "isa-serial,chardev=serial$i";
2394 die "no such serial device\n" if ! -c
$path;
2395 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2396 push @$devices, '-device', "isa-serial,chardev=serial$i";
2402 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2403 if (my $path = $conf->{"parallel$i"}) {
2404 die "no such parallel device\n" if ! -c
$path;
2405 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2406 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2407 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2411 my $vmname = $conf->{name
} || "vm$vmid";
2413 push @$cmd, '-name', $vmname;
2416 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2417 $sockets = $conf->{sockets
} if $conf->{sockets
};
2419 my $cores = $conf->{cores
} || 1;
2420 my $maxcpus = $conf->{maxcpus
} if $conf->{maxcpus
};
2423 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
2425 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2428 push @$cmd, '-nodefaults';
2430 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2432 my $bootindex_hash = {};
2434 foreach my $o (split(//, $bootorder)) {
2435 $bootindex_hash->{$o} = $i*100;
2439 push @$cmd, '-boot', "menu=on";
2441 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2443 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2445 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2448 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2450 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2451 my $useLocaltime = $conf->{localtime};
2453 if (my $ost = $conf->{ostype
}) {
2454 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2456 if ($ost =~ m/^w/) { # windows
2457 $useLocaltime = 1 if !defined($conf->{localtime});
2459 # use time drift fix when acpi is enabled
2460 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2461 $tdf = 1 if !defined($conf->{tdf
});
2465 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2467 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2468 push @$cmd, '-no-hpet';
2469 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2470 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2473 if ($ost eq 'win7' || $ost eq 'win8') {
2474 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2478 push @$rtcFlags, 'driftfix=slew' if $tdf;
2481 push @$machineFlags, 'accel=tcg';
2483 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2486 my $machine_type = $forcemachine || $conf->{machine
};
2487 if ($machine_type) {
2488 push @$machineFlags, "type=${machine_type}";
2491 if ($conf->{startdate
}) {
2492 push @$rtcFlags, "base=$conf->{startdate}";
2493 } elsif ($useLocaltime) {
2494 push @$rtcFlags, 'base=localtime';
2497 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2498 $cpu = $conf->{cpu
} if $conf->{cpu
};
2500 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2502 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2504 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2506 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2508 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2510 # Note: enforce needs kernel 3.10, so we do not use it for now
2511 # push @$cmd, '-cpu', "$cpu,enforce";
2512 push @$cmd, '-cpu', $cpu;
2514 push @$cmd, '-S' if $conf->{freeze
};
2516 # set keyboard layout
2517 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2518 push @$cmd, '-k', $kb if $kb;
2521 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2522 #push @$cmd, '-soundhw', 'es1370';
2523 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2525 if($conf->{agent
}) {
2526 my $qgasocket = qga_socket
($vmid);
2527 my $pciaddr = print_pci_addr
("qga0", $bridges);
2528 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2529 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2530 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2537 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2538 for(my $i = 1; $i < $qxlnum; $i++){
2539 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2540 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2543 # assume other OS works like Linux
2544 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2545 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2549 my $pciaddr = print_pci_addr
("spice", $bridges);
2551 $spice_port = PVE
::Tools
::next_spice_port
();
2553 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2555 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2556 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2557 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2560 # enable balloon by default, unless explicitly disabled
2561 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2562 $pciaddr = print_pci_addr
("balloon0", $bridges);
2563 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2566 if ($conf->{watchdog
}) {
2567 my $wdopts = parse_watchdog
($conf->{watchdog
});
2568 $pciaddr = print_pci_addr
("watchdog", $bridges);
2569 my $watchdog = $wdopts->{model
} || 'i6300esb';
2570 push @$devices, '-device', "$watchdog$pciaddr";
2571 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2575 my $scsicontroller = {};
2576 my $ahcicontroller = {};
2577 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2579 foreach_drive
($conf, sub {
2580 my ($ds, $drive) = @_;
2582 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2583 push @$vollist, $drive->{file
};
2586 $use_virtio = 1 if $ds =~ m/^virtio/;
2588 if (drive_is_cdrom
($drive)) {
2589 if ($bootindex_hash->{d
}) {
2590 $drive->{bootindex
} = $bootindex_hash->{d
};
2591 $bootindex_hash->{d
} += 1;
2594 if ($bootindex_hash->{c
}) {
2595 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2596 $bootindex_hash->{c
} += 1;
2600 if ($drive->{interface
} eq 'scsi') {
2602 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2603 my $controller = int($drive->{index} / $maxdev);
2604 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2605 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2606 $scsicontroller->{$controller}=1;
2609 if ($drive->{interface
} eq 'sata') {
2610 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2611 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2612 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2613 $ahcicontroller->{$controller}=1;
2616 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2617 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2620 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2622 for (my $i = 0; $i < $MAX_NETS; $i++) {
2623 next if !$conf->{"net$i"};
2624 my $d = parse_net
($conf->{"net$i"});
2627 $use_virtio = 1 if $d->{model
} eq 'virtio';
2629 if ($bootindex_hash->{n
}) {
2630 $d->{bootindex
} = $bootindex_hash->{n
};
2631 $bootindex_hash->{n
} += 1;
2634 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2635 push @$devices, '-netdev', $netdevfull;
2637 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2638 push @$devices, '-device', $netdevicefull;
2642 while (my ($k, $v) = each %$bridges) {
2643 $pciaddr = print_pci_addr
("pci.$k");
2644 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2648 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2649 # when the VM uses virtio devices.
2650 if (!$use_virtio && $have_ovz) {
2652 my $cpuunits = defined($conf->{cpuunits
}) ?
2653 $conf->{cpuunits
} : $defaults->{cpuunits
};
2655 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2657 # fixme: cpulimit is currently ignored
2658 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2662 if ($conf->{args
}) {
2663 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2667 push @$cmd, @$devices;
2668 push @$cmd, '-rtc', join(',', @$rtcFlags)
2669 if scalar(@$rtcFlags);
2670 push @$cmd, '-machine', join(',', @$machineFlags)
2671 if scalar(@$machineFlags);
2672 push @$cmd, '-global', join(',', @$globalFlags)
2673 if scalar(@$globalFlags);
2675 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2680 return "${var_run_tmpdir}/$vmid.vnc";
2686 my $res = vm_mon_cmd
($vmid, 'query-spice');
2688 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2693 return "${var_run_tmpdir}/$vmid.qmp";
2698 return "${var_run_tmpdir}/$vmid.qga";
2703 return "${var_run_tmpdir}/$vmid.pid";
2706 sub vm_devices_list
{
2709 my $res = vm_mon_cmd
($vmid, 'query-pci');
2712 foreach my $pcibus (@$res) {
2713 foreach my $device (@{$pcibus->{devices
}}) {
2714 next if !$device->{'qdev_id'};
2715 $devices->{$device->{'qdev_id'}} = $device;
2723 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2725 return 1 if !check_running
($vmid);
2727 if ($deviceid eq 'tablet') {
2728 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2729 qemu_deviceadd
($vmid, $devicefull);
2733 return 1 if !$conf->{hotplug
};
2735 my $devices_list = vm_devices_list
($vmid);
2736 return 1 if defined($devices_list->{$deviceid});
2738 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2740 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2741 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2742 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2743 qemu_deviceadd
($vmid, $devicefull);
2744 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2745 qemu_drivedel
($vmid, $deviceid);
2750 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2751 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2752 my $pciaddr = print_pci_addr
($deviceid);
2753 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2754 qemu_deviceadd
($vmid, $devicefull);
2755 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2758 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2759 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2760 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2761 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2762 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2763 if(!qemu_deviceadd
($vmid, $devicefull)) {
2764 qemu_drivedel
($vmid, $deviceid);
2769 if ($deviceid =~ m/^(net)(\d+)$/) {
2770 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2771 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2772 qemu_deviceadd
($vmid, $netdevicefull);
2773 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2774 qemu_netdevdel
($vmid, $deviceid);
2779 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2781 my $pciaddr = print_pci_addr
($deviceid);
2782 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2783 qemu_deviceadd
($vmid, $devicefull);
2784 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2790 sub vm_deviceunplug
{
2791 my ($vmid, $conf, $deviceid) = @_;
2793 return 1 if !check_running
($vmid);
2795 if ($deviceid eq 'tablet') {
2796 qemu_devicedel
($vmid, $deviceid);
2800 return 1 if !$conf->{hotplug
};
2802 my $devices_list = vm_devices_list
($vmid);
2803 return 1 if !defined($devices_list->{$deviceid});
2805 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2807 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2808 qemu_devicedel
($vmid, $deviceid);
2809 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2810 return undef if !qemu_drivedel
($vmid, $deviceid);
2813 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2814 return undef if !qemu_devicedel
($vmid, $deviceid);
2817 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2818 return undef if !qemu_devicedel
($vmid, $deviceid);
2819 return undef if !qemu_drivedel
($vmid, $deviceid);
2822 if ($deviceid =~ m/^(net)(\d+)$/) {
2823 qemu_devicedel
($vmid, $deviceid);
2824 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2825 return undef if !qemu_netdevdel
($vmid, $deviceid);
2831 sub qemu_deviceadd
{
2832 my ($vmid, $devicefull) = @_;
2834 $devicefull = "driver=".$devicefull;
2835 my %options = split(/[=,]/, $devicefull);
2837 vm_mon_cmd
($vmid, "device_add" , %options);
2841 sub qemu_devicedel
{
2842 my($vmid, $deviceid) = @_;
2843 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2848 my($storecfg, $vmid, $device) = @_;
2850 my $drive = print_drive_full
($storecfg, $vmid, $device);
2851 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2852 # If the command succeeds qemu prints: "OK"
2853 if ($ret !~ m/OK/s) {
2854 syslog
("err", "adding drive failed: $ret");
2861 my($vmid, $deviceid) = @_;
2863 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2865 if ($ret =~ m/Device \'.*?\' not found/s) {
2866 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2868 elsif ($ret ne "") {
2869 syslog
("err", "deleting drive $deviceid failed : $ret");
2875 sub qemu_deviceaddverify
{
2876 my ($vmid,$deviceid) = @_;
2878 for (my $i = 0; $i <= 5; $i++) {
2879 my $devices_list = vm_devices_list
($vmid);
2880 return 1 if defined($devices_list->{$deviceid});
2883 syslog
("err", "error on hotplug device $deviceid");
2888 sub qemu_devicedelverify
{
2889 my ($vmid,$deviceid) = @_;
2891 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2892 for (my $i = 0; $i <= 5; $i++) {
2893 my $devices_list = vm_devices_list
($vmid);
2894 return 1 if !defined($devices_list->{$deviceid});
2897 syslog
("err", "error on hot-unplugging device $deviceid");
2901 sub qemu_findorcreatescsihw
{
2902 my ($storecfg, $conf, $vmid, $device) = @_;
2904 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2905 my $controller = int($device->{index} / $maxdev);
2906 my $scsihwid="scsihw$controller";
2907 my $devices_list = vm_devices_list
($vmid);
2909 if(!defined($devices_list->{$scsihwid})) {
2910 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2915 sub qemu_bridgeadd
{
2916 my ($storecfg, $conf, $vmid, $device) = @_;
2919 my $bridgeid = undef;
2920 print_pci_addr
($device, $bridges);
2922 while (my ($k, $v) = each %$bridges) {
2925 return if !$bridgeid || $bridgeid < 1;
2926 my $bridge = "pci.$bridgeid";
2927 my $devices_list = vm_devices_list
($vmid);
2929 if(!defined($devices_list->{$bridge})) {
2930 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2935 sub qemu_netdevadd
{
2936 my ($vmid, $conf, $device, $deviceid) = @_;
2938 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2939 my %options = split(/[=,]/, $netdev);
2941 vm_mon_cmd
($vmid, "netdev_add", %options);
2945 sub qemu_netdevdel
{
2946 my ($vmid, $deviceid) = @_;
2948 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2952 sub qemu_cpu_hotplug
{
2953 my ($vmid, $conf, $cores) = @_;
2955 die "new cores config is not defined" if !$cores;
2956 die "you can't add more cores than maxcpus"
2957 if $conf->{maxcpus
} && ($cores > $conf->{maxcpus
});
2958 return if !check_running
($vmid);
2960 my $currentcores = $conf->{cores
} if $conf->{cores
};
2961 die "current cores is not defined" if !$currentcores;
2962 die "maxcpus is not defined" if !$conf->{maxcpus
};
2963 raise_param_exc
({ 'cores' => "online cpu unplug is not yet possible" })
2964 if($cores < $currentcores);
2966 my $currentrunningcores = vm_mon_cmd
($vmid, "query-cpus");
2967 raise_param_exc
({ 'cores' => "cores number if running vm is different than configuration" })
2968 if scalar (@{$currentrunningcores}) != $currentcores;
2970 for(my $i = $currentcores; $i < $cores; $i++) {
2971 vm_mon_cmd
($vmid, "cpu-add", id
=> int($i));
2975 sub qemu_block_set_io_throttle
{
2976 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2978 return if !check_running
($vmid) ;
2980 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));
2984 # old code, only used to shutdown old VM after update
2986 my ($fh, $timeout) = @_;
2988 my $sel = new IO
::Select
;
2995 while (scalar (@ready = $sel->can_read($timeout))) {
2997 if ($count = $fh->sysread($buf, 8192)) {
2998 if ($buf =~ /^(.*)\(qemu\) $/s) {
3005 if (!defined($count)) {
3012 die "monitor read timeout\n" if !scalar(@ready);
3017 # old code, only used to shutdown old VM after update
3018 sub vm_monitor_command
{
3019 my ($vmid, $cmdstr, $nocheck) = @_;
3024 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3026 my $sname = "${var_run_tmpdir}/$vmid.mon";
3028 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
3029 die "unable to connect to VM $vmid socket - $!\n";
3033 # hack: migrate sometime blocks the monitor (when migrate_downtime
3035 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3036 $timeout = 60*60; # 1 hour
3040 my $data = __read_avail
($sock, $timeout);
3042 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3043 die "got unexpected qemu monitor banner\n";
3046 my $sel = new IO
::Select
;
3049 if (!scalar(my @ready = $sel->can_write($timeout))) {
3050 die "monitor write error - timeout";
3053 my $fullcmd = "$cmdstr\r";
3055 # syslog('info', "VM $vmid monitor command: $cmdstr");
3058 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3059 die "monitor write error - $!";
3062 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3066 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3067 $timeout = 60*60; # 1 hour
3068 } elsif ($cmdstr =~ m/^(eject|change)/) {
3069 $timeout = 60; # note: cdrom mount command is slow
3071 if ($res = __read_avail
($sock, $timeout)) {
3073 my @lines = split("\r?\n", $res);
3075 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3077 $res = join("\n", @lines);
3085 syslog
("err", "VM $vmid monitor command failed - $err");
3092 sub qemu_block_resize
{
3093 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3095 my $running = check_running
($vmid);
3097 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3099 return if !$running;
3101 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3105 sub qemu_volume_snapshot
{
3106 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3108 my $running = check_running
($vmid);
3110 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3112 return if !$running;
3114 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3118 sub qemu_volume_snapshot_delete
{
3119 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3121 my $running = check_running
($vmid);
3123 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3125 return if !$running;
3127 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3133 #need to impplement call to qemu-ga
3136 sub qga_unfreezefs
{
3139 #need to impplement call to qemu-ga
3142 sub set_migration_caps
{
3148 "auto-converge" => 1,
3150 "x-rdma-pin-all" => 0,
3154 my $supported_capabilities = vm_mon_cmd_nocheck
($vmid, "query-migrate-capabilities");
3156 for my $supported_capability (@$supported_capabilities) {
3158 capability
=> $supported_capability->{capability
},
3159 state => $enabled_cap->{$supported_capability->{capability
}} ? JSON
::true
: JSON
::false
,
3163 vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> $cap_ref);
3167 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3169 lock_config
($vmid, sub {
3170 my $conf = load_config
($vmid, $migratedfrom);
3172 die "you can't start a vm if it's a template\n" if is_template
($conf);
3174 check_lock
($conf) if !$skiplock;
3176 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3178 my $defaults = load_defaults
();
3180 # set environment variable useful inside network script
3181 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3183 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3185 my $migrate_port = 0;
3188 if ($statefile eq 'tcp') {
3189 my $localip = "localhost";
3190 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3191 if ($datacenterconf->{migration_unsecure
}) {
3192 my $nodename = PVE
::INotify
::nodename
();
3193 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3195 $migrate_port = PVE
::Tools
::next_migrate_port
();
3196 $migrate_uri = "tcp:${localip}:${migrate_port}";
3197 push @$cmd, '-incoming', $migrate_uri;
3200 push @$cmd, '-loadstate', $statefile;
3207 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3208 my $d = parse_hostpci
($conf->{"hostpci$i"});
3210 my $info = pci_device_info
("0000:$d->{pciid}");
3211 die "IOMMU not present\n" if !check_iommu_support
();
3212 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3213 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3214 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3217 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3219 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3222 die "start failed: $err" if $err;
3224 print "migration listens on $migrate_uri\n" if $migrate_uri;
3226 if ($statefile && $statefile ne 'tcp') {
3227 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3231 if ($migratedfrom) {
3234 PVE
::QemuServer
::set_migration_caps
($vmid);
3239 print "spice listens on port $spice_port\n";
3240 if ($spice_ticket) {
3241 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3242 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3248 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3249 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3250 if $conf->{balloon
};
3251 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3252 path
=> "machine/peripheral/balloon0",
3253 property
=> "guest-stats-polling-interval",
3261 my ($vmid, $execute, %params) = @_;
3263 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3264 vm_qmp_command
($vmid, $cmd);
3267 sub vm_mon_cmd_nocheck
{
3268 my ($vmid, $execute, %params) = @_;
3270 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3271 vm_qmp_command
($vmid, $cmd, 1);
3274 sub vm_qmp_command
{
3275 my ($vmid, $cmd, $nocheck) = @_;
3280 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3281 $timeout = $cmd->{arguments
}->{timeout
};
3282 delete $cmd->{arguments
}->{timeout
};
3286 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3287 my $sname = qmp_socket
($vmid);
3289 my $qmpclient = PVE
::QMPClient-
>new();
3291 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3292 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3293 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3294 if scalar(%{$cmd->{arguments
}});
3295 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3297 die "unable to open monitor socket\n";
3301 syslog
("err", "VM $vmid qmp command failed - $err");
3308 sub vm_human_monitor_command
{
3309 my ($vmid, $cmdline) = @_;
3314 execute
=> 'human-monitor-command',
3315 arguments
=> { 'command-line' => $cmdline},
3318 return vm_qmp_command
($vmid, $cmd);
3321 sub vm_commandline
{
3322 my ($storecfg, $vmid) = @_;
3324 my $conf = load_config
($vmid);
3326 my $defaults = load_defaults
();
3328 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3330 return join(' ', @$cmd);
3334 my ($vmid, $skiplock) = @_;
3336 lock_config
($vmid, sub {
3338 my $conf = load_config
($vmid);
3340 check_lock
($conf) if !$skiplock;
3342 vm_mon_cmd
($vmid, "system_reset");
3346 sub get_vm_volumes
{
3350 foreach_volid
($conf, sub {
3351 my ($volid, $is_cdrom) = @_;
3353 return if $volid =~ m
|^/|;
3355 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3358 push @$vollist, $volid;
3364 sub vm_stop_cleanup
{
3365 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3368 fairsched_rmnod
($vmid); # try to destroy group
3371 my $vollist = get_vm_volumes
($conf);
3372 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3375 foreach my $ext (qw(mon qmp pid vnc qga)) {
3376 unlink "/var/run/qemu-server/${vmid}.$ext";
3379 warn $@ if $@; # avoid errors - just warn
3382 # Note: use $nockeck to skip tests if VM configuration file exists.
3383 # We need that when migration VMs to other nodes (files already moved)
3384 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3386 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3388 $force = 1 if !defined($force) && !$shutdown;
3391 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3392 kill 15, $pid if $pid;
3393 my $conf = load_config
($vmid, $migratedfrom);
3394 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3398 lock_config
($vmid, sub {
3400 my $pid = check_running
($vmid, $nocheck);
3405 $conf = load_config
($vmid);
3406 check_lock
($conf) if !$skiplock;
3407 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3408 my $opts = parse_startup
($conf->{startup
});
3409 $timeout = $opts->{down
} if $opts->{down
};
3413 $timeout = 60 if !defined($timeout);
3417 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3420 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3427 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3432 if ($count >= $timeout) {
3434 warn "VM still running - terminating now with SIGTERM\n";
3437 die "VM quit/powerdown failed - got timeout\n";
3440 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3445 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3448 die "VM quit/powerdown failed\n";
3456 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3461 if ($count >= $timeout) {
3462 warn "VM still running - terminating now with SIGKILL\n";
3467 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3472 my ($vmid, $skiplock) = @_;
3474 lock_config
($vmid, sub {
3476 my $conf = load_config
($vmid);
3478 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3480 vm_mon_cmd
($vmid, "stop");
3485 my ($vmid, $skiplock) = @_;
3487 lock_config
($vmid, sub {
3489 my $conf = load_config
($vmid);
3491 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3493 vm_mon_cmd
($vmid, "cont");
3498 my ($vmid, $skiplock, $key) = @_;
3500 lock_config
($vmid, sub {
3502 my $conf = load_config
($vmid);
3504 # there is no qmp command, so we use the human monitor command
3505 vm_human_monitor_command
($vmid, "sendkey $key");
3510 my ($storecfg, $vmid, $skiplock) = @_;
3512 lock_config
($vmid, sub {
3514 my $conf = load_config
($vmid);
3516 check_lock
($conf) if !$skiplock;
3518 if (!check_running
($vmid)) {
3519 fairsched_rmnod
($vmid); # try to destroy group
3520 destroy_vm
($storecfg, $vmid);
3522 die "VM $vmid is running - destroy failed\n";
3530 my ($filename, $buf) = @_;
3532 my $fh = IO
::File-
>new($filename, "w");
3533 return undef if !$fh;
3535 my $res = print $fh $buf;
3542 sub pci_device_info
{
3547 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3548 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3550 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3551 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3553 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3554 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3556 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3557 return undef if !defined($product) || $product !~ s/^0x//;
3562 product
=> $product,
3568 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3577 my $name = $dev->{name
};
3579 my $fn = "$pcisysfs/devices/$name/reset";
3581 return file_write
($fn, "1");
3584 sub pci_dev_bind_to_stub
{
3587 my $name = $dev->{name
};
3589 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3590 return 1 if -d
$testdir;
3592 my $data = "$dev->{vendor} $dev->{product}";
3593 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3595 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3596 if (!file_write
($fn, $name)) {
3597 return undef if -f
$fn;
3600 $fn = "$pcisysfs/drivers/pci-stub/bind";
3601 if (! -d
$testdir) {
3602 return undef if !file_write
($fn, $name);
3608 sub print_pci_addr
{
3609 my ($id, $bridges) = @_;
3613 piix3
=> { bus
=> 0, addr
=> 1 },
3614 #addr2 : first videocard
3615 balloon0
=> { bus
=> 0, addr
=> 3 },
3616 watchdog
=> { bus
=> 0, addr
=> 4 },
3617 scsihw0
=> { bus
=> 0, addr
=> 5 },
3618 scsihw1
=> { bus
=> 0, addr
=> 6 },
3619 ahci0
=> { bus
=> 0, addr
=> 7 },
3620 qga0
=> { bus
=> 0, addr
=> 8 },
3621 spice
=> { bus
=> 0, addr
=> 9 },
3622 virtio0
=> { bus
=> 0, addr
=> 10 },
3623 virtio1
=> { bus
=> 0, addr
=> 11 },
3624 virtio2
=> { bus
=> 0, addr
=> 12 },
3625 virtio3
=> { bus
=> 0, addr
=> 13 },
3626 virtio4
=> { bus
=> 0, addr
=> 14 },
3627 virtio5
=> { bus
=> 0, addr
=> 15 },
3628 hostpci0
=> { bus
=> 0, addr
=> 16 },
3629 hostpci1
=> { bus
=> 0, addr
=> 17 },
3630 net0
=> { bus
=> 0, addr
=> 18 },
3631 net1
=> { bus
=> 0, addr
=> 19 },
3632 net2
=> { bus
=> 0, addr
=> 20 },
3633 net3
=> { bus
=> 0, addr
=> 21 },
3634 net4
=> { bus
=> 0, addr
=> 22 },
3635 net5
=> { bus
=> 0, addr
=> 23 },
3636 vga1
=> { bus
=> 0, addr
=> 24 },
3637 vga2
=> { bus
=> 0, addr
=> 25 },
3638 vga3
=> { bus
=> 0, addr
=> 26 },
3639 #addr29 : usb-host (pve-usb.cfg)
3640 'pci.1' => { bus
=> 0, addr
=> 30 },
3641 'pci.2' => { bus
=> 0, addr
=> 31 },
3642 'net6' => { bus
=> 1, addr
=> 1 },
3643 'net7' => { bus
=> 1, addr
=> 2 },
3644 'net8' => { bus
=> 1, addr
=> 3 },
3645 'net9' => { bus
=> 1, addr
=> 4 },
3646 'net10' => { bus
=> 1, addr
=> 5 },
3647 'net11' => { bus
=> 1, addr
=> 6 },
3648 'net12' => { bus
=> 1, addr
=> 7 },
3649 'net13' => { bus
=> 1, addr
=> 8 },
3650 'net14' => { bus
=> 1, addr
=> 9 },
3651 'net15' => { bus
=> 1, addr
=> 10 },
3652 'net16' => { bus
=> 1, addr
=> 11 },
3653 'net17' => { bus
=> 1, addr
=> 12 },
3654 'net18' => { bus
=> 1, addr
=> 13 },
3655 'net19' => { bus
=> 1, addr
=> 14 },
3656 'net20' => { bus
=> 1, addr
=> 15 },
3657 'net21' => { bus
=> 1, addr
=> 16 },
3658 'net22' => { bus
=> 1, addr
=> 17 },
3659 'net23' => { bus
=> 1, addr
=> 18 },
3660 'net24' => { bus
=> 1, addr
=> 19 },
3661 'net25' => { bus
=> 1, addr
=> 20 },
3662 'net26' => { bus
=> 1, addr
=> 21 },
3663 'net27' => { bus
=> 1, addr
=> 22 },
3664 'net28' => { bus
=> 1, addr
=> 23 },
3665 'net29' => { bus
=> 1, addr
=> 24 },
3666 'net30' => { bus
=> 1, addr
=> 25 },
3667 'net31' => { bus
=> 1, addr
=> 26 },
3668 'virtio6' => { bus
=> 2, addr
=> 1 },
3669 'virtio7' => { bus
=> 2, addr
=> 2 },
3670 'virtio8' => { bus
=> 2, addr
=> 3 },
3671 'virtio9' => { bus
=> 2, addr
=> 4 },
3672 'virtio10' => { bus
=> 2, addr
=> 5 },
3673 'virtio11' => { bus
=> 2, addr
=> 6 },
3674 'virtio12' => { bus
=> 2, addr
=> 7 },
3675 'virtio13' => { bus
=> 2, addr
=> 8 },
3676 'virtio14' => { bus
=> 2, addr
=> 9 },
3677 'virtio15' => { bus
=> 2, addr
=> 10 },
3680 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3681 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3682 my $bus = $devices->{$id}->{bus
};
3683 $res = ",bus=pci.$bus,addr=$addr";
3684 $bridges->{$bus} = 1 if $bridges;
3690 # vzdump restore implementaion
3692 sub tar_archive_read_firstfile
{
3693 my $archive = shift;
3695 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3697 # try to detect archive type first
3698 my $pid = open (TMP
, "tar tf '$archive'|") ||
3699 die "unable to open file '$archive'\n";
3700 my $firstfile = <TMP
>;
3704 die "ERROR: archive contaions no data\n" if !$firstfile;
3710 sub tar_restore_cleanup
{
3711 my ($storecfg, $statfile) = @_;
3713 print STDERR
"starting cleanup\n";
3715 if (my $fd = IO
::File-
>new($statfile, "r")) {
3716 while (defined(my $line = <$fd>)) {
3717 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3720 if ($volid =~ m
|^/|) {
3721 unlink $volid || die 'unlink failed\n';
3723 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3725 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3727 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3729 print STDERR
"unable to parse line in statfile - $line";
3736 sub restore_archive
{
3737 my ($archive, $vmid, $user, $opts) = @_;
3739 my $format = $opts->{format
};
3742 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3743 $format = 'tar' if !$format;
3745 } elsif ($archive =~ m/\.tar$/) {
3746 $format = 'tar' if !$format;
3747 } elsif ($archive =~ m/.tar.lzo$/) {
3748 $format = 'tar' if !$format;
3750 } elsif ($archive =~ m/\.vma$/) {
3751 $format = 'vma' if !$format;
3752 } elsif ($archive =~ m/\.vma\.gz$/) {
3753 $format = 'vma' if !$format;
3755 } elsif ($archive =~ m/\.vma\.lzo$/) {
3756 $format = 'vma' if !$format;
3759 $format = 'vma' if !$format; # default
3762 # try to detect archive format
3763 if ($format eq 'tar') {
3764 return restore_tar_archive
($archive, $vmid, $user, $opts);
3766 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3770 sub restore_update_config_line
{
3771 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3773 return if $line =~ m/^\#qmdump\#/;
3774 return if $line =~ m/^\#vzdump\#/;
3775 return if $line =~ m/^lock:/;
3776 return if $line =~ m/^unused\d+:/;
3777 return if $line =~ m/^parent:/;
3778 return if $line =~ m/^template:/; # restored VM is never a template
3780 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3781 # try to convert old 1.X settings
3782 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3783 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3784 my ($model, $macaddr) = split(/\=/, $devconfig);
3785 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3788 bridge
=> "vmbr$ind",
3789 macaddr
=> $macaddr,
3791 my $netstr = print_net
($net);
3793 print $outfd "net$cookie->{netcount}: $netstr\n";
3794 $cookie->{netcount
}++;
3796 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3797 my ($id, $netstr) = ($1, $2);
3798 my $net = parse_net
($netstr);
3799 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3800 $netstr = print_net
($net);
3801 print $outfd "$id: $netstr\n";
3802 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3805 if ($line =~ m/backup=no/) {
3806 print $outfd "#$line";
3807 } elsif ($virtdev && $map->{$virtdev}) {
3808 my $di = parse_drive
($virtdev, $value);
3809 delete $di->{format
}; # format can change on restore
3810 $di->{file
} = $map->{$virtdev};
3811 $value = print_drive
($vmid, $di);
3812 print $outfd "$virtdev: $value\n";
3822 my ($cfg, $vmid) = @_;
3824 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3826 my $volid_hash = {};
3827 foreach my $storeid (keys %$info) {
3828 foreach my $item (@{$info->{$storeid}}) {
3829 next if !($item->{volid
} && $item->{size
});
3830 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3831 $volid_hash->{$item->{volid
}} = $item;
3838 sub get_used_paths
{
3839 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3843 my $scan_config = sub {
3844 my ($cref, $snapname) = @_;
3846 foreach my $key (keys %$cref) {
3847 my $value = $cref->{$key};
3848 if (valid_drivename
($key)) {
3849 next if $skip_drive && $key eq $skip_drive;
3850 my $drive = parse_drive
($key, $value);
3851 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3852 if ($drive->{file
} =~ m!^/!) {
3853 $used_path->{$drive->{file
}}++; # = 1;
3855 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3857 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3859 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3860 $used_path->{$path}++; # = 1;
3866 &$scan_config($conf);
3870 if ($scan_snapshots) {
3871 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3872 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3879 sub update_disksize
{
3880 my ($vmid, $conf, $volid_hash) = @_;
3886 # Note: it is allowed to define multiple storages with same path (alias), so
3887 # we need to check both 'volid' and real 'path' (two different volid can point
3888 # to the same path).
3893 foreach my $opt (keys %$conf) {
3894 if (valid_drivename
($opt)) {
3895 my $drive = parse_drive
($opt, $conf->{$opt});
3896 my $volid = $drive->{file
};
3899 $used->{$volid} = 1;
3900 if ($volid_hash->{$volid} &&
3901 (my $path = $volid_hash->{$volid}->{path
})) {
3902 $usedpath->{$path} = 1;
3905 next if drive_is_cdrom
($drive);
3906 next if !$volid_hash->{$volid};
3908 $drive->{size
} = $volid_hash->{$volid}->{size
};
3909 my $new = print_drive
($vmid, $drive);
3910 if ($new ne $conf->{$opt}) {
3912 $conf->{$opt} = $new;
3917 # remove 'unusedX' entry if volume is used
3918 foreach my $opt (keys %$conf) {
3919 next if $opt !~ m/^unused\d+$/;
3920 my $volid = $conf->{$opt};
3921 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3922 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3924 delete $conf->{$opt};
3928 foreach my $volid (sort keys %$volid_hash) {
3929 next if $volid =~ m/vm-$vmid-state-/;
3930 next if $used->{$volid};
3931 my $path = $volid_hash->{$volid}->{path
};
3932 next if !$path; # just to be sure
3933 next if $usedpath->{$path};
3935 add_unused_volume
($conf, $volid);
3936 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3943 my ($vmid, $nolock) = @_;
3945 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3947 my $volid_hash = scan_volids
($cfg, $vmid);
3949 my $updatefn = sub {
3952 my $conf = load_config
($vmid);
3957 foreach my $volid (keys %$volid_hash) {
3958 my $info = $volid_hash->{$volid};
3959 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3962 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3964 update_config_nolock
($vmid, $conf, 1) if $changes;
3967 if (defined($vmid)) {
3971 lock_config
($vmid, $updatefn, $vmid);
3974 my $vmlist = config_list
();
3975 foreach my $vmid (keys %$vmlist) {
3979 lock_config
($vmid, $updatefn, $vmid);
3985 sub restore_vma_archive
{
3986 my ($archive, $vmid, $user, $opts, $comp) = @_;
3988 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3989 my $readfrom = $archive;
3994 my $qarchive = PVE
::Tools
::shellquote
($archive);
3995 if ($comp eq 'gzip') {
3996 $uncomp = "zcat $qarchive|";
3997 } elsif ($comp eq 'lzop') {
3998 $uncomp = "lzop -d -c $qarchive|";
4000 die "unknown compression method '$comp'\n";
4005 my $tmpdir = "/var/tmp/vzdumptmp$$";
4008 # disable interrupts (always do cleanups)
4009 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4010 warn "got interrupt - ignored\n";
4013 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4014 POSIX
::mkfifo
($mapfifo, 0600);
4017 my $openfifo = sub {
4018 open($fifofh, '>', $mapfifo) || die $!;
4021 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4028 my $rpcenv = PVE
::RPCEnvironment
::get
();
4030 my $conffile = config_file
($vmid);
4031 my $tmpfn = "$conffile.$$.tmp";
4033 # Note: $oldconf is undef if VM does not exists
4034 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
4036 my $print_devmap = sub {
4037 my $virtdev_hash = {};
4039 my $cfgfn = "$tmpdir/qemu-server.conf";
4041 # we can read the config - that is already extracted
4042 my $fh = IO
::File-
>new($cfgfn, "r") ||
4043 "unable to read qemu-server.conf - $!\n";
4045 while (defined(my $line = <$fh>)) {
4046 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4047 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4048 die "archive does not contain data for drive '$virtdev'\n"
4049 if !$devinfo->{$devname};
4050 if (defined($opts->{storage
})) {
4051 $storeid = $opts->{storage
} || 'local';
4052 } elsif (!$storeid) {
4055 $format = 'raw' if !$format;
4056 $devinfo->{$devname}->{devname
} = $devname;
4057 $devinfo->{$devname}->{virtdev
} = $virtdev;
4058 $devinfo->{$devname}->{format
} = $format;
4059 $devinfo->{$devname}->{storeid
} = $storeid;
4061 # check permission on storage
4062 my $pool = $opts->{pool
}; # todo: do we need that?
4063 if ($user ne 'root@pam') {
4064 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4067 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4071 foreach my $devname (keys %$devinfo) {
4072 die "found no device mapping information for device '$devname'\n"
4073 if !$devinfo->{$devname}->{virtdev
};
4076 my $cfg = cfs_read_file
('storage.cfg');
4078 # create empty/temp config
4080 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
4081 foreach_drive
($oldconf, sub {
4082 my ($ds, $drive) = @_;
4084 return if drive_is_cdrom
($drive);
4086 my $volid = $drive->{file
};
4088 return if !$volid || $volid =~ m
|^/|;
4090 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4091 return if !$path || !$owner || ($owner != $vmid);
4093 # Note: only delete disk we want to restore
4094 # other volumes will become unused
4095 if ($virtdev_hash->{$ds}) {
4096 PVE
::Storage
::vdisk_free
($cfg, $volid);
4102 foreach my $virtdev (sort keys %$virtdev_hash) {
4103 my $d = $virtdev_hash->{$virtdev};
4104 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4105 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4107 # test if requested format is supported
4108 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4109 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4110 $d->{format
} = $defFormat if !$supported;
4112 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4113 $d->{format
}, undef, $alloc_size);
4114 print STDERR
"new volume ID is '$volid'\n";
4115 $d->{volid
} = $volid;
4116 my $path = PVE
::Storage
::path
($cfg, $volid);
4118 my $write_zeros = 1;
4119 # fixme: what other storages types initialize volumes with zero?
4120 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4121 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4125 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4127 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4128 $map->{$virtdev} = $volid;
4131 $fh->seek(0, 0) || die "seek failed - $!\n";
4133 my $outfd = new IO
::File
($tmpfn, "w") ||
4134 die "unable to write config for VM $vmid\n";
4136 my $cookie = { netcount
=> 0 };
4137 while (defined(my $line = <$fh>)) {
4138 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4147 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4148 die "interrupted by signal\n";
4150 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4152 $oldtimeout = alarm($timeout);
4159 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4160 my ($dev_id, $size, $devname) = ($1, $2, $3);
4161 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4162 } elsif ($line =~ m/^CTIME: /) {
4163 # we correctly received the vma config, so we can disable
4164 # the timeout now for disk allocation (set to 10 minutes, so
4165 # that we always timeout if something goes wrong)
4168 print $fifofh "done\n";
4169 my $tmp = $oldtimeout || 0;
4170 $oldtimeout = undef;
4176 print "restore vma archive: $cmd\n";
4177 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4181 alarm($oldtimeout) if $oldtimeout;
4189 my $cfg = cfs_read_file
('storage.cfg');
4190 foreach my $devname (keys %$devinfo) {
4191 my $volid = $devinfo->{$devname}->{volid
};
4194 if ($volid =~ m
|^/|) {
4195 unlink $volid || die 'unlink failed\n';
4197 PVE
::Storage
::vdisk_free
($cfg, $volid);
4199 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4201 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4208 rename($tmpfn, $conffile) ||
4209 die "unable to commit configuration file '$conffile'\n";
4211 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4213 eval { rescan
($vmid, 1); };
4217 sub restore_tar_archive
{
4218 my ($archive, $vmid, $user, $opts) = @_;
4220 if ($archive ne '-') {
4221 my $firstfile = tar_archive_read_firstfile
($archive);
4222 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4223 if $firstfile ne 'qemu-server.conf';
4226 my $storecfg = cfs_read_file
('storage.cfg');
4228 # destroy existing data - keep empty config
4229 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4230 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4232 my $tocmd = "/usr/lib/qemu-server/qmextract";
4234 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4235 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4236 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4237 $tocmd .= ' --info' if $opts->{info
};
4239 # tar option "xf" does not autodetect compression when read from STDIN,
4240 # so we pipe to zcat
4241 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4242 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4244 my $tmpdir = "/var/tmp/vzdumptmp$$";
4247 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4248 local $ENV{VZDUMP_VMID
} = $vmid;
4249 local $ENV{VZDUMP_USER
} = $user;
4251 my $conffile = config_file
($vmid);
4252 my $tmpfn = "$conffile.$$.tmp";
4254 # disable interrupts (always do cleanups)
4255 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4256 print STDERR
"got interrupt - ignored\n";
4261 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4262 die "interrupted by signal\n";
4265 if ($archive eq '-') {
4266 print "extracting archive from STDIN\n";
4267 run_command
($cmd, input
=> "<&STDIN");
4269 print "extracting archive '$archive'\n";
4273 return if $opts->{info
};
4277 my $statfile = "$tmpdir/qmrestore.stat";
4278 if (my $fd = IO
::File-
>new($statfile, "r")) {
4279 while (defined (my $line = <$fd>)) {
4280 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4281 $map->{$1} = $2 if $1;
4283 print STDERR
"unable to parse line in statfile - $line\n";
4289 my $confsrc = "$tmpdir/qemu-server.conf";
4291 my $srcfd = new IO
::File
($confsrc, "r") ||
4292 die "unable to open file '$confsrc'\n";
4294 my $outfd = new IO
::File
($tmpfn, "w") ||
4295 die "unable to write config for VM $vmid\n";
4297 my $cookie = { netcount
=> 0 };
4298 while (defined (my $line = <$srcfd>)) {
4299 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4311 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4318 rename $tmpfn, $conffile ||
4319 die "unable to commit configuration file '$conffile'\n";
4321 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4323 eval { rescan
($vmid, 1); };
4328 # Internal snapshots
4330 # NOTE: Snapshot create/delete involves several non-atomic
4331 # action, and can take a long time.
4332 # So we try to avoid locking the file and use 'lock' variable
4333 # inside the config file instead.
4335 my $snapshot_copy_config = sub {
4336 my ($source, $dest) = @_;
4338 foreach my $k (keys %$source) {
4339 next if $k eq 'snapshots';
4340 next if $k eq 'snapstate';
4341 next if $k eq 'snaptime';
4342 next if $k eq 'vmstate';
4343 next if $k eq 'lock';
4344 next if $k eq 'digest';
4345 next if $k eq 'description';
4346 next if $k =~ m/^unused\d+$/;
4348 $dest->{$k} = $source->{$k};
4352 my $snapshot_apply_config = sub {
4353 my ($conf, $snap) = @_;
4355 # copy snapshot list
4357 snapshots
=> $conf->{snapshots
},
4360 # keep description and list of unused disks
4361 foreach my $k (keys %$conf) {
4362 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4363 $newconf->{$k} = $conf->{$k};
4366 &$snapshot_copy_config($snap, $newconf);
4371 sub foreach_writable_storage
{
4372 my ($conf, $func) = @_;
4376 foreach my $ds (keys %$conf) {
4377 next if !valid_drivename
($ds);
4379 my $drive = parse_drive
($ds, $conf->{$ds});
4381 next if drive_is_cdrom
($drive);
4383 my $volid = $drive->{file
};
4385 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4386 $sidhash->{$sid} = $sid if $sid;
4389 foreach my $sid (sort keys %$sidhash) {
4394 my $alloc_vmstate_volid = sub {
4395 my ($storecfg, $vmid, $conf, $snapname) = @_;
4397 # Note: we try to be smart when selecting a $target storage
4401 # search shared storage first
4402 foreach_writable_storage
($conf, sub {
4404 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4405 return if !$scfg->{shared
};
4407 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4411 # now search local storage
4412 foreach_writable_storage
($conf, sub {
4414 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4415 return if $scfg->{shared
};
4417 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4421 $target = 'local' if !$target;
4423 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4424 # we abort live save after $conf->{memory}, so we need at max twice that space
4425 my $size = $conf->{memory
}*2 + $driver_state_size;
4427 my $name = "vm-$vmid-state-$snapname";
4428 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4429 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4430 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4435 my $snapshot_prepare = sub {
4436 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4440 my $updatefn = sub {
4442 my $conf = load_config
($vmid);
4444 die "you can't take a snapshot if it's a template\n"
4445 if is_template
($conf);
4449 $conf->{lock} = 'snapshot';
4451 die "snapshot name '$snapname' already used\n"
4452 if defined($conf->{snapshots
}->{$snapname});
4454 my $storecfg = PVE
::Storage
::config
();
4455 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4457 $snap = $conf->{snapshots
}->{$snapname} = {};
4459 if ($save_vmstate && check_running
($vmid)) {
4460 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4463 &$snapshot_copy_config($conf, $snap);
4465 $snap->{snapstate
} = "prepare";
4466 $snap->{snaptime
} = time();
4467 $snap->{description
} = $comment if $comment;
4469 # always overwrite machine if we save vmstate. This makes sure we
4470 # can restore it later using correct machine type
4471 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4473 update_config_nolock
($vmid, $conf, 1);
4476 lock_config
($vmid, $updatefn);
4481 my $snapshot_commit = sub {
4482 my ($vmid, $snapname) = @_;
4484 my $updatefn = sub {
4486 my $conf = load_config
($vmid);
4488 die "missing snapshot lock\n"
4489 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4491 my $snap = $conf->{snapshots
}->{$snapname};
4493 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4495 die "wrong snapshot state\n"
4496 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4498 delete $snap->{snapstate
};
4499 delete $conf->{lock};
4501 my $newconf = &$snapshot_apply_config($conf, $snap);
4503 $newconf->{parent
} = $snapname;
4505 update_config_nolock
($vmid, $newconf, 1);
4508 lock_config
($vmid, $updatefn);
4511 sub snapshot_rollback
{
4512 my ($vmid, $snapname) = @_;
4518 my $storecfg = PVE
::Storage
::config
();
4520 my $updatefn = sub {
4522 my $conf = load_config
($vmid);
4524 die "you can't rollback if vm is a template\n" if is_template
($conf);
4526 $snap = $conf->{snapshots
}->{$snapname};
4528 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4530 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4531 if $snap->{snapstate
};
4535 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4538 die "unable to rollback vm $vmid: vm is running\n"
4539 if check_running
($vmid);
4542 $conf->{lock} = 'rollback';
4544 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4545 delete $conf->{lock};
4551 my $has_machine_config = defined($conf->{machine
});
4553 # copy snapshot config to current config
4554 $conf = &$snapshot_apply_config($conf, $snap);
4555 $conf->{parent
} = $snapname;
4557 # Note: old code did not store 'machine', so we try to be smart
4558 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4559 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4560 # we remove the 'machine' configuration if not explicitly specified
4561 # in the original config.
4562 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4565 update_config_nolock
($vmid, $conf, 1);
4567 if (!$prepare && $snap->{vmstate
}) {
4568 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4569 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4573 lock_config
($vmid, $updatefn);
4575 foreach_drive
($snap, sub {
4576 my ($ds, $drive) = @_;
4578 return if drive_is_cdrom
($drive);
4580 my $volid = $drive->{file
};
4581 my $device = "drive-$ds";
4583 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4587 lock_config
($vmid, $updatefn);
4590 my $savevm_wait = sub {
4594 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4595 if (!$stat->{status
}) {
4596 die "savevm not active\n";
4597 } elsif ($stat->{status
} eq 'active') {
4600 } elsif ($stat->{status
} eq 'completed') {
4603 die "query-savevm returned status '$stat->{status}'\n";
4608 sub snapshot_create
{
4609 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4611 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4613 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4617 my $running = check_running
($vmid);
4620 # create internal snapshots of all drives
4622 my $storecfg = PVE
::Storage
::config
();
4625 if ($snap->{vmstate
}) {
4626 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4627 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4628 &$savevm_wait($vmid);
4630 vm_mon_cmd
($vmid, "savevm-start");
4634 qga_freezefs
($vmid) if $running && $freezefs;
4636 foreach_drive
($snap, sub {
4637 my ($ds, $drive) = @_;
4639 return if drive_is_cdrom
($drive);
4641 my $volid = $drive->{file
};
4642 my $device = "drive-$ds";
4644 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4645 $drivehash->{$ds} = 1;
4650 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4653 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4657 warn "snapshot create failed: starting cleanup\n";
4658 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4663 &$snapshot_commit($vmid, $snapname);
4666 # Note: $drivehash is only set when called from snapshot_create.
4667 sub snapshot_delete
{
4668 my ($vmid, $snapname, $force, $drivehash) = @_;
4675 my $unlink_parent = sub {
4676 my ($confref, $new_parent) = @_;
4678 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4680 $confref->{parent
} = $new_parent;
4682 delete $confref->{parent
};
4687 my $updatefn = sub {
4688 my ($remove_drive) = @_;
4690 my $conf = load_config
($vmid);
4694 die "you can't delete a snapshot if vm is a template\n"
4695 if is_template
($conf);
4698 $snap = $conf->{snapshots
}->{$snapname};
4700 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4702 # remove parent refs
4703 &$unlink_parent($conf, $snap->{parent
});
4704 foreach my $sn (keys %{$conf->{snapshots
}}) {
4705 next if $sn eq $snapname;
4706 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4709 if ($remove_drive) {
4710 if ($remove_drive eq 'vmstate') {
4711 delete $snap->{$remove_drive};
4713 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4714 my $volid = $drive->{file
};
4715 delete $snap->{$remove_drive};
4716 add_unused_volume
($conf, $volid);
4721 $snap->{snapstate
} = 'delete';
4723 delete $conf->{snapshots
}->{$snapname};
4724 delete $conf->{lock} if $drivehash;
4725 foreach my $volid (@$unused) {
4726 add_unused_volume
($conf, $volid);
4730 update_config_nolock
($vmid, $conf, 1);
4733 lock_config
($vmid, $updatefn);
4735 # now remove vmstate file
4737 my $storecfg = PVE
::Storage
::config
();
4739 if ($snap->{vmstate
}) {
4740 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4742 die $err if !$force;
4745 # save changes (remove vmstate from snapshot)
4746 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4749 # now remove all internal snapshots
4750 foreach_drive
($snap, sub {
4751 my ($ds, $drive) = @_;
4753 return if drive_is_cdrom
($drive);
4755 my $volid = $drive->{file
};
4756 my $device = "drive-$ds";
4758 if (!$drivehash || $drivehash->{$ds}) {
4759 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4761 die $err if !$force;
4766 # save changes (remove drive fron snapshot)
4767 lock_config
($vmid, $updatefn, $ds) if !$force;
4768 push @$unused, $volid;
4771 # now cleanup config
4773 lock_config
($vmid, $updatefn);
4777 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4780 foreach_drive
($conf, sub {
4781 my ($ds, $drive) = @_;
4783 return if drive_is_cdrom
($drive);
4784 my $volid = $drive->{file
};
4785 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4788 return $err ?
0 : 1;
4791 sub template_create
{
4792 my ($vmid, $conf, $disk) = @_;
4794 my $storecfg = PVE
::Storage
::config
();
4796 foreach_drive
($conf, sub {
4797 my ($ds, $drive) = @_;
4799 return if drive_is_cdrom
($drive);
4800 return if $disk && $ds ne $disk;
4802 my $volid = $drive->{file
};
4803 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4805 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4806 $drive->{file
} = $voliddst;
4807 $conf->{$ds} = print_drive
($vmid, $drive);
4808 update_config_nolock
($vmid, $conf, 1);
4815 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4818 sub qemu_img_convert
{
4819 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4821 my $storecfg = PVE
::Storage
::config
();
4822 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4823 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4825 if ($src_storeid && $dst_storeid) {
4826 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4827 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4829 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4830 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4832 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4833 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4836 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4837 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4838 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4842 if($line =~ m/\((\S+)\/100\
%\)/){
4844 my $transferred = int($size * $percent / 100);
4845 my $remaining = $size - $transferred;
4847 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4852 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4854 die "copy failed: $err" if $err;
4858 sub qemu_img_format
{
4859 my ($scfg, $volname) = @_;
4861 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4863 } elsif ($scfg->{type
} eq 'iscsi') {
4864 return "host_device";
4870 sub qemu_drive_mirror
{
4871 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4877 my $storecfg = PVE
::Storage
::config
();
4878 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4881 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4884 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4888 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4891 #fixme : sometime drive-mirror timeout, but works fine after.
4892 # (I have see the problem with big volume > 200GB), so we need to eval
4893 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4894 sync
=> "full", target
=> $dst_path, format
=> $format); };
4896 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4897 sync
=> "full", target
=> $dst_path); };
4902 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4903 my $stat = @$stats[0];
4904 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4905 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4907 my $transferred = $stat->{offset
};
4908 my $total = $stat->{len
};
4909 my $remaining = $total - $transferred;
4910 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4912 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4914 last if ($stat->{len
} == $stat->{offset
});
4915 if ($old_len == $stat->{offset
}) {
4916 if ($maxwait && $count > $maxwait) {
4917 # if writes to disk occurs the disk needs to be freezed
4918 # to be able to complete the migration
4919 vm_suspend
($vmid,1);
4923 $count++ unless $frozen;
4929 $old_len = $stat->{offset
};
4933 if ($vmiddst == $vmid) {
4934 # switch the disk if source and destination are on the same guest
4935 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4939 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4940 die "mirroring error: $err";
4943 if ($vmiddst != $vmid) {
4944 # if we clone a disk for a new target vm, we don't switch the disk
4945 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4951 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4952 $newvmid, $storage, $format, $full, $newvollist) = @_;
4957 print "create linked clone of drive $drivename ($drive->{file})\n";
4958 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4959 push @$newvollist, $newvolid;
4961 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4962 $storeid = $storage if $storage;
4964 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4966 $format = $drive->{format
} || $defFormat;
4969 # test if requested format is supported - else use default
4970 my $supported = grep { $_ eq $format } @$validFormats;
4971 $format = $defFormat if !$supported;
4973 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4975 print "create full clone of drive $drivename ($drive->{file})\n";
4976 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4977 push @$newvollist, $newvolid;
4979 if (!$running || $snapname) {
4980 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4982 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4986 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4989 $disk->{format
} = undef;
4990 $disk->{file
} = $newvolid;
4991 $disk->{size
} = $size;
4996 # this only works if VM is running
4997 sub get_current_qemu_machine
{
5000 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5001 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
5003 my ($current, $default);
5004 foreach my $e (@$res) {
5005 $default = $e->{name
} if $e->{'is-default'};
5006 $current = $e->{name
} if $e->{'is-current'};
5009 # fallback to the default machine if current is not supported by qemu
5010 return $current || $default || 'pc';