1 package PVE
::QemuServer
;
21 use Storable
qw(dclone);
22 use PVE
::Exception
qw(raise raise_param_exc);
24 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline);
25 use PVE
::JSONSchema
qw(get_standard_option);
26 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
30 use PVE
::RPCEnvironment
;
31 use Time
::HiRes
qw(gettimeofday);
33 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
35 # Note about locking: we use flock on the config file protect
36 # against concurent actions.
37 # Aditionaly, we have a 'lock' setting in the config file. This
38 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
39 # allowed when such lock is set. But you can ignore this kind of
40 # lock with the --skiplock flag.
42 cfs_register_file
('/qemu-server/',
46 PVE
::JSONSchema
::register_standard_option
('skiplock', {
47 description
=> "Ignore locks - only root is allowed to use this option.",
52 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
53 description
=> "Some command save/restore state from this location.",
59 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
60 description
=> "The name of the snapshot.",
61 type
=> 'string', format
=> 'pve-configid',
65 #no warnings 'redefine';
67 unless(defined(&_VZSYSCALLS_H_
)) {
68 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
69 require 'sys/syscall.ph';
70 if(defined(&__x86_64__
)) {
71 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
72 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
73 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
74 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
75 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
76 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
77 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
78 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
80 elsif(defined( &__i386__
) ) {
81 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
82 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
83 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
84 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
85 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
86 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
87 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
88 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
90 die("no fairsched syscall for this arch");
92 require 'asm/ioctl.ph';
93 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
97 my ($parent, $weight, $desired) = @_;
99 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
102 sub fairsched_rmnod
{
105 return syscall(&__NR_fairsched_rmnod
, int($id));
109 my ($pid, $newid) = @_;
111 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
114 sub fairsched_vcpus
{
115 my ($id, $vcpus) = @_;
117 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
121 my ($id, $op, $rate) = @_;
123 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
126 use constant FAIRSCHED_SET_RATE
=> 0;
127 use constant FAIRSCHED_DROP_RATE
=> 1;
128 use constant FAIRSCHED_GET_RATE
=> 2;
130 sub fairsched_cpulimit
{
131 my ($id, $limit) = @_;
133 my $cpulim1024 = int($limit * 1024 / 100);
134 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
136 return fairsched_rate
($id, $op, $cpulim1024);
139 my $nodename = PVE
::INotify
::nodename
();
141 mkdir "/etc/pve/nodes/$nodename";
142 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
145 my $var_run_tmpdir = "/var/run/qemu-server";
146 mkdir $var_run_tmpdir;
148 my $lock_dir = "/var/lock/qemu-server";
151 my $pcisysfs = "/sys/bus/pci";
157 description
=> "Specifies whether a VM will be started during system bootup.",
163 description
=> "Automatic restart after crash (currently ignored).",
169 description
=> "Allow hotplug for disk and network device",
175 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
181 description
=> "Lock/unlock the VM.",
182 enum
=> [qw(migrate backup snapshot rollback)],
187 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.",
194 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.",
202 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
209 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
215 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",
223 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
224 enum
=> PVE
::Tools
::kvmkeymaplist
(),
229 type
=> 'string', format
=> 'dns-name',
230 description
=> "Set a name for the VM. Only used on the configuration web interface.",
235 description
=> "scsi controller model",
236 enum
=> [qw(lsi virtio-scsi-pci megasas)],
242 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
247 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
248 description
=> <<EODESC,
249 Used to enable special optimization/features for specific
252 other => unspecified OS
253 wxp => Microsoft Windows XP
254 w2k => Microsoft Windows 2000
255 w2k3 => Microsoft Windows 2003
256 w2k8 => Microsoft Windows 2008
257 wvista => Microsoft Windows Vista
258 win7 => Microsoft Windows 7
259 win8 => Microsoft Windows 8/2012
260 l24 => Linux 2.4 Kernel
261 l26 => Linux 2.6/3.X Kernel
263 other|l24|l26 ... no special behaviour
264 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
270 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
271 pattern
=> '[acdn]{1,4}',
276 type
=> 'string', format
=> 'pve-qm-bootdisk',
277 description
=> "Enable booting from specified disk.",
278 pattern
=> '(ide|sata|scsi|virtio)\d+',
283 description
=> "The number of CPUs. Please use option -sockets instead.",
290 description
=> "The number of CPU sockets.",
297 description
=> "The number of cores per socket.",
304 description
=> "Enable/disable ACPI.",
310 description
=> "Enable/disable Qemu GuestAgent.",
316 description
=> "Enable/disable KVM hardware virtualization.",
322 description
=> "Enable/disable time drift fix.",
328 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
333 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
338 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.",
339 enum
=> [qw(std cirrus vmware qxl)],
343 type
=> 'string', format
=> 'pve-qm-watchdog',
344 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
345 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)",
350 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
351 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'.",
352 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
357 type
=> 'string', format
=> 'pve-qm-startup',
358 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
359 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.",
364 description
=> "Enable/disable Template.",
370 description
=> <<EODESCR,
371 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
373 args: -no-reboot -no-hpet
380 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. 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.",
385 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
389 migrate_downtime
=> {
392 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
398 type
=> 'string', format
=> 'pve-qm-drive',
399 typetext
=> 'volume',
400 description
=> "This is an alias for option -ide2",
404 description
=> "Emulated CPU type.",
406 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) ],
409 parent
=> get_standard_option
('pve-snapshot-name', {
411 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
415 description
=> "Timestamp for snapshots.",
421 type
=> 'string', format
=> 'pve-volume-id',
422 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
425 description
=> "Specific the Qemu machine type.",
427 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
433 # what about other qemu settings ?
435 #machine => 'string',
448 ##soundhw => 'string',
450 while (my ($k, $v) = each %$confdesc) {
451 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
454 my $MAX_IDE_DISKS = 4;
455 my $MAX_SCSI_DISKS = 14;
456 my $MAX_VIRTIO_DISKS = 16;
457 my $MAX_SATA_DISKS = 6;
458 my $MAX_USB_DEVICES = 5;
460 my $MAX_UNUSED_DISKS = 8;
461 my $MAX_HOSTPCI_DEVICES = 2;
462 my $MAX_SERIAL_PORTS = 4;
463 my $MAX_PARALLEL_PORTS = 3;
465 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
466 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
467 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
471 type
=> 'string', format
=> 'pve-qm-net',
472 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
473 description
=> <<EODESCR,
474 Specify network devices.
476 MODEL is one of: $nic_model_list_txt
478 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
479 automatically generated if not specified.
481 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
483 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'.
485 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
491 The DHCP server assign addresses to the guest starting from 10.0.2.15.
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
497 for (my $i = 0; $i < $MAX_NETS; $i++) {
498 $confdesc->{"net$i"} = $netdesc;
505 type
=> 'string', format
=> 'pve-qm-drive',
506 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]',
507 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
509 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
513 type
=> 'string', format
=> 'pve-qm-drive',
514 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]',
515 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
517 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
521 type
=> 'string', format
=> 'pve-qm-drive',
522 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]',
523 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
525 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
529 type
=> 'string', format
=> 'pve-qm-drive',
530 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]',
531 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
533 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
537 type
=> 'string', format
=> 'pve-qm-usb-device',
538 typetext
=> 'host=HOSTUSBDEVICE',
539 description
=> <<EODESCR,
540 Configure an USB device (n is 0 to 4). This can be used to
541 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
543 'bus-port(.port)*' (decimal numbers) or
544 'vendor_id:product_id' (hexadeciaml numbers)
546 You can use the 'lsusb -t' command to list existing usb devices.
548 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
552 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
556 type
=> 'string', format
=> 'pve-qm-hostpci',
557 typetext
=> "HOSTPCIDEVICE",
558 description
=> <<EODESCR,
559 Map host pci devices. HOSTPCIDEVICE syntax is:
561 'bus:dev.func' (hexadecimal numbers)
563 You can us the 'lspci' command to list existing pci devices.
565 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
567 Experimental: user reported problems with this option.
570 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
575 pattern
=> '/dev/ttyS\d+',
576 description
=> <<EODESCR,
577 Map host serial devices (n is 0 to 3).
579 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
581 Experimental: user reported problems with this option.
588 pattern
=> '/dev/parport\d+',
589 description
=> <<EODESCR,
590 Map host parallel devices (n is 0 to 2).
592 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
594 Experimental: user reported problems with this option.
598 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
599 $confdesc->{"parallel$i"} = $paralleldesc;
602 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
603 $confdesc->{"serial$i"} = $serialdesc;
606 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
607 $confdesc->{"hostpci$i"} = $hostpcidesc;
610 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
611 $drivename_hash->{"ide$i"} = 1;
612 $confdesc->{"ide$i"} = $idedesc;
615 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
616 $drivename_hash->{"sata$i"} = 1;
617 $confdesc->{"sata$i"} = $satadesc;
620 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
621 $drivename_hash->{"scsi$i"} = 1;
622 $confdesc->{"scsi$i"} = $scsidesc ;
625 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
626 $drivename_hash->{"virtio$i"} = 1;
627 $confdesc->{"virtio$i"} = $virtiodesc;
630 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
631 $confdesc->{"usb$i"} = $usbdesc;
636 type
=> 'string', format
=> 'pve-volume-id',
637 description
=> "Reference to unused volumes.",
640 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
641 $confdesc->{"unused$i"} = $unuseddesc;
644 my $kvm_api_version = 0;
648 return $kvm_api_version if $kvm_api_version;
650 my $fh = IO
::File-
>new("</dev/kvm") ||
653 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
654 $kvm_api_version = $v;
659 return $kvm_api_version;
662 my $kvm_user_version;
664 sub kvm_user_version
{
666 return $kvm_user_version if $kvm_user_version;
668 $kvm_user_version = 'unknown';
670 my $tmp = `kvm -help 2>/dev/null`;
672 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
673 $kvm_user_version = $2;
676 return $kvm_user_version;
680 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
683 # order is important - used to autoselect boot disk
684 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
685 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
686 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
687 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
690 sub valid_drivename
{
693 return defined($drivename_hash->{$dev});
698 return defined($confdesc->{$key});
702 return $nic_model_list;
705 sub os_list_description
{
710 w2k
=> 'Windows 2000',
711 w2k3
=>, 'Windows 2003',
712 w2k8
=> 'Windows 2008',
713 wvista
=> 'Windows Vista',
715 win8
=> 'Windows 8/2012',
725 return $cdrom_path if $cdrom_path;
727 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
728 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
729 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
733 my ($storecfg, $vmid, $cdrom) = @_;
735 if ($cdrom eq 'cdrom') {
736 return get_cdrom_path
();
737 } elsif ($cdrom eq 'none') {
739 } elsif ($cdrom =~ m
|^/|) {
742 return PVE
::Storage
::path
($storecfg, $cdrom);
746 # try to convert old style file names to volume IDs
747 sub filename_to_volume_id
{
748 my ($vmid, $file, $media) = @_;
750 if (!($file eq 'none' || $file eq 'cdrom' ||
751 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
753 return undef if $file =~ m
|/|;
755 if ($media && $media eq 'cdrom') {
756 $file = "local:iso/$file";
758 $file = "local:$vmid/$file";
765 sub verify_media_type
{
766 my ($opt, $vtype, $media) = @_;
771 if ($media eq 'disk') {
773 } elsif ($media eq 'cdrom') {
776 die "internal error";
779 return if ($vtype eq $etype);
781 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
784 sub cleanup_drive_path
{
785 my ($opt, $storecfg, $drive) = @_;
787 # try to convert filesystem paths to volume IDs
789 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
790 ($drive->{file
} !~ m
|^/dev/.+|) &&
791 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
792 ($drive->{file
} !~ m/^\d+$/)) {
793 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
794 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
795 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
796 verify_media_type
($opt, $vtype, $drive->{media
});
797 $drive->{file
} = $volid;
800 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
803 sub create_conf_nolock
{
804 my ($vmid, $settings) = @_;
806 my $filename = config_file
($vmid);
808 die "configuration file '$filename' already exists\n" if -f
$filename;
810 my $defaults = load_defaults
();
812 $settings->{name
} = "vm$vmid" if !$settings->{name
};
813 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
816 foreach my $opt (keys %$settings) {
817 next if !$confdesc->{$opt};
819 my $value = $settings->{$opt};
822 $data .= "$opt: $value\n";
825 PVE
::Tools
::file_set_contents
($filename, $data);
828 my $parse_size = sub {
831 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
832 my ($size, $unit) = ($1, $3);
835 $size = $size * 1024;
836 } elsif ($unit eq 'M') {
837 $size = $size * 1024 * 1024;
838 } elsif ($unit eq 'G') {
839 $size = $size * 1024 * 1024 * 1024;
845 my $format_size = sub {
850 my $kb = int($size/1024);
851 return $size if $kb*1024 != $size;
853 my $mb = int($kb/1024);
854 return "${kb}K" if $mb*1024 != $kb;
856 my $gb = int($mb/1024);
857 return "${mb}M" if $gb*1024 != $mb;
862 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
863 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
864 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
865 # [,aio=native|threads]
868 my ($key, $data) = @_;
872 # $key may be undefined - used to verify JSON parameters
873 if (!defined($key)) {
874 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
876 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
877 $res->{interface
} = $1;
883 foreach my $p (split (/,/, $data)) {
884 next if $p =~ m/^\s*$/;
886 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|bps_rd|mbps_rd|bps_wr|mbps_wr|iops|iops_rd|iops_wr|size)=(.+)$/) {
887 my ($k, $v) = ($1, $2);
889 $k = 'file' if $k eq 'volume';
891 return undef if defined $res->{$k};
893 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
894 return undef if !$v || $v !~ m/^\d+/;
896 $v = sprintf("%.3f", $v / (1024*1024));
900 if (!$res->{file
} && $p !~ m/=/) {
908 return undef if !$res->{file
};
910 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
914 return undef if $res->{cache
} &&
915 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
916 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
917 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
918 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
919 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
920 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
921 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
922 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
923 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
924 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
925 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
926 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
929 return undef if $res->{mbps_rd
} && $res->{mbps
};
930 return undef if $res->{mbps_wr
} && $res->{mbps
};
932 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
933 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
934 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
936 return undef if $res->{iops_rd
} && $res->{iops
};
937 return undef if $res->{iops_wr
} && $res->{iops
};
938 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
939 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
940 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
944 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
947 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
948 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
949 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
950 return undef if $res->{interface
} eq 'virtio';
953 # rerror does not work with scsi drives
954 if ($res->{rerror
}) {
955 return undef if $res->{interface
} eq 'scsi';
961 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
964 my ($vmid, $drive) = @_;
967 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
968 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
971 if ($drive->{size
}) {
972 $opts .= ",size=" . &$format_size($drive->{size
});
975 return "$drive->{file}$opts";
979 my($fh, $noerr) = @_;
982 my $SG_GET_VERSION_NUM = 0x2282;
984 my $versionbuf = "\x00" x
8;
985 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
987 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
990 my $version = unpack("I", $versionbuf);
991 if ($version < 30000) {
992 die "scsi generic interface too old\n" if !$noerr;
996 my $buf = "\x00" x
36;
997 my $sensebuf = "\x00" x
8;
998 my $cmd = pack("C x3 C x1", 0x12, 36);
1000 # see /usr/include/scsi/sg.h
1001 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";
1003 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1004 length($sensebuf), 0, length($buf), $buf,
1005 $cmd, $sensebuf, 6000);
1007 $ret = ioctl($fh, $SG_IO, $packet);
1009 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1013 my @res = unpack($sg_io_hdr_t, $packet);
1014 if ($res[17] || $res[18]) {
1015 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1020 (my $byte0, my $byte1, $res->{vendor
},
1021 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1023 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1024 $res->{type
} = $byte0 & 31;
1032 my $fh = IO
::File-
>new("+<$path") || return undef;
1033 my $res = scsi_inquiry
($fh, 1);
1039 sub print_drivedevice_full
{
1040 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1045 if ($drive->{interface
} eq 'virtio') {
1046 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1047 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1048 } elsif ($drive->{interface
} eq 'scsi') {
1049 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1050 my $controller = int($drive->{index} / $maxdev);
1051 my $unit = $drive->{index} % $maxdev;
1052 my $devicetype = 'hd';
1054 if (drive_is_cdrom
($drive)) {
1057 if ($drive->{file
} =~ m
|^/|) {
1058 $path = $drive->{file
};
1060 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1063 if($path =~ m/^iscsi\:\/\
//){
1064 $devicetype = 'generic';
1066 if (my $info = path_is_scsi
($path)) {
1067 if ($info->{type
} == 0) {
1068 $devicetype = 'block';
1069 } elsif ($info->{type
} == 1) { # tape
1070 $devicetype = 'generic';
1076 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1077 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}" if !$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi';
1079 $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}";
1082 } elsif ($drive->{interface
} eq 'ide'){
1084 my $controller = int($drive->{index} / $maxdev);
1085 my $unit = $drive->{index} % $maxdev;
1086 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1088 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1089 } elsif ($drive->{interface
} eq 'sata'){
1090 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1091 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1092 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1093 } elsif ($drive->{interface
} eq 'usb') {
1095 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1097 die "unsupported interface type";
1100 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1105 sub print_drive_full
{
1106 my ($storecfg, $vmid, $drive) = @_;
1109 foreach my $o (@qemu_drive_options) {
1110 next if $o eq 'bootindex';
1111 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1114 foreach my $o (qw(bps bps_rd bps_wr)) {
1115 my $v = $drive->{"m$o"};
1116 $opts .= ",$o=" . int($v*1024*1024) if $v;
1119 # use linux-aio by default (qemu default is threads)
1120 $opts .= ",aio=native" if !$drive->{aio
};
1123 my $volid = $drive->{file
};
1124 if (drive_is_cdrom
($drive)) {
1125 $path = get_iso_path
($storecfg, $vmid, $volid);
1127 if ($volid =~ m
|^/|) {
1130 $path = PVE
::Storage
::path
($storecfg, $volid);
1134 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1136 my $pathinfo = $path ?
"file=$path," : '';
1138 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1141 sub print_netdevice_full
{
1142 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1144 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1146 my $device = $net->{model
};
1147 if ($net->{model
} eq 'virtio') {
1148 $device = 'virtio-net-pci';
1151 # qemu > 0.15 always try to boot from network - we disable that by
1152 # not loading the pxe rom file
1153 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1154 my $pciaddr = print_pci_addr
("$netid", $bridges);
1155 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1156 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1160 sub print_netdev_full
{
1161 my ($vmid, $conf, $net, $netid) = @_;
1164 if ($netid =~ m/^net(\d+)$/) {
1168 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1170 my $ifname = "tap${vmid}i$i";
1172 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1173 die "interface name '$ifname' is too long (max 15 character)\n"
1174 if length($ifname) >= 16;
1176 my $vhostparam = '';
1177 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1179 my $vmname = $conf->{name
} || "vm$vmid";
1181 if ($net->{bridge
}) {
1182 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1184 return "type=user,id=$netid,hostname=$vmname";
1188 sub drive_is_cdrom
{
1191 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1198 return undef if !$value;
1202 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1203 $res->{pciid
} = $value;
1211 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1217 foreach my $kvp (split(/,/, $data)) {
1219 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1221 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1222 $res->{model
} = $model;
1223 $res->{macaddr
} = $mac;
1224 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1225 $res->{bridge
} = $1;
1226 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1228 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1236 return undef if !$res->{model
};
1244 my $res = "$net->{model}";
1245 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1246 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1247 $res .= ",rate=$net->{rate}" if $net->{rate
};
1248 $res .= ",tag=$net->{tag}" if $net->{tag
};
1253 sub add_random_macs
{
1254 my ($settings) = @_;
1256 foreach my $opt (keys %$settings) {
1257 next if $opt !~ m/^net(\d+)$/;
1258 my $net = parse_net
($settings->{$opt});
1260 $settings->{$opt} = print_net
($net);
1264 sub add_unused_volume
{
1265 my ($config, $volid) = @_;
1268 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1269 my $test = "unused$ind";
1270 if (my $vid = $config->{$test}) {
1271 return if $vid eq $volid; # do not add duplicates
1277 die "To many unused volume - please delete them first.\n" if !$key;
1279 $config->{$key} = $volid;
1284 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1285 sub verify_bootdisk
{
1286 my ($value, $noerr) = @_;
1288 return $value if valid_drivename
($value);
1290 return undef if $noerr;
1292 die "invalid boot disk '$value'\n";
1295 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1297 my ($value, $noerr) = @_;
1299 return $value if parse_net
($value);
1301 return undef if $noerr;
1303 die "unable to parse network options\n";
1306 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1308 my ($value, $noerr) = @_;
1310 return $value if parse_drive
(undef, $value);
1312 return undef if $noerr;
1314 die "unable to parse drive options\n";
1317 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1318 sub verify_hostpci
{
1319 my ($value, $noerr) = @_;
1321 return $value if parse_hostpci
($value);
1323 return undef if $noerr;
1325 die "unable to parse pci id\n";
1328 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1329 sub verify_watchdog
{
1330 my ($value, $noerr) = @_;
1332 return $value if parse_watchdog
($value);
1334 return undef if $noerr;
1336 die "unable to parse watchdog options\n";
1339 sub parse_watchdog
{
1342 return undef if !$value;
1346 foreach my $p (split(/,/, $value)) {
1347 next if $p =~ m/^\s*$/;
1349 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1351 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1352 $res->{action
} = $2;
1361 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1362 sub verify_startup
{
1363 my ($value, $noerr) = @_;
1365 return $value if parse_startup
($value);
1367 return undef if $noerr;
1369 die "unable to parse startup options\n";
1375 return undef if !$value;
1379 foreach my $p (split(/,/, $value)) {
1380 next if $p =~ m/^\s*$/;
1382 if ($p =~ m/^(order=)?(\d+)$/) {
1384 } elsif ($p =~ m/^up=(\d+)$/) {
1386 } elsif ($p =~ m/^down=(\d+)$/) {
1396 sub parse_usb_device
{
1399 return undef if !$value;
1401 my @dl = split(/,/, $value);
1405 foreach my $v (@dl) {
1406 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1408 $res->{vendorid
} = $2;
1409 $res->{productid
} = $4;
1410 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1412 $res->{hostbus
} = $1;
1413 $res->{hostport
} = $2;
1418 return undef if !$found;
1423 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1424 sub verify_usb_device
{
1425 my ($value, $noerr) = @_;
1427 return $value if parse_usb_device
($value);
1429 return undef if $noerr;
1431 die "unable to parse usb device\n";
1434 # add JSON properties for create and set function
1435 sub json_config_properties
{
1438 foreach my $opt (keys %$confdesc) {
1439 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1440 $prop->{$opt} = $confdesc->{$opt};
1447 my ($key, $value) = @_;
1449 die "unknown setting '$key'\n" if !$confdesc->{$key};
1451 my $type = $confdesc->{$key}->{type
};
1453 if (!defined($value)) {
1454 die "got undefined value\n";
1457 if ($value =~ m/[\n\r]/) {
1458 die "property contains a line feed\n";
1461 if ($type eq 'boolean') {
1462 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1463 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1464 die "type check ('boolean') failed - got '$value'\n";
1465 } elsif ($type eq 'integer') {
1466 return int($1) if $value =~ m/^(\d+)$/;
1467 die "type check ('integer') failed - got '$value'\n";
1468 } elsif ($type eq 'number') {
1469 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1470 die "type check ('number') failed - got '$value'\n";
1471 } elsif ($type eq 'string') {
1472 if (my $fmt = $confdesc->{$key}->{format
}) {
1473 if ($fmt eq 'pve-qm-drive') {
1474 # special case - we need to pass $key to parse_drive()
1475 my $drive = parse_drive
($key, $value);
1476 return $value if $drive;
1477 die "unable to parse drive options\n";
1479 PVE
::JSONSchema
::check_format
($fmt, $value);
1482 $value =~ s/^\"(.*)\"$/$1/;
1485 die "internal error"
1489 sub lock_config_full
{
1490 my ($vmid, $timeout, $code, @param) = @_;
1492 my $filename = config_file_lock
($vmid);
1494 my $res = lock_file
($filename, $timeout, $code, @param);
1501 sub lock_config_mode
{
1502 my ($vmid, $timeout, $shared, $code, @param) = @_;
1504 my $filename = config_file_lock
($vmid);
1506 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1514 my ($vmid, $code, @param) = @_;
1516 return lock_config_full
($vmid, 10, $code, @param);
1519 sub cfs_config_path
{
1520 my ($vmid, $node) = @_;
1522 $node = $nodename if !$node;
1523 return "nodes/$node/qemu-server/$vmid.conf";
1526 sub check_iommu_support
{
1527 #fixme : need to check IOMMU support
1528 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1536 my ($vmid, $node) = @_;
1538 my $cfspath = cfs_config_path
($vmid, $node);
1539 return "/etc/pve/$cfspath";
1542 sub config_file_lock
{
1545 return "$lock_dir/lock-$vmid.conf";
1551 my $conf = config_file
($vmid);
1552 utime undef, undef, $conf;
1556 my ($storecfg, $vmid, $keep_empty_config) = @_;
1558 my $conffile = config_file
($vmid);
1560 my $conf = load_config
($vmid);
1564 # only remove disks owned by this VM
1565 foreach_drive
($conf, sub {
1566 my ($ds, $drive) = @_;
1568 return if drive_is_cdrom
($drive);
1570 my $volid = $drive->{file
};
1572 return if !$volid || $volid =~ m
|^/|;
1574 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1575 return if !$path || !$owner || ($owner != $vmid);
1577 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1580 if ($keep_empty_config) {
1581 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1586 # also remove unused disk
1588 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1591 PVE
::Storage
::foreach_volid
($dl, sub {
1592 my ($volid, $sid, $volname, $d) = @_;
1593 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1603 my ($vmid, $node) = @_;
1605 my $cfspath = cfs_config_path
($vmid, $node);
1607 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1609 die "no such VM ('$vmid')\n" if !defined($conf);
1614 sub parse_vm_config
{
1615 my ($filename, $raw) = @_;
1617 return undef if !defined($raw);
1620 digest
=> Digest
::SHA
::sha1_hex
($raw),
1624 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1625 || die "got strange filename '$filename'";
1632 my @lines = split(/\n/, $raw);
1633 foreach my $line (@lines) {
1634 next if $line =~ m/^\s*$/;
1636 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1638 $conf->{description
} = $descr if $descr;
1640 $conf = $res->{snapshots
}->{$snapname} = {};
1644 if ($line =~ m/^\#(.*)\s*$/) {
1645 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1649 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1650 $descr .= PVE
::Tools
::decode_text
($2);
1651 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1652 $conf->{snapstate
} = $1;
1653 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1656 $conf->{$key} = $value;
1657 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1660 eval { $value = check_type
($key, $value); };
1662 warn "vm $vmid - unable to parse value of '$key' - $@";
1664 my $fmt = $confdesc->{$key}->{format
};
1665 if ($fmt && $fmt eq 'pve-qm-drive') {
1666 my $v = parse_drive
($key, $value);
1667 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1668 $v->{file
} = $volid;
1669 $value = print_drive
($vmid, $v);
1671 warn "vm $vmid - unable to parse value of '$key'\n";
1676 if ($key eq 'cdrom') {
1677 $conf->{ide2
} = $value;
1679 $conf->{$key} = $value;
1685 $conf->{description
} = $descr if $descr;
1687 delete $res->{snapstate
}; # just to be sure
1692 sub write_vm_config
{
1693 my ($filename, $conf) = @_;
1695 delete $conf->{snapstate
}; # just to be sure
1697 if ($conf->{cdrom
}) {
1698 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1699 $conf->{ide2
} = $conf->{cdrom
};
1700 delete $conf->{cdrom
};
1703 # we do not use 'smp' any longer
1704 if ($conf->{sockets
}) {
1705 delete $conf->{smp
};
1706 } elsif ($conf->{smp
}) {
1707 $conf->{sockets
} = $conf->{smp
};
1708 delete $conf->{cores
};
1709 delete $conf->{smp
};
1712 my $used_volids = {};
1714 my $cleanup_config = sub {
1715 my ($cref, $snapname) = @_;
1717 foreach my $key (keys %$cref) {
1718 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1719 $key eq 'snapstate';
1720 my $value = $cref->{$key};
1721 eval { $value = check_type
($key, $value); };
1722 die "unable to parse value of '$key' - $@" if $@;
1724 $cref->{$key} = $value;
1726 if (!$snapname && valid_drivename
($key)) {
1727 my $drive = parse_drive
($key, $value);
1728 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1733 &$cleanup_config($conf);
1734 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1735 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1738 # remove 'unusedX' settings if we re-add a volume
1739 foreach my $key (keys %$conf) {
1740 my $value = $conf->{$key};
1741 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1742 delete $conf->{$key};
1746 my $generate_raw_config = sub {
1751 # add description as comment to top of file
1752 my $descr = $conf->{description
} || '';
1753 foreach my $cl (split(/\n/, $descr)) {
1754 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1757 foreach my $key (sort keys %$conf) {
1758 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1759 $raw .= "$key: $conf->{$key}\n";
1764 my $raw = &$generate_raw_config($conf);
1765 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1766 $raw .= "\n[$snapname]\n";
1767 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1773 sub update_config_nolock
{
1774 my ($vmid, $conf, $skiplock) = @_;
1776 check_lock
($conf) if !$skiplock;
1778 my $cfspath = cfs_config_path
($vmid);
1780 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1784 my ($vmid, $conf, $skiplock) = @_;
1786 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1793 # we use static defaults from our JSON schema configuration
1794 foreach my $key (keys %$confdesc) {
1795 if (defined(my $default = $confdesc->{$key}->{default})) {
1796 $res->{$key} = $default;
1800 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1801 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1807 my $vmlist = PVE
::Cluster
::get_vmlist
();
1809 return $res if !$vmlist || !$vmlist->{ids
};
1810 my $ids = $vmlist->{ids
};
1812 foreach my $vmid (keys %$ids) {
1813 my $d = $ids->{$vmid};
1814 next if !$d->{node
} || $d->{node
} ne $nodename;
1815 next if !$d->{type
} || $d->{type
} ne 'qemu';
1816 $res->{$vmid}->{exists} = 1;
1821 # test if VM uses local resources (to prevent migration)
1822 sub check_local_resources
{
1823 my ($conf, $noerr) = @_;
1827 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1828 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1830 foreach my $k (keys %$conf) {
1831 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1834 die "VM uses local resources\n" if $loc_res && !$noerr;
1839 # check if used storages are available on all nodes (use by migrate)
1840 sub check_storage_availability
{
1841 my ($storecfg, $conf, $node) = @_;
1843 foreach_drive
($conf, sub {
1844 my ($ds, $drive) = @_;
1846 my $volid = $drive->{file
};
1849 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1852 # check if storage is available on both nodes
1853 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1854 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1858 # list nodes where all VM images are available (used by has_feature API)
1860 my ($conf, $storecfg) = @_;
1862 my $nodelist = PVE
::Cluster
::get_nodelist
();
1863 my $nodehash = { map { $_ => 1 } @$nodelist };
1864 my $nodename = PVE
::INotify
::nodename
();
1866 foreach_drive
($conf, sub {
1867 my ($ds, $drive) = @_;
1869 my $volid = $drive->{file
};
1872 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1874 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1875 if ($scfg->{disable
}) {
1877 } elsif (my $avail = $scfg->{nodes
}) {
1878 foreach my $node (keys %$nodehash) {
1879 delete $nodehash->{$node} if !$avail->{$node};
1881 } elsif (!$scfg->{shared
}) {
1882 foreach my $node (keys %$nodehash) {
1883 delete $nodehash->{$node} if $node ne $nodename
1895 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1899 my ($pidfile, $pid) = @_;
1901 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1905 return undef if !$line;
1906 my @param = split(/\0/, $line);
1908 my $cmd = $param[0];
1909 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1911 for (my $i = 0; $i < scalar (@param); $i++) {
1914 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1915 my $p = $param[$i+1];
1916 return 1 if $p && ($p eq $pidfile);
1925 my ($vmid, $nocheck, $node) = @_;
1927 my $filename = config_file
($vmid, $node);
1929 die "unable to find configuration file for VM $vmid - no such machine\n"
1930 if !$nocheck && ! -f
$filename;
1932 my $pidfile = pidfile_name
($vmid);
1934 if (my $fd = IO
::File-
>new("<$pidfile")) {
1939 my $mtime = $st->mtime;
1940 if ($mtime > time()) {
1941 warn "file '$filename' modified in future\n";
1944 if ($line =~ m/^(\d+)$/) {
1946 if (check_cmdline
($pidfile, $pid)) {
1947 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1959 my $vzlist = config_list
();
1961 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1963 while (defined(my $de = $fd->read)) {
1964 next if $de !~ m/^(\d+)\.pid$/;
1966 next if !defined($vzlist->{$vmid});
1967 if (my $pid = check_running
($vmid)) {
1968 $vzlist->{$vmid}->{pid
} = $pid;
1976 my ($storecfg, $conf) = @_;
1978 my $bootdisk = $conf->{bootdisk
};
1979 return undef if !$bootdisk;
1980 return undef if !valid_drivename
($bootdisk);
1982 return undef if !$conf->{$bootdisk};
1984 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1985 return undef if !defined($drive);
1987 return undef if drive_is_cdrom
($drive);
1989 my $volid = $drive->{file
};
1990 return undef if !$volid;
1992 return $drive->{size
};
1995 my $last_proc_pid_stat;
1997 # get VM status information
1998 # This must be fast and should not block ($full == false)
1999 # We only query KVM using QMP if $full == true (this can be slow)
2001 my ($opt_vmid, $full) = @_;
2005 my $storecfg = PVE
::Storage
::config
();
2007 my $list = vzlist
();
2008 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2010 my $cpucount = $cpuinfo->{cpus
} || 1;
2012 foreach my $vmid (keys %$list) {
2013 next if $opt_vmid && ($vmid ne $opt_vmid);
2015 my $cfspath = cfs_config_path
($vmid);
2016 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2019 $d->{pid
} = $list->{$vmid}->{pid
};
2021 # fixme: better status?
2022 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2024 my $size = disksize
($storecfg, $conf);
2025 if (defined($size)) {
2026 $d->{disk
} = 0; # no info available
2027 $d->{maxdisk
} = $size;
2033 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2034 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2036 $d->{name
} = $conf->{name
} || "VM $vmid";
2037 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2039 if ($conf->{balloon
}) {
2040 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2041 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2052 $d->{diskwrite
} = 0;
2054 $d->{template
} = is_template
($conf);
2059 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2060 foreach my $dev (keys %$netdev) {
2061 next if $dev !~ m/^tap([1-9]\d*)i/;
2063 my $d = $res->{$vmid};
2066 $d->{netout
} += $netdev->{$dev}->{receive
};
2067 $d->{netin
} += $netdev->{$dev}->{transmit
};
2070 my $ctime = gettimeofday
;
2072 foreach my $vmid (keys %$list) {
2074 my $d = $res->{$vmid};
2075 my $pid = $d->{pid
};
2078 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2079 next if !$pstat; # not running
2081 my $used = $pstat->{utime} + $pstat->{stime
};
2083 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2085 if ($pstat->{vsize
}) {
2086 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2089 my $old = $last_proc_pid_stat->{$pid};
2091 $last_proc_pid_stat->{$pid} = {
2099 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2101 if ($dtime > 1000) {
2102 my $dutime = $used - $old->{used
};
2104 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2105 $last_proc_pid_stat->{$pid} = {
2111 $d->{cpu
} = $old->{cpu
};
2115 return $res if !$full;
2117 my $qmpclient = PVE
::QMPClient-
>new();
2119 my $ballooncb = sub {
2120 my ($vmid, $resp) = @_;
2122 my $info = $resp->{'return'};
2123 return if !$info->{max_mem
};
2125 my $d = $res->{$vmid};
2127 # use memory assigned to VM
2128 $d->{maxmem
} = $info->{max_mem
};
2129 $d->{balloon
} = $info->{actual
};
2131 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2132 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2133 $d->{freemem
} = $info->{free_mem
};
2138 my $blockstatscb = sub {
2139 my ($vmid, $resp) = @_;
2140 my $data = $resp->{'return'} || [];
2141 my $totalrdbytes = 0;
2142 my $totalwrbytes = 0;
2143 for my $blockstat (@$data) {
2144 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2145 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2147 $res->{$vmid}->{diskread
} = $totalrdbytes;
2148 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2151 my $statuscb = sub {
2152 my ($vmid, $resp) = @_;
2154 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2155 # this fails if ballon driver is not loaded, so this must be
2156 # the last commnand (following command are aborted if this fails).
2157 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2159 my $status = 'unknown';
2160 if (!defined($status = $resp->{'return'}->{status
})) {
2161 warn "unable to get VM status\n";
2165 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2168 foreach my $vmid (keys %$list) {
2169 next if $opt_vmid && ($vmid ne $opt_vmid);
2170 next if !$res->{$vmid}->{pid
}; # not running
2171 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2174 $qmpclient->queue_execute();
2176 foreach my $vmid (keys %$list) {
2177 next if $opt_vmid && ($vmid ne $opt_vmid);
2178 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2185 my ($conf, $func) = @_;
2187 foreach my $ds (keys %$conf) {
2188 next if !valid_drivename
($ds);
2190 my $drive = parse_drive
($ds, $conf->{$ds});
2193 &$func($ds, $drive);
2198 my ($conf, $func) = @_;
2202 my $test_volid = sub {
2203 my ($volid, $is_cdrom) = @_;
2207 $volhash->{$volid} = $is_cdrom || 0;
2210 foreach_drive
($conf, sub {
2211 my ($ds, $drive) = @_;
2212 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2215 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2216 my $snap = $conf->{snapshots
}->{$snapname};
2217 &$test_volid($snap->{vmstate
}, 0);
2218 foreach_drive
($snap, sub {
2219 my ($ds, $drive) = @_;
2220 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2224 foreach my $volid (keys %$volhash) {
2225 &$func($volid, $volhash->{$volid});
2229 sub config_to_command
{
2230 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2233 my $globalFlags = [];
2234 my $machineFlags = [];
2240 my $kvmver = kvm_user_version
();
2241 my $vernum = 0; # unknown
2242 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2243 $vernum = $1*1000000+$2*1000;
2244 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2245 $vernum = $1*1000000+$2*1000+$3;
2248 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2250 my $have_ovz = -f
'/proc/vz/vestat';
2252 push @$cmd, '/usr/bin/kvm';
2254 push @$cmd, '-id', $vmid;
2258 my $qmpsocket = qmp_socket
($vmid);
2259 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2260 push @$cmd, '-mon', "chardev=qmp,mode=control";
2262 my $socket = vnc_socket
($vmid);
2263 push @$cmd, '-vnc', "unix:$socket,x509,password";
2265 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2267 push @$cmd, '-daemonize';
2269 $pciaddr = print_pci_addr
("piix3", $bridges);
2270 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2273 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2274 next if !$conf->{"usb$i"};
2277 # include usb device config
2278 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2280 # enable absolute mouse coordinates (needed by vnc)
2281 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2282 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2285 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2286 my $d = parse_hostpci
($conf->{"hostpci$i"});
2288 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2289 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2293 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2294 my $d = parse_usb_device
($conf->{"usb$i"});
2296 if ($d->{vendorid
} && $d->{productid
}) {
2297 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2298 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2299 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2304 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2305 if (my $path = $conf->{"serial$i"}) {
2306 die "no such serial device\n" if ! -c
$path;
2307 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2308 push @$devices, '-device', "isa-serial,chardev=serial$i";
2313 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2314 if (my $path = $conf->{"parallel$i"}) {
2315 die "no such parallel device\n" if ! -c
$path;
2316 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2317 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2321 my $vmname = $conf->{name
} || "vm$vmid";
2323 push @$cmd, '-name', $vmname;
2326 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2327 $sockets = $conf->{sockets
} if $conf->{sockets
};
2329 my $cores = $conf->{cores
} || 1;
2330 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2332 push @$cmd, '-nodefaults';
2334 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2336 my $bootindex_hash = {};
2338 foreach my $o (split(//, $bootorder)) {
2339 $bootindex_hash->{$o} = $i*100;
2343 push @$cmd, '-boot', "menu=on";
2345 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2347 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2349 my $vga = $conf->{vga
};
2351 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' || $conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2358 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2361 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2363 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2364 my $useLocaltime = $conf->{localtime};
2366 if (my $ost = $conf->{ostype
}) {
2367 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2369 if ($ost =~ m/^w/) { # windows
2370 $useLocaltime = 1 if !defined($conf->{localtime});
2372 # use time drift fix when acpi is enabled
2373 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2374 $tdf = 1 if !defined($conf->{tdf
});
2378 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2380 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2381 push @$cmd, '-no-hpet';
2382 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2383 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2386 if ($ost eq 'win7' || $ost eq 'win8') {
2387 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2391 push @$rtcFlags, 'driftfix=slew' if $tdf;
2394 push @$machineFlags, 'accel=tcg';
2396 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2399 my $machine_type = $forcemachine || $conf->{machine
};
2400 if ($machine_type) {
2401 push @$machineFlags, "type=${machine_type}";
2404 if ($conf->{startdate
}) {
2405 push @$rtcFlags, "base=$conf->{startdate}";
2406 } elsif ($useLocaltime) {
2407 push @$rtcFlags, 'base=localtime';
2410 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2411 $cpu = $conf->{cpu
} if $conf->{cpu
};
2413 push @$cpuFlags , '+x2apic' if !$nokvm;
2415 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2417 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2419 push @$cmd, '-cpu', $cpu;
2421 push @$cmd, '-S' if $conf->{freeze
};
2423 # set keyboard layout
2424 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2425 push @$cmd, '-k', $kb if $kb;
2428 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2429 #push @$cmd, '-soundhw', 'es1370';
2430 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2432 if($conf->{agent
}) {
2433 my $qgasocket = qga_socket
($vmid);
2434 my $pciaddr = print_pci_addr
("qga0", $bridges);
2435 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2436 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2437 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2440 if ($vga eq 'qxl') {
2441 my $pciaddr = print_pci_addr
("spice", $bridges);
2444 #my $x509 = "x509-key-file=/etc/pve/local/pve-ssl.key";
2445 #$x509 .= ",x509-cert-file=/etc/pve/local/pve-ssl.pem";
2446 #$x509 .= ",x509-cacert-file=/etc/pve/pve-root-ca.pem";
2448 my $socket = spice_socket
($vmid);
2449 push @$cmd, '-spice', "unix=$socket";
2450 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2451 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2452 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2455 # enable balloon by default, unless explicitly disabled
2456 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2457 $pciaddr = print_pci_addr
("balloon0", $bridges);
2458 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2461 if ($conf->{watchdog
}) {
2462 my $wdopts = parse_watchdog
($conf->{watchdog
});
2463 $pciaddr = print_pci_addr
("watchdog", $bridges);
2464 my $watchdog = $wdopts->{model
} || 'i6300esb';
2465 push @$devices, '-device', "$watchdog$pciaddr";
2466 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2470 my $scsicontroller = {};
2471 my $ahcicontroller = {};
2472 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2474 foreach_drive
($conf, sub {
2475 my ($ds, $drive) = @_;
2477 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2478 push @$vollist, $drive->{file
};
2481 $use_virtio = 1 if $ds =~ m/^virtio/;
2483 if (drive_is_cdrom
($drive)) {
2484 if ($bootindex_hash->{d
}) {
2485 $drive->{bootindex
} = $bootindex_hash->{d
};
2486 $bootindex_hash->{d
} += 1;
2489 if ($bootindex_hash->{c
}) {
2490 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2491 $bootindex_hash->{c
} += 1;
2495 if ($drive->{interface
} eq 'scsi') {
2497 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2498 my $controller = int($drive->{index} / $maxdev);
2499 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2500 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2501 $scsicontroller->{$controller}=1;
2504 if ($drive->{interface
} eq 'sata') {
2505 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2506 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2507 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2508 $ahcicontroller->{$controller}=1;
2511 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2512 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2515 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2517 for (my $i = 0; $i < $MAX_NETS; $i++) {
2518 next if !$conf->{"net$i"};
2519 my $d = parse_net
($conf->{"net$i"});
2522 $use_virtio = 1 if $d->{model
} eq 'virtio';
2524 if ($bootindex_hash->{n
}) {
2525 $d->{bootindex
} = $bootindex_hash->{n
};
2526 $bootindex_hash->{n
} += 1;
2529 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2530 push @$devices, '-netdev', $netdevfull;
2532 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2533 push @$devices, '-device', $netdevicefull;
2537 while (my ($k, $v) = each %$bridges) {
2538 $pciaddr = print_pci_addr
("pci.$k");
2539 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2543 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2544 # when the VM uses virtio devices.
2545 if (!$use_virtio && $have_ovz) {
2547 my $cpuunits = defined($conf->{cpuunits
}) ?
2548 $conf->{cpuunits
} : $defaults->{cpuunits
};
2550 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2552 # fixme: cpulimit is currently ignored
2553 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2557 if ($conf->{args
}) {
2558 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2562 push @$cmd, @$devices;
2563 push @$cmd, '-rtc', join(',', @$rtcFlags)
2564 if scalar(@$rtcFlags);
2565 push @$cmd, '-machine', join(',', @$machineFlags)
2566 if scalar(@$machineFlags);
2567 push @$cmd, '-global', join(',', @$globalFlags)
2568 if scalar(@$globalFlags);
2570 return wantarray ?
($cmd, $vollist) : $cmd;
2575 return "${var_run_tmpdir}/$vmid.vnc";
2580 return "${var_run_tmpdir}/$vmid.spice";
2585 return "${var_run_tmpdir}/$vmid.qmp";
2590 return "${var_run_tmpdir}/$vmid.qga";
2595 return "${var_run_tmpdir}/$vmid.pid";
2598 sub vm_devices_list
{
2601 my $res = vm_mon_cmd
($vmid, 'query-pci');
2604 foreach my $pcibus (@$res) {
2605 foreach my $device (@{$pcibus->{devices
}}) {
2606 next if !$device->{'qdev_id'};
2607 $devices->{$device->{'qdev_id'}} = $device;
2615 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2617 return 1 if !check_running
($vmid);
2619 if ($deviceid eq 'tablet') {
2620 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2621 qemu_deviceadd
($vmid, $devicefull);
2625 return 1 if !$conf->{hotplug
};
2627 my $devices_list = vm_devices_list
($vmid);
2628 return 1 if defined($devices_list->{$deviceid});
2630 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2632 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2633 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2634 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2635 qemu_deviceadd
($vmid, $devicefull);
2636 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2637 qemu_drivedel
($vmid, $deviceid);
2642 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2643 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2644 my $pciaddr = print_pci_addr
($deviceid);
2645 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2646 qemu_deviceadd
($vmid, $devicefull);
2647 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2650 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2651 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2652 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2653 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2654 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2655 if(!qemu_deviceadd
($vmid, $devicefull)) {
2656 qemu_drivedel
($vmid, $deviceid);
2661 if ($deviceid =~ m/^(net)(\d+)$/) {
2662 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2663 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2664 qemu_deviceadd
($vmid, $netdevicefull);
2665 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2666 qemu_netdevdel
($vmid, $deviceid);
2671 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2673 my $pciaddr = print_pci_addr
($deviceid);
2674 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2675 qemu_deviceadd
($vmid, $devicefull);
2676 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2682 sub vm_deviceunplug
{
2683 my ($vmid, $conf, $deviceid) = @_;
2685 return 1 if !check_running
($vmid);
2687 if ($deviceid eq 'tablet') {
2688 qemu_devicedel
($vmid, $deviceid);
2692 return 1 if !$conf->{hotplug
};
2694 my $devices_list = vm_devices_list
($vmid);
2695 return 1 if !defined($devices_list->{$deviceid});
2697 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2699 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2700 qemu_devicedel
($vmid, $deviceid);
2701 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2702 return undef if !qemu_drivedel
($vmid, $deviceid);
2705 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2706 return undef if !qemu_devicedel
($vmid, $deviceid);
2709 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2710 return undef if !qemu_devicedel
($vmid, $deviceid);
2711 return undef if !qemu_drivedel
($vmid, $deviceid);
2714 if ($deviceid =~ m/^(net)(\d+)$/) {
2715 qemu_devicedel
($vmid, $deviceid);
2716 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2717 return undef if !qemu_netdevdel
($vmid, $deviceid);
2723 sub qemu_deviceadd
{
2724 my ($vmid, $devicefull) = @_;
2726 $devicefull = "driver=".$devicefull;
2727 my %options = split(/[=,]/, $devicefull);
2729 vm_mon_cmd
($vmid, "device_add" , %options);
2733 sub qemu_devicedel
{
2734 my($vmid, $deviceid) = @_;
2735 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2740 my($storecfg, $vmid, $device) = @_;
2742 my $drive = print_drive_full
($storecfg, $vmid, $device);
2743 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2744 # If the command succeeds qemu prints: "OK"
2745 if ($ret !~ m/OK/s) {
2746 syslog
("err", "adding drive failed: $ret");
2753 my($vmid, $deviceid) = @_;
2755 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2757 if ($ret =~ m/Device \'.*?\' not found/s) {
2758 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2760 elsif ($ret ne "") {
2761 syslog
("err", "deleting drive $deviceid failed : $ret");
2767 sub qemu_deviceaddverify
{
2768 my ($vmid,$deviceid) = @_;
2770 for (my $i = 0; $i <= 5; $i++) {
2771 my $devices_list = vm_devices_list
($vmid);
2772 return 1 if defined($devices_list->{$deviceid});
2775 syslog
("err", "error on hotplug device $deviceid");
2780 sub qemu_devicedelverify
{
2781 my ($vmid,$deviceid) = @_;
2783 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2784 for (my $i = 0; $i <= 5; $i++) {
2785 my $devices_list = vm_devices_list
($vmid);
2786 return 1 if !defined($devices_list->{$deviceid});
2789 syslog
("err", "error on hot-unplugging device $deviceid");
2793 sub qemu_findorcreatescsihw
{
2794 my ($storecfg, $conf, $vmid, $device) = @_;
2796 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2797 my $controller = int($device->{index} / $maxdev);
2798 my $scsihwid="scsihw$controller";
2799 my $devices_list = vm_devices_list
($vmid);
2801 if(!defined($devices_list->{$scsihwid})) {
2802 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2807 sub qemu_bridgeadd
{
2808 my ($storecfg, $conf, $vmid, $device) = @_;
2811 my $bridgeid = undef;
2812 print_pci_addr
($device, $bridges);
2814 while (my ($k, $v) = each %$bridges) {
2817 return if !$bridgeid || $bridgeid < 1;
2818 my $bridge = "pci.$bridgeid";
2819 my $devices_list = vm_devices_list
($vmid);
2821 if(!defined($devices_list->{$bridge})) {
2822 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2827 sub qemu_netdevadd
{
2828 my ($vmid, $conf, $device, $deviceid) = @_;
2830 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2831 my %options = split(/[=,]/, $netdev);
2833 vm_mon_cmd
($vmid, "netdev_add", %options);
2837 sub qemu_netdevdel
{
2838 my ($vmid, $deviceid) = @_;
2840 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2844 sub qemu_block_set_io_throttle
{
2845 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2847 return if !check_running
($vmid) ;
2849 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));
2853 # old code, only used to shutdown old VM after update
2855 my ($fh, $timeout) = @_;
2857 my $sel = new IO
::Select
;
2864 while (scalar (@ready = $sel->can_read($timeout))) {
2866 if ($count = $fh->sysread($buf, 8192)) {
2867 if ($buf =~ /^(.*)\(qemu\) $/s) {
2874 if (!defined($count)) {
2881 die "monitor read timeout\n" if !scalar(@ready);
2886 # old code, only used to shutdown old VM after update
2887 sub vm_monitor_command
{
2888 my ($vmid, $cmdstr, $nocheck) = @_;
2893 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2895 my $sname = "${var_run_tmpdir}/$vmid.mon";
2897 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2898 die "unable to connect to VM $vmid socket - $!\n";
2902 # hack: migrate sometime blocks the monitor (when migrate_downtime
2904 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2905 $timeout = 60*60; # 1 hour
2909 my $data = __read_avail
($sock, $timeout);
2911 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2912 die "got unexpected qemu monitor banner\n";
2915 my $sel = new IO
::Select
;
2918 if (!scalar(my @ready = $sel->can_write($timeout))) {
2919 die "monitor write error - timeout";
2922 my $fullcmd = "$cmdstr\r";
2924 # syslog('info', "VM $vmid monitor command: $cmdstr");
2927 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2928 die "monitor write error - $!";
2931 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2935 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2936 $timeout = 60*60; # 1 hour
2937 } elsif ($cmdstr =~ m/^(eject|change)/) {
2938 $timeout = 60; # note: cdrom mount command is slow
2940 if ($res = __read_avail
($sock, $timeout)) {
2942 my @lines = split("\r?\n", $res);
2944 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2946 $res = join("\n", @lines);
2954 syslog
("err", "VM $vmid monitor command failed - $err");
2961 sub qemu_block_resize
{
2962 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2964 my $running = check_running
($vmid);
2966 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2968 return if !$running;
2970 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2974 sub qemu_volume_snapshot
{
2975 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2977 my $running = check_running
($vmid);
2979 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2981 return if !$running;
2983 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2987 sub qemu_volume_snapshot_delete
{
2988 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2990 my $running = check_running
($vmid);
2992 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2994 return if !$running;
2996 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3002 #need to impplement call to qemu-ga
3005 sub qga_unfreezefs
{
3008 #need to impplement call to qemu-ga
3012 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine) = @_;
3014 lock_config
($vmid, sub {
3015 my $conf = load_config
($vmid, $migratedfrom);
3017 die "you can't start a vm if it's a template\n" if is_template
($conf);
3019 check_lock
($conf) if !$skiplock;
3021 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3023 my $defaults = load_defaults
();
3025 # set environment variable useful inside network script
3026 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3028 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3030 my $migrate_port = 0;
3033 if ($statefile eq 'tcp') {
3034 $migrate_port = PVE
::Tools
::next_migrate_port
();
3035 my $migrate_uri = "tcp:localhost:${migrate_port}";
3036 push @$cmd, '-incoming', $migrate_uri;
3039 push @$cmd, '-loadstate', $statefile;
3046 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3047 my $d = parse_hostpci
($conf->{"hostpci$i"});
3049 my $info = pci_device_info
("0000:$d->{pciid}");
3050 die "IOMMU not present\n" if !check_iommu_support
();
3051 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3052 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3053 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3056 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3058 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3061 die "start failed: $err" if $err;
3063 print "migration listens on port $migrate_port\n" if $migrate_port;
3065 if ($statefile && $statefile ne 'tcp') {
3066 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3071 my $capabilities = {};
3072 $capabilities->{capability
} = "xbzrle";
3073 $capabilities->{state} = JSON
::true
;
3074 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
3078 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3079 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3080 if $conf->{balloon
};
3081 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3082 path
=> "machine/peripheral/balloon0",
3083 property
=> "guest-stats-polling-interval",
3091 my ($vmid, $execute, %params) = @_;
3093 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3094 vm_qmp_command
($vmid, $cmd);
3097 sub vm_mon_cmd_nocheck
{
3098 my ($vmid, $execute, %params) = @_;
3100 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3101 vm_qmp_command
($vmid, $cmd, 1);
3104 sub vm_qmp_command
{
3105 my ($vmid, $cmd, $nocheck) = @_;
3110 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3111 $timeout = $cmd->{arguments
}->{timeout
};
3112 delete $cmd->{arguments
}->{timeout
};
3116 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3117 my $sname = qmp_socket
($vmid);
3119 my $qmpclient = PVE
::QMPClient-
>new();
3121 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3122 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3123 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3124 if scalar(%{$cmd->{arguments
}});
3125 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3127 die "unable to open monitor socket\n";
3131 syslog
("err", "VM $vmid qmp command failed - $err");
3138 sub vm_human_monitor_command
{
3139 my ($vmid, $cmdline) = @_;
3144 execute
=> 'human-monitor-command',
3145 arguments
=> { 'command-line' => $cmdline},
3148 return vm_qmp_command
($vmid, $cmd);
3151 sub vm_commandline
{
3152 my ($storecfg, $vmid) = @_;
3154 my $conf = load_config
($vmid);
3156 my $defaults = load_defaults
();
3158 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3160 return join(' ', @$cmd);
3164 my ($vmid, $skiplock) = @_;
3166 lock_config
($vmid, sub {
3168 my $conf = load_config
($vmid);
3170 check_lock
($conf) if !$skiplock;
3172 vm_mon_cmd
($vmid, "system_reset");
3176 sub get_vm_volumes
{
3180 foreach_volid
($conf, sub {
3181 my ($volid, $is_cdrom) = @_;
3183 return if $volid =~ m
|^/|;
3185 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3188 push @$vollist, $volid;
3194 sub vm_stop_cleanup
{
3195 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3198 fairsched_rmnod
($vmid); # try to destroy group
3201 my $vollist = get_vm_volumes
($conf);
3202 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3205 foreach my $ext (qw(mon qmp pid vnc qga)) {
3206 unlink "/var/run/qemu-server/${vmid}.$ext";
3209 warn $@ if $@; # avoid errors - just warn
3212 # Note: use $nockeck to skip tests if VM configuration file exists.
3213 # We need that when migration VMs to other nodes (files already moved)
3214 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3216 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3218 $force = 1 if !defined($force) && !$shutdown;
3221 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3222 kill 15, $pid if $pid;
3223 my $conf = load_config
($vmid, $migratedfrom);
3224 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3228 lock_config
($vmid, sub {
3230 my $pid = check_running
($vmid, $nocheck);
3235 $conf = load_config
($vmid);
3236 check_lock
($conf) if !$skiplock;
3237 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3238 my $opts = parse_startup
($conf->{startup
});
3239 $timeout = $opts->{down
} if $opts->{down
};
3243 $timeout = 60 if !defined($timeout);
3247 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3250 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3257 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3262 if ($count >= $timeout) {
3264 warn "VM still running - terminating now with SIGTERM\n";
3267 die "VM quit/powerdown failed - got timeout\n";
3270 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3275 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3278 die "VM quit/powerdown failed\n";
3286 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3291 if ($count >= $timeout) {
3292 warn "VM still running - terminating now with SIGKILL\n";
3297 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3302 my ($vmid, $skiplock) = @_;
3304 lock_config
($vmid, sub {
3306 my $conf = load_config
($vmid);
3308 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3310 vm_mon_cmd
($vmid, "stop");
3315 my ($vmid, $skiplock) = @_;
3317 lock_config
($vmid, sub {
3319 my $conf = load_config
($vmid);
3321 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3323 vm_mon_cmd
($vmid, "cont");
3328 my ($vmid, $skiplock, $key) = @_;
3330 lock_config
($vmid, sub {
3332 my $conf = load_config
($vmid);
3334 # there is no qmp command, so we use the human monitor command
3335 vm_human_monitor_command
($vmid, "sendkey $key");
3340 my ($storecfg, $vmid, $skiplock) = @_;
3342 lock_config
($vmid, sub {
3344 my $conf = load_config
($vmid);
3346 check_lock
($conf) if !$skiplock;
3348 if (!check_running
($vmid)) {
3349 fairsched_rmnod
($vmid); # try to destroy group
3350 destroy_vm
($storecfg, $vmid);
3352 die "VM $vmid is running - destroy failed\n";
3360 my ($filename, $buf) = @_;
3362 my $fh = IO
::File-
>new($filename, "w");
3363 return undef if !$fh;
3365 my $res = print $fh $buf;
3372 sub pci_device_info
{
3377 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3378 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3380 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3381 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3383 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3384 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3386 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3387 return undef if !defined($product) || $product !~ s/^0x//;
3392 product
=> $product,
3398 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3407 my $name = $dev->{name
};
3409 my $fn = "$pcisysfs/devices/$name/reset";
3411 return file_write
($fn, "1");
3414 sub pci_dev_bind_to_stub
{
3417 my $name = $dev->{name
};
3419 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3420 return 1 if -d
$testdir;
3422 my $data = "$dev->{vendor} $dev->{product}";
3423 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3425 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3426 if (!file_write
($fn, $name)) {
3427 return undef if -f
$fn;
3430 $fn = "$pcisysfs/drivers/pci-stub/bind";
3431 if (! -d
$testdir) {
3432 return undef if !file_write
($fn, $name);
3438 sub print_pci_addr
{
3439 my ($id, $bridges) = @_;
3443 piix3
=> { bus
=> 0, addr
=> 1 },
3444 #addr2 : first videocard
3445 balloon0
=> { bus
=> 0, addr
=> 3 },
3446 watchdog
=> { bus
=> 0, addr
=> 4 },
3447 scsihw0
=> { bus
=> 0, addr
=> 5 },
3448 scsihw1
=> { bus
=> 0, addr
=> 6 },
3449 ahci0
=> { bus
=> 0, addr
=> 7 },
3450 qga0
=> { bus
=> 0, addr
=> 8 },
3451 spice
=> { bus
=> 0, addr
=> 9 },
3452 virtio0
=> { bus
=> 0, addr
=> 10 },
3453 virtio1
=> { bus
=> 0, addr
=> 11 },
3454 virtio2
=> { bus
=> 0, addr
=> 12 },
3455 virtio3
=> { bus
=> 0, addr
=> 13 },
3456 virtio4
=> { bus
=> 0, addr
=> 14 },
3457 virtio5
=> { bus
=> 0, addr
=> 15 },
3458 hostpci0
=> { bus
=> 0, addr
=> 16 },
3459 hostpci1
=> { bus
=> 0, addr
=> 17 },
3460 net0
=> { bus
=> 0, addr
=> 18 },
3461 net1
=> { bus
=> 0, addr
=> 19 },
3462 net2
=> { bus
=> 0, addr
=> 20 },
3463 net3
=> { bus
=> 0, addr
=> 21 },
3464 net4
=> { bus
=> 0, addr
=> 22 },
3465 net5
=> { bus
=> 0, addr
=> 23 },
3466 #addr29 : usb-host (pve-usb.cfg)
3467 'pci.1' => { bus
=> 0, addr
=> 30 },
3468 'pci.2' => { bus
=> 0, addr
=> 31 },
3469 'net6' => { bus
=> 1, addr
=> 1 },
3470 'net7' => { bus
=> 1, addr
=> 2 },
3471 'net8' => { bus
=> 1, addr
=> 3 },
3472 'net9' => { bus
=> 1, addr
=> 4 },
3473 'net10' => { bus
=> 1, addr
=> 5 },
3474 'net11' => { bus
=> 1, addr
=> 6 },
3475 'net12' => { bus
=> 1, addr
=> 7 },
3476 'net13' => { bus
=> 1, addr
=> 8 },
3477 'net14' => { bus
=> 1, addr
=> 9 },
3478 'net15' => { bus
=> 1, addr
=> 10 },
3479 'net16' => { bus
=> 1, addr
=> 11 },
3480 'net17' => { bus
=> 1, addr
=> 12 },
3481 'net18' => { bus
=> 1, addr
=> 13 },
3482 'net19' => { bus
=> 1, addr
=> 14 },
3483 'net20' => { bus
=> 1, addr
=> 15 },
3484 'net21' => { bus
=> 1, addr
=> 16 },
3485 'net22' => { bus
=> 1, addr
=> 17 },
3486 'net23' => { bus
=> 1, addr
=> 18 },
3487 'net24' => { bus
=> 1, addr
=> 19 },
3488 'net25' => { bus
=> 1, addr
=> 20 },
3489 'net26' => { bus
=> 1, addr
=> 21 },
3490 'net27' => { bus
=> 1, addr
=> 22 },
3491 'net28' => { bus
=> 1, addr
=> 23 },
3492 'net29' => { bus
=> 1, addr
=> 24 },
3493 'net30' => { bus
=> 1, addr
=> 25 },
3494 'net31' => { bus
=> 1, addr
=> 26 },
3495 'virtio6' => { bus
=> 2, addr
=> 1 },
3496 'virtio7' => { bus
=> 2, addr
=> 2 },
3497 'virtio8' => { bus
=> 2, addr
=> 3 },
3498 'virtio9' => { bus
=> 2, addr
=> 4 },
3499 'virtio10' => { bus
=> 2, addr
=> 5 },
3500 'virtio11' => { bus
=> 2, addr
=> 6 },
3501 'virtio12' => { bus
=> 2, addr
=> 7 },
3502 'virtio13' => { bus
=> 2, addr
=> 8 },
3503 'virtio14' => { bus
=> 2, addr
=> 9 },
3504 'virtio15' => { bus
=> 2, addr
=> 10 },
3507 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3508 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3509 my $bus = $devices->{$id}->{bus
};
3510 $res = ",bus=pci.$bus,addr=$addr";
3511 $bridges->{$bus} = 1 if $bridges;
3517 # vzdump restore implementaion
3519 sub tar_archive_read_firstfile
{
3520 my $archive = shift;
3522 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3524 # try to detect archive type first
3525 my $pid = open (TMP
, "tar tf '$archive'|") ||
3526 die "unable to open file '$archive'\n";
3527 my $firstfile = <TMP
>;
3531 die "ERROR: archive contaions no data\n" if !$firstfile;
3537 sub tar_restore_cleanup
{
3538 my ($storecfg, $statfile) = @_;
3540 print STDERR
"starting cleanup\n";
3542 if (my $fd = IO
::File-
>new($statfile, "r")) {
3543 while (defined(my $line = <$fd>)) {
3544 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3547 if ($volid =~ m
|^/|) {
3548 unlink $volid || die 'unlink failed\n';
3550 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3552 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3554 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3556 print STDERR
"unable to parse line in statfile - $line";
3563 sub restore_archive
{
3564 my ($archive, $vmid, $user, $opts) = @_;
3566 my $format = $opts->{format
};
3569 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3570 $format = 'tar' if !$format;
3572 } elsif ($archive =~ m/\.tar$/) {
3573 $format = 'tar' if !$format;
3574 } elsif ($archive =~ m/.tar.lzo$/) {
3575 $format = 'tar' if !$format;
3577 } elsif ($archive =~ m/\.vma$/) {
3578 $format = 'vma' if !$format;
3579 } elsif ($archive =~ m/\.vma\.gz$/) {
3580 $format = 'vma' if !$format;
3582 } elsif ($archive =~ m/\.vma\.lzo$/) {
3583 $format = 'vma' if !$format;
3586 $format = 'vma' if !$format; # default
3589 # try to detect archive format
3590 if ($format eq 'tar') {
3591 return restore_tar_archive
($archive, $vmid, $user, $opts);
3593 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3597 sub restore_update_config_line
{
3598 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3600 return if $line =~ m/^\#qmdump\#/;
3601 return if $line =~ m/^\#vzdump\#/;
3602 return if $line =~ m/^lock:/;
3603 return if $line =~ m/^unused\d+:/;
3604 return if $line =~ m/^parent:/;
3605 return if $line =~ m/^template:/; # restored VM is never a template
3607 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3608 # try to convert old 1.X settings
3609 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3610 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3611 my ($model, $macaddr) = split(/\=/, $devconfig);
3612 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3615 bridge
=> "vmbr$ind",
3616 macaddr
=> $macaddr,
3618 my $netstr = print_net
($net);
3620 print $outfd "net$cookie->{netcount}: $netstr\n";
3621 $cookie->{netcount
}++;
3623 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3624 my ($id, $netstr) = ($1, $2);
3625 my $net = parse_net
($netstr);
3626 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3627 $netstr = print_net
($net);
3628 print $outfd "$id: $netstr\n";
3629 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3632 if ($line =~ m/backup=no/) {
3633 print $outfd "#$line";
3634 } elsif ($virtdev && $map->{$virtdev}) {
3635 my $di = parse_drive
($virtdev, $value);
3636 delete $di->{format
}; # format can change on restore
3637 $di->{file
} = $map->{$virtdev};
3638 $value = print_drive
($vmid, $di);
3639 print $outfd "$virtdev: $value\n";
3649 my ($cfg, $vmid) = @_;
3651 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3653 my $volid_hash = {};
3654 foreach my $storeid (keys %$info) {
3655 foreach my $item (@{$info->{$storeid}}) {
3656 next if !($item->{volid
} && $item->{size
});
3657 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3658 $volid_hash->{$item->{volid
}} = $item;
3665 sub get_used_paths
{
3666 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3670 my $scan_config = sub {
3671 my ($cref, $snapname) = @_;
3673 foreach my $key (keys %$cref) {
3674 my $value = $cref->{$key};
3675 if (valid_drivename
($key)) {
3676 next if $skip_drive && $key eq $skip_drive;
3677 my $drive = parse_drive
($key, $value);
3678 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3679 if ($drive->{file
} =~ m!^/!) {
3680 $used_path->{$drive->{file
}}++; # = 1;
3682 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3684 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3686 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3687 $used_path->{$path}++; # = 1;
3693 &$scan_config($conf);
3697 if ($scan_snapshots) {
3698 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3699 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3706 sub update_disksize
{
3707 my ($vmid, $conf, $volid_hash) = @_;
3713 # Note: it is allowed to define multiple storages with same path (alias), so
3714 # we need to check both 'volid' and real 'path' (two different volid can point
3715 # to the same path).
3720 foreach my $opt (keys %$conf) {
3721 if (valid_drivename
($opt)) {
3722 my $drive = parse_drive
($opt, $conf->{$opt});
3723 my $volid = $drive->{file
};
3726 $used->{$volid} = 1;
3727 if ($volid_hash->{$volid} &&
3728 (my $path = $volid_hash->{$volid}->{path
})) {
3729 $usedpath->{$path} = 1;
3732 next if drive_is_cdrom
($drive);
3733 next if !$volid_hash->{$volid};
3735 $drive->{size
} = $volid_hash->{$volid}->{size
};
3736 my $new = print_drive
($vmid, $drive);
3737 if ($new ne $conf->{$opt}) {
3739 $conf->{$opt} = $new;
3744 # remove 'unusedX' entry if volume is used
3745 foreach my $opt (keys %$conf) {
3746 next if $opt !~ m/^unused\d+$/;
3747 my $volid = $conf->{$opt};
3748 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3749 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3751 delete $conf->{$opt};
3755 foreach my $volid (sort keys %$volid_hash) {
3756 next if $volid =~ m/vm-$vmid-state-/;
3757 next if $used->{$volid};
3758 my $path = $volid_hash->{$volid}->{path
};
3759 next if !$path; # just to be sure
3760 next if $usedpath->{$path};
3762 add_unused_volume
($conf, $volid);
3763 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3770 my ($vmid, $nolock) = @_;
3772 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3774 my $volid_hash = scan_volids
($cfg, $vmid);
3776 my $updatefn = sub {
3779 my $conf = load_config
($vmid);
3784 foreach my $volid (keys %$volid_hash) {
3785 my $info = $volid_hash->{$volid};
3786 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3789 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3791 update_config_nolock
($vmid, $conf, 1) if $changes;
3794 if (defined($vmid)) {
3798 lock_config
($vmid, $updatefn, $vmid);
3801 my $vmlist = config_list
();
3802 foreach my $vmid (keys %$vmlist) {
3806 lock_config
($vmid, $updatefn, $vmid);
3812 sub restore_vma_archive
{
3813 my ($archive, $vmid, $user, $opts, $comp) = @_;
3815 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3816 my $readfrom = $archive;
3821 my $qarchive = PVE
::Tools
::shellquote
($archive);
3822 if ($comp eq 'gzip') {
3823 $uncomp = "zcat $qarchive|";
3824 } elsif ($comp eq 'lzop') {
3825 $uncomp = "lzop -d -c $qarchive|";
3827 die "unknown compression method '$comp'\n";
3832 my $tmpdir = "/var/tmp/vzdumptmp$$";
3835 # disable interrupts (always do cleanups)
3836 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3837 warn "got interrupt - ignored\n";
3840 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3841 POSIX
::mkfifo
($mapfifo, 0600);
3844 my $openfifo = sub {
3845 open($fifofh, '>', $mapfifo) || die $!;
3848 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3855 my $rpcenv = PVE
::RPCEnvironment
::get
();
3857 my $conffile = config_file
($vmid);
3858 my $tmpfn = "$conffile.$$.tmp";
3860 # Note: $oldconf is undef if VM does not exists
3861 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3863 my $print_devmap = sub {
3864 my $virtdev_hash = {};
3866 my $cfgfn = "$tmpdir/qemu-server.conf";
3868 # we can read the config - that is already extracted
3869 my $fh = IO
::File-
>new($cfgfn, "r") ||
3870 "unable to read qemu-server.conf - $!\n";
3872 while (defined(my $line = <$fh>)) {
3873 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3874 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3875 die "archive does not contain data for drive '$virtdev'\n"
3876 if !$devinfo->{$devname};
3877 if (defined($opts->{storage
})) {
3878 $storeid = $opts->{storage
} || 'local';
3879 } elsif (!$storeid) {
3882 $format = 'raw' if !$format;
3883 $devinfo->{$devname}->{devname
} = $devname;
3884 $devinfo->{$devname}->{virtdev
} = $virtdev;
3885 $devinfo->{$devname}->{format
} = $format;
3886 $devinfo->{$devname}->{storeid
} = $storeid;
3888 # check permission on storage
3889 my $pool = $opts->{pool
}; # todo: do we need that?
3890 if ($user ne 'root@pam') {
3891 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3894 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3898 foreach my $devname (keys %$devinfo) {
3899 die "found no device mapping information for device '$devname'\n"
3900 if !$devinfo->{$devname}->{virtdev
};
3903 my $cfg = cfs_read_file
('storage.cfg');
3905 # create empty/temp config
3907 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3908 foreach_drive
($oldconf, sub {
3909 my ($ds, $drive) = @_;
3911 return if drive_is_cdrom
($drive);
3913 my $volid = $drive->{file
};
3915 return if !$volid || $volid =~ m
|^/|;
3917 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3918 return if !$path || !$owner || ($owner != $vmid);
3920 # Note: only delete disk we want to restore
3921 # other volumes will become unused
3922 if ($virtdev_hash->{$ds}) {
3923 PVE
::Storage
::vdisk_free
($cfg, $volid);
3929 foreach my $virtdev (sort keys %$virtdev_hash) {
3930 my $d = $virtdev_hash->{$virtdev};
3931 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3932 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3934 # test if requested format is supported
3935 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
3936 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
3937 $d->{format
} = $defFormat if !$supported;
3939 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3940 $d->{format
}, undef, $alloc_size);
3941 print STDERR
"new volume ID is '$volid'\n";
3942 $d->{volid
} = $volid;
3943 my $path = PVE
::Storage
::path
($cfg, $volid);
3945 my $write_zeros = 1;
3946 # fixme: what other storages types initialize volumes with zero?
3947 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' ||
3948 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
3952 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3954 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3955 $map->{$virtdev} = $volid;
3958 $fh->seek(0, 0) || die "seek failed - $!\n";
3960 my $outfd = new IO
::File
($tmpfn, "w") ||
3961 die "unable to write config for VM $vmid\n";
3963 my $cookie = { netcount
=> 0 };
3964 while (defined(my $line = <$fh>)) {
3965 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3974 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3975 die "interrupted by signal\n";
3977 local $SIG{ALRM
} = sub { die "got timeout\n"; };
3979 $oldtimeout = alarm($timeout);
3986 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
3987 my ($dev_id, $size, $devname) = ($1, $2, $3);
3988 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
3989 } elsif ($line =~ m/^CTIME: /) {
3991 print $fifofh "done\n";
3992 my $tmp = $oldtimeout || 0;
3993 $oldtimeout = undef;
3999 print "restore vma archive: $cmd\n";
4000 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4004 alarm($oldtimeout) if $oldtimeout;
4012 my $cfg = cfs_read_file
('storage.cfg');
4013 foreach my $devname (keys %$devinfo) {
4014 my $volid = $devinfo->{$devname}->{volid
};
4017 if ($volid =~ m
|^/|) {
4018 unlink $volid || die 'unlink failed\n';
4020 PVE
::Storage
::vdisk_free
($cfg, $volid);
4022 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4024 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4031 rename($tmpfn, $conffile) ||
4032 die "unable to commit configuration file '$conffile'\n";
4034 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4036 eval { rescan
($vmid, 1); };
4040 sub restore_tar_archive
{
4041 my ($archive, $vmid, $user, $opts) = @_;
4043 if ($archive ne '-') {
4044 my $firstfile = tar_archive_read_firstfile
($archive);
4045 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4046 if $firstfile ne 'qemu-server.conf';
4049 my $storecfg = cfs_read_file
('storage.cfg');
4051 # destroy existing data - keep empty config
4052 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4053 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4055 my $tocmd = "/usr/lib/qemu-server/qmextract";
4057 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4058 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4059 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4060 $tocmd .= ' --info' if $opts->{info
};
4062 # tar option "xf" does not autodetect compression when read from STDIN,
4063 # so we pipe to zcat
4064 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4065 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4067 my $tmpdir = "/var/tmp/vzdumptmp$$";
4070 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4071 local $ENV{VZDUMP_VMID
} = $vmid;
4072 local $ENV{VZDUMP_USER
} = $user;
4074 my $conffile = config_file
($vmid);
4075 my $tmpfn = "$conffile.$$.tmp";
4077 # disable interrupts (always do cleanups)
4078 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4079 print STDERR
"got interrupt - ignored\n";
4084 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4085 die "interrupted by signal\n";
4088 if ($archive eq '-') {
4089 print "extracting archive from STDIN\n";
4090 run_command
($cmd, input
=> "<&STDIN");
4092 print "extracting archive '$archive'\n";
4096 return if $opts->{info
};
4100 my $statfile = "$tmpdir/qmrestore.stat";
4101 if (my $fd = IO
::File-
>new($statfile, "r")) {
4102 while (defined (my $line = <$fd>)) {
4103 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4104 $map->{$1} = $2 if $1;
4106 print STDERR
"unable to parse line in statfile - $line\n";
4112 my $confsrc = "$tmpdir/qemu-server.conf";
4114 my $srcfd = new IO
::File
($confsrc, "r") ||
4115 die "unable to open file '$confsrc'\n";
4117 my $outfd = new IO
::File
($tmpfn, "w") ||
4118 die "unable to write config for VM $vmid\n";
4120 my $cookie = { netcount
=> 0 };
4121 while (defined (my $line = <$srcfd>)) {
4122 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4134 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4141 rename $tmpfn, $conffile ||
4142 die "unable to commit configuration file '$conffile'\n";
4144 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4146 eval { rescan
($vmid, 1); };
4151 # Internal snapshots
4153 # NOTE: Snapshot create/delete involves several non-atomic
4154 # action, and can take a long time.
4155 # So we try to avoid locking the file and use 'lock' variable
4156 # inside the config file instead.
4158 my $snapshot_copy_config = sub {
4159 my ($source, $dest) = @_;
4161 foreach my $k (keys %$source) {
4162 next if $k eq 'snapshots';
4163 next if $k eq 'snapstate';
4164 next if $k eq 'snaptime';
4165 next if $k eq 'vmstate';
4166 next if $k eq 'lock';
4167 next if $k eq 'digest';
4168 next if $k eq 'description';
4169 next if $k =~ m/^unused\d+$/;
4171 $dest->{$k} = $source->{$k};
4175 my $snapshot_apply_config = sub {
4176 my ($conf, $snap) = @_;
4178 # copy snapshot list
4180 snapshots
=> $conf->{snapshots
},
4183 # keep description and list of unused disks
4184 foreach my $k (keys %$conf) {
4185 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4186 $newconf->{$k} = $conf->{$k};
4189 &$snapshot_copy_config($snap, $newconf);
4194 sub foreach_writable_storage
{
4195 my ($conf, $func) = @_;
4199 foreach my $ds (keys %$conf) {
4200 next if !valid_drivename
($ds);
4202 my $drive = parse_drive
($ds, $conf->{$ds});
4204 next if drive_is_cdrom
($drive);
4206 my $volid = $drive->{file
};
4208 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4209 $sidhash->{$sid} = $sid if $sid;
4212 foreach my $sid (sort keys %$sidhash) {
4217 my $alloc_vmstate_volid = sub {
4218 my ($storecfg, $vmid, $conf, $snapname) = @_;
4220 # Note: we try to be smart when selecting a $target storage
4224 # search shared storage first
4225 foreach_writable_storage
($conf, sub {
4227 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4228 return if !$scfg->{shared
};
4230 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4234 # now search local storage
4235 foreach_writable_storage
($conf, sub {
4237 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4238 return if $scfg->{shared
};
4240 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4244 $target = 'local' if !$target;
4246 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4247 # we abort live save after $conf->{memory}, so we need at max twice that space
4248 my $size = $conf->{memory
}*2 + $driver_state_size;
4250 my $name = "vm-$vmid-state-$snapname";
4251 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4252 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4253 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4258 my $snapshot_prepare = sub {
4259 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4263 my $updatefn = sub {
4265 my $conf = load_config
($vmid);
4267 die "you can't take a snapshot if it's a template\n"
4268 if is_template
($conf);
4272 $conf->{lock} = 'snapshot';
4274 die "snapshot name '$snapname' already used\n"
4275 if defined($conf->{snapshots
}->{$snapname});
4277 my $storecfg = PVE
::Storage
::config
();
4278 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4280 $snap = $conf->{snapshots
}->{$snapname} = {};
4282 if ($save_vmstate && check_running
($vmid)) {
4283 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4286 &$snapshot_copy_config($conf, $snap);
4288 $snap->{snapstate
} = "prepare";
4289 $snap->{snaptime
} = time();
4290 $snap->{description
} = $comment if $comment;
4292 # always overwrite machine if we save vmstate. This makes sure we
4293 # can restore it later using correct machine type
4294 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4296 update_config_nolock
($vmid, $conf, 1);
4299 lock_config
($vmid, $updatefn);
4304 my $snapshot_commit = sub {
4305 my ($vmid, $snapname) = @_;
4307 my $updatefn = sub {
4309 my $conf = load_config
($vmid);
4311 die "missing snapshot lock\n"
4312 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4314 my $snap = $conf->{snapshots
}->{$snapname};
4316 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4318 die "wrong snapshot state\n"
4319 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4321 delete $snap->{snapstate
};
4322 delete $conf->{lock};
4324 my $newconf = &$snapshot_apply_config($conf, $snap);
4326 $newconf->{parent
} = $snapname;
4328 update_config_nolock
($vmid, $newconf, 1);
4331 lock_config
($vmid, $updatefn);
4334 sub snapshot_rollback
{
4335 my ($vmid, $snapname) = @_;
4341 my $storecfg = PVE
::Storage
::config
();
4343 my $updatefn = sub {
4345 my $conf = load_config
($vmid);
4347 die "you can't rollback if vm is a template\n" if is_template
($conf);
4349 $snap = $conf->{snapshots
}->{$snapname};
4351 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4353 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4354 if $snap->{snapstate
};
4358 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4361 die "unable to rollback vm $vmid: vm is running\n"
4362 if check_running
($vmid);
4365 $conf->{lock} = 'rollback';
4367 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4368 delete $conf->{lock};
4374 my $has_machine_config = defined($conf->{machine
});
4376 # copy snapshot config to current config
4377 $conf = &$snapshot_apply_config($conf, $snap);
4378 $conf->{parent
} = $snapname;
4380 # Note: old code did not store 'machine', so we try to be smart
4381 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4382 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4383 # we remove the 'machine' configuration if not explicitly specified
4384 # in the original config.
4385 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4388 update_config_nolock
($vmid, $conf, 1);
4390 if (!$prepare && $snap->{vmstate
}) {
4391 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4392 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4396 lock_config
($vmid, $updatefn);
4398 foreach_drive
($snap, sub {
4399 my ($ds, $drive) = @_;
4401 return if drive_is_cdrom
($drive);
4403 my $volid = $drive->{file
};
4404 my $device = "drive-$ds";
4406 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4410 lock_config
($vmid, $updatefn);
4413 my $savevm_wait = sub {
4417 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4418 if (!$stat->{status
}) {
4419 die "savevm not active\n";
4420 } elsif ($stat->{status
} eq 'active') {
4423 } elsif ($stat->{status
} eq 'completed') {
4426 die "query-savevm returned status '$stat->{status}'\n";
4431 sub snapshot_create
{
4432 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4434 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4436 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4440 my $running = check_running
($vmid);
4443 # create internal snapshots of all drives
4445 my $storecfg = PVE
::Storage
::config
();
4448 if ($snap->{vmstate
}) {
4449 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4450 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4451 &$savevm_wait($vmid);
4453 vm_mon_cmd
($vmid, "savevm-start");
4457 qga_freezefs
($vmid) if $running && $freezefs;
4459 foreach_drive
($snap, sub {
4460 my ($ds, $drive) = @_;
4462 return if drive_is_cdrom
($drive);
4464 my $volid = $drive->{file
};
4465 my $device = "drive-$ds";
4467 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4468 $drivehash->{$ds} = 1;
4473 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4476 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4480 warn "snapshot create failed: starting cleanup\n";
4481 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4486 &$snapshot_commit($vmid, $snapname);
4489 # Note: $drivehash is only set when called from snapshot_create.
4490 sub snapshot_delete
{
4491 my ($vmid, $snapname, $force, $drivehash) = @_;
4498 my $unlink_parent = sub {
4499 my ($confref, $new_parent) = @_;
4501 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4503 $confref->{parent
} = $new_parent;
4505 delete $confref->{parent
};
4510 my $updatefn = sub {
4511 my ($remove_drive) = @_;
4513 my $conf = load_config
($vmid);
4517 die "you can't delete a snapshot if vm is a template\n"
4518 if is_template
($conf);
4521 $snap = $conf->{snapshots
}->{$snapname};
4523 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4525 # remove parent refs
4526 &$unlink_parent($conf, $snap->{parent
});
4527 foreach my $sn (keys %{$conf->{snapshots
}}) {
4528 next if $sn eq $snapname;
4529 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4532 if ($remove_drive) {
4533 if ($remove_drive eq 'vmstate') {
4534 delete $snap->{$remove_drive};
4536 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4537 my $volid = $drive->{file
};
4538 delete $snap->{$remove_drive};
4539 add_unused_volume
($conf, $volid);
4544 $snap->{snapstate
} = 'delete';
4546 delete $conf->{snapshots
}->{$snapname};
4547 delete $conf->{lock} if $drivehash;
4548 foreach my $volid (@$unused) {
4549 add_unused_volume
($conf, $volid);
4553 update_config_nolock
($vmid, $conf, 1);
4556 lock_config
($vmid, $updatefn);
4558 # now remove vmstate file
4560 my $storecfg = PVE
::Storage
::config
();
4562 if ($snap->{vmstate
}) {
4563 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4565 die $err if !$force;
4568 # save changes (remove vmstate from snapshot)
4569 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4572 # now remove all internal snapshots
4573 foreach_drive
($snap, sub {
4574 my ($ds, $drive) = @_;
4576 return if drive_is_cdrom
($drive);
4578 my $volid = $drive->{file
};
4579 my $device = "drive-$ds";
4581 if (!$drivehash || $drivehash->{$ds}) {
4582 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4584 die $err if !$force;
4589 # save changes (remove drive fron snapshot)
4590 lock_config
($vmid, $updatefn, $ds) if !$force;
4591 push @$unused, $volid;
4594 # now cleanup config
4596 lock_config
($vmid, $updatefn);
4600 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4603 foreach_drive
($conf, sub {
4604 my ($ds, $drive) = @_;
4606 return if drive_is_cdrom
($drive);
4607 my $volid = $drive->{file
};
4608 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4611 return $err ?
0 : 1;
4614 sub template_create
{
4615 my ($vmid, $conf, $disk) = @_;
4617 my $storecfg = PVE
::Storage
::config
();
4619 foreach_drive
($conf, sub {
4620 my ($ds, $drive) = @_;
4622 return if drive_is_cdrom
($drive);
4623 return if $disk && $ds ne $disk;
4625 my $volid = $drive->{file
};
4626 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4628 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4629 $drive->{file
} = $voliddst;
4630 $conf->{$ds} = print_drive
($vmid, $drive);
4631 update_config_nolock
($vmid, $conf, 1);
4638 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4641 sub qemu_img_convert
{
4642 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4644 my $storecfg = PVE
::Storage
::config
();
4645 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4646 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4648 if ($src_storeid && $dst_storeid) {
4649 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4650 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4652 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4653 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4655 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4656 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4659 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C';
4660 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4661 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4665 if($line =~ m/\((\S+)\/100\
%\)/){
4667 my $transferred = int($size * $percent / 100);
4668 my $remaining = $size - $transferred;
4670 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4675 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4677 die "copy failed: $err" if $err;
4681 sub qemu_img_format
{
4682 my ($scfg, $volname) = @_;
4684 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4686 } elsif ($scfg->{type
} eq 'iscsi') {
4687 return "host_device";
4693 sub qemu_drive_mirror
{
4694 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4700 my $storecfg = PVE
::Storage
::config
();
4701 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4704 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4707 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4711 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4714 #fixme : sometime drive-mirror timeout, but works fine after.
4715 # (I have see the problem with big volume > 200GB), so we need to eval
4716 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4717 sync
=> "full", target
=> $dst_path, format
=> $format); };
4719 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4720 sync
=> "full", target
=> $dst_path); };
4725 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4726 my $stat = @$stats[0];
4727 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4728 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4730 my $transferred = $stat->{offset
};
4731 my $total = $stat->{len
};
4732 my $remaining = $total - $transferred;
4733 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4735 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4737 last if ($stat->{len
} == $stat->{offset
});
4738 if ($old_len == $stat->{offset
}) {
4739 if ($maxwait && $count > $maxwait) {
4740 # if writes to disk occurs the disk needs to be freezed
4741 # to be able to complete the migration
4742 vm_suspend
($vmid,1);
4746 $count++ unless $frozen;
4752 $old_len = $stat->{offset
};
4756 if ($vmiddst == $vmid) {
4757 # switch the disk if source and destination are on the same guest
4758 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4762 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4763 die "mirroring error: $err";
4766 if ($vmiddst != $vmid) {
4767 # if we clone a disk for a new target vm, we don't switch the disk
4768 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4774 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4775 $newvmid, $storage, $format, $full, $newvollist) = @_;
4780 print "create linked clone of drive $drivename ($drive->{file})\n";
4781 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4782 push @$newvollist, $newvolid;
4784 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4785 $storeid = $storage if $storage;
4787 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4789 $format = $drive->{format
} || $defFormat;
4792 # test if requested format is supported - else use default
4793 my $supported = grep { $_ eq $format } @$validFormats;
4794 $format = $defFormat if !$supported;
4796 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4798 print "create full clone of drive $drivename ($drive->{file})\n";
4799 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4800 push @$newvollist, $newvolid;
4802 if (!$running || $snapname) {
4803 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4805 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4809 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4812 $disk->{format
} = undef;
4813 $disk->{file
} = $newvolid;
4814 $disk->{size
} = $size;
4819 # this only works if VM is running
4820 sub get_current_qemu_machine
{
4823 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4824 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4826 my ($current, $default);
4827 foreach my $e (@$res) {
4828 $default = $e->{name
} if $e->{'is-default'};
4829 $current = $e->{name
} if $e->{'is-current'};
4832 # fallback to the default machine if current is not supported by qemu
4833 return $current || $default || 'pc';