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",
339 enum
=> [qw(std cirrus vmware)],
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.",
426 # what about other qemu settings ?
428 #machine => 'string',
441 ##soundhw => 'string',
443 while (my ($k, $v) = each %$confdesc) {
444 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
447 my $MAX_IDE_DISKS = 4;
448 my $MAX_SCSI_DISKS = 14;
449 my $MAX_VIRTIO_DISKS = 16;
450 my $MAX_SATA_DISKS = 6;
451 my $MAX_USB_DEVICES = 5;
453 my $MAX_UNUSED_DISKS = 8;
454 my $MAX_HOSTPCI_DEVICES = 2;
455 my $MAX_SERIAL_PORTS = 4;
456 my $MAX_PARALLEL_PORTS = 3;
458 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
459 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
460 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
464 type
=> 'string', format
=> 'pve-qm-net',
465 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
466 description
=> <<EODESCR,
467 Specify network devices.
469 MODEL is one of: $nic_model_list_txt
471 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
472 automatically generated if not specified.
474 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
476 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'.
478 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
484 The DHCP server assign addresses to the guest starting from 10.0.2.15.
488 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
490 for (my $i = 0; $i < $MAX_NETS; $i++) {
491 $confdesc->{"net$i"} = $netdesc;
498 type
=> 'string', format
=> 'pve-qm-drive',
499 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]',
500 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
502 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
506 type
=> 'string', format
=> 'pve-qm-drive',
507 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]',
508 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
510 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
516 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
524 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
530 type
=> 'string', format
=> 'pve-qm-usb-device',
531 typetext
=> 'host=HOSTUSBDEVICE',
532 description
=> <<EODESCR,
533 Configure an USB device (n is 0 to 4). This can be used to
534 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
536 'bus-port(.port)*' (decimal numbers) or
537 'vendor_id:product_id' (hexadeciaml numbers)
539 You can use the 'lsusb -t' command to list existing usb devices.
541 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
545 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
549 type
=> 'string', format
=> 'pve-qm-hostpci',
550 typetext
=> "HOSTPCIDEVICE",
551 description
=> <<EODESCR,
552 Map host pci devices. HOSTPCIDEVICE syntax is:
554 'bus:dev.func' (hexadecimal numbers)
556 You can us the 'lspci' command to list existing pci devices.
558 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
560 Experimental: user reported problems with this option.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
568 pattern
=> '/dev/ttyS\d+',
569 description
=> <<EODESCR,
570 Map host serial devices (n is 0 to 3).
572 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
574 Experimental: user reported problems with this option.
581 pattern
=> '/dev/parport\d+',
582 description
=> <<EODESCR,
583 Map host parallel devices (n is 0 to 2).
585 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
587 Experimental: user reported problems with this option.
591 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
592 $confdesc->{"parallel$i"} = $paralleldesc;
595 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
596 $confdesc->{"serial$i"} = $serialdesc;
599 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
600 $confdesc->{"hostpci$i"} = $hostpcidesc;
603 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
604 $drivename_hash->{"ide$i"} = 1;
605 $confdesc->{"ide$i"} = $idedesc;
608 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
609 $drivename_hash->{"sata$i"} = 1;
610 $confdesc->{"sata$i"} = $satadesc;
613 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
614 $drivename_hash->{"scsi$i"} = 1;
615 $confdesc->{"scsi$i"} = $scsidesc ;
618 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
619 $drivename_hash->{"virtio$i"} = 1;
620 $confdesc->{"virtio$i"} = $virtiodesc;
623 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
624 $confdesc->{"usb$i"} = $usbdesc;
629 type
=> 'string', format
=> 'pve-volume-id',
630 description
=> "Reference to unused volumes.",
633 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
634 $confdesc->{"unused$i"} = $unuseddesc;
637 my $kvm_api_version = 0;
641 return $kvm_api_version if $kvm_api_version;
643 my $fh = IO
::File-
>new("</dev/kvm") ||
646 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
647 $kvm_api_version = $v;
652 return $kvm_api_version;
655 my $kvm_user_version;
657 sub kvm_user_version
{
659 return $kvm_user_version if $kvm_user_version;
661 $kvm_user_version = 'unknown';
663 my $tmp = `kvm -help 2>/dev/null`;
665 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
666 $kvm_user_version = $2;
669 return $kvm_user_version;
673 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
676 # order is important - used to autoselect boot disk
677 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
678 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
679 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
680 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
683 sub valid_drivename
{
686 return defined($drivename_hash->{$dev});
691 return defined($confdesc->{$key});
695 return $nic_model_list;
698 sub os_list_description
{
703 w2k
=> 'Windows 2000',
704 w2k3
=>, 'Windows 2003',
705 w2k8
=> 'Windows 2008',
706 wvista
=> 'Windows Vista',
708 win8
=> 'Windows 8/2012',
718 return $cdrom_path if $cdrom_path;
720 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
721 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
722 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
726 my ($storecfg, $vmid, $cdrom) = @_;
728 if ($cdrom eq 'cdrom') {
729 return get_cdrom_path
();
730 } elsif ($cdrom eq 'none') {
732 } elsif ($cdrom =~ m
|^/|) {
735 return PVE
::Storage
::path
($storecfg, $cdrom);
739 # try to convert old style file names to volume IDs
740 sub filename_to_volume_id
{
741 my ($vmid, $file, $media) = @_;
743 if (!($file eq 'none' || $file eq 'cdrom' ||
744 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
746 return undef if $file =~ m
|/|;
748 if ($media && $media eq 'cdrom') {
749 $file = "local:iso/$file";
751 $file = "local:$vmid/$file";
758 sub verify_media_type
{
759 my ($opt, $vtype, $media) = @_;
764 if ($media eq 'disk') {
766 } elsif ($media eq 'cdrom') {
769 die "internal error";
772 return if ($vtype eq $etype);
774 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
777 sub cleanup_drive_path
{
778 my ($opt, $storecfg, $drive) = @_;
780 # try to convert filesystem paths to volume IDs
782 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
783 ($drive->{file
} !~ m
|^/dev/.+|) &&
784 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
785 ($drive->{file
} !~ m/^\d+$/)) {
786 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
787 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
788 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
789 verify_media_type
($opt, $vtype, $drive->{media
});
790 $drive->{file
} = $volid;
793 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
796 sub create_conf_nolock
{
797 my ($vmid, $settings) = @_;
799 my $filename = config_file
($vmid);
801 die "configuration file '$filename' already exists\n" if -f
$filename;
803 my $defaults = load_defaults
();
805 $settings->{name
} = "vm$vmid" if !$settings->{name
};
806 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
809 foreach my $opt (keys %$settings) {
810 next if !$confdesc->{$opt};
812 my $value = $settings->{$opt};
815 $data .= "$opt: $value\n";
818 PVE
::Tools
::file_set_contents
($filename, $data);
821 my $parse_size = sub {
824 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
825 my ($size, $unit) = ($1, $3);
828 $size = $size * 1024;
829 } elsif ($unit eq 'M') {
830 $size = $size * 1024 * 1024;
831 } elsif ($unit eq 'G') {
832 $size = $size * 1024 * 1024 * 1024;
838 my $format_size = sub {
843 my $kb = int($size/1024);
844 return $size if $kb*1024 != $size;
846 my $mb = int($kb/1024);
847 return "${kb}K" if $mb*1024 != $kb;
849 my $gb = int($mb/1024);
850 return "${mb}M" if $gb*1024 != $mb;
855 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
856 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
857 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
858 # [,aio=native|threads]
861 my ($key, $data) = @_;
865 # $key may be undefined - used to verify JSON parameters
866 if (!defined($key)) {
867 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
869 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
870 $res->{interface
} = $1;
876 foreach my $p (split (/,/, $data)) {
877 next if $p =~ m/^\s*$/;
879 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)=(.+)$/) {
880 my ($k, $v) = ($1, $2);
882 $k = 'file' if $k eq 'volume';
884 return undef if defined $res->{$k};
886 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
887 return undef if !$v || $v !~ m/^\d+/;
889 $v = sprintf("%.3f", $v / (1024*1024));
893 if (!$res->{file
} && $p !~ m/=/) {
901 return undef if !$res->{file
};
903 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
907 return undef if $res->{cache
} &&
908 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
909 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
910 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
911 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
912 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
913 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
914 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
915 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
916 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
917 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
918 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
919 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
922 return undef if $res->{mbps_rd
} && $res->{mbps
};
923 return undef if $res->{mbps_wr
} && $res->{mbps
};
925 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
926 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
927 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
929 return undef if $res->{iops_rd
} && $res->{iops
};
930 return undef if $res->{iops_wr
} && $res->{iops
};
931 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
932 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
933 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
937 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
940 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
941 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
942 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
943 return undef if $res->{interface
} eq 'virtio';
946 # rerror does not work with scsi drives
947 if ($res->{rerror
}) {
948 return undef if $res->{interface
} eq 'scsi';
954 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
957 my ($vmid, $drive) = @_;
960 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
961 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
964 if ($drive->{size
}) {
965 $opts .= ",size=" . &$format_size($drive->{size
});
968 return "$drive->{file}$opts";
972 my($fh, $noerr) = @_;
975 my $SG_GET_VERSION_NUM = 0x2282;
977 my $versionbuf = "\x00" x
8;
978 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
980 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
983 my $version = unpack("I", $versionbuf);
984 if ($version < 30000) {
985 die "scsi generic interface too old\n" if !$noerr;
989 my $buf = "\x00" x
36;
990 my $sensebuf = "\x00" x
8;
991 my $cmd = pack("C x3 C x11", 0x12, 36);
993 # see /usr/include/scsi/sg.h
994 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";
996 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
997 length($sensebuf), 0, length($buf), $buf,
998 $cmd, $sensebuf, 6000);
1000 $ret = ioctl($fh, $SG_IO, $packet);
1002 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1006 my @res = unpack($sg_io_hdr_t, $packet);
1007 if ($res[17] || $res[18]) {
1008 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1013 ($res->{device
}, $res->{removable
}, $res->{venodor
},
1014 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1022 my $fh = IO
::File-
>new("+<$path") || return undef;
1023 my $res = scsi_inquiry
($fh, 1);
1029 sub print_drivedevice_full
{
1030 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1035 if ($drive->{interface
} eq 'virtio') {
1036 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1037 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1038 } elsif ($drive->{interface
} eq 'scsi') {
1039 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1040 my $controller = int($drive->{index} / $maxdev);
1041 my $unit = $drive->{index} % $maxdev;
1042 my $devicetype = 'hd';
1044 if (drive_is_cdrom
($drive)) {
1047 if ($drive->{file
} =~ m
|^/|) {
1048 $path = $drive->{file
};
1050 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1053 if($path =~ m/^iscsi\:\/\
//){
1054 $devicetype = 'generic';
1057 $devicetype = 'block' if path_is_scsi
($path);
1061 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1062 $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';
1064 $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}";
1067 } elsif ($drive->{interface
} eq 'ide'){
1069 my $controller = int($drive->{index} / $maxdev);
1070 my $unit = $drive->{index} % $maxdev;
1071 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1073 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1074 } elsif ($drive->{interface
} eq 'sata'){
1075 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1076 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1077 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1078 } elsif ($drive->{interface
} eq 'usb') {
1080 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1082 die "unsupported interface type";
1085 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1090 sub print_drive_full
{
1091 my ($storecfg, $vmid, $drive) = @_;
1094 foreach my $o (@qemu_drive_options) {
1095 next if $o eq 'bootindex';
1096 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1099 foreach my $o (qw(bps bps_rd bps_wr)) {
1100 my $v = $drive->{"m$o"};
1101 $opts .= ",$o=" . int($v*1024*1024) if $v;
1104 # use linux-aio by default (qemu default is threads)
1105 $opts .= ",aio=native" if !$drive->{aio
};
1108 my $volid = $drive->{file
};
1109 if (drive_is_cdrom
($drive)) {
1110 $path = get_iso_path
($storecfg, $vmid, $volid);
1112 if ($volid =~ m
|^/|) {
1115 $path = PVE
::Storage
::path
($storecfg, $volid);
1119 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1121 my $pathinfo = $path ?
"file=$path," : '';
1123 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1126 sub print_netdevice_full
{
1127 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1129 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1131 my $device = $net->{model
};
1132 if ($net->{model
} eq 'virtio') {
1133 $device = 'virtio-net-pci';
1136 # qemu > 0.15 always try to boot from network - we disable that by
1137 # not loading the pxe rom file
1138 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1139 my $pciaddr = print_pci_addr
("$netid", $bridges);
1140 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1141 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1145 sub print_netdev_full
{
1146 my ($vmid, $conf, $net, $netid) = @_;
1149 if ($netid =~ m/^net(\d+)$/) {
1153 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1155 my $ifname = "tap${vmid}i$i";
1157 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1158 die "interface name '$ifname' is too long (max 15 character)\n"
1159 if length($ifname) >= 16;
1161 my $vhostparam = '';
1162 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1164 my $vmname = $conf->{name
} || "vm$vmid";
1166 if ($net->{bridge
}) {
1167 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1169 return "type=user,id=$netid,hostname=$vmname";
1173 sub drive_is_cdrom
{
1176 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1183 return undef if !$value;
1187 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1188 $res->{pciid
} = $value;
1196 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1202 foreach my $kvp (split(/,/, $data)) {
1204 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1206 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1207 $res->{model
} = $model;
1208 $res->{macaddr
} = $mac;
1209 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1210 $res->{bridge
} = $1;
1211 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1213 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1221 return undef if !$res->{model
};
1229 my $res = "$net->{model}";
1230 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1231 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1232 $res .= ",rate=$net->{rate}" if $net->{rate
};
1233 $res .= ",tag=$net->{tag}" if $net->{tag
};
1238 sub add_random_macs
{
1239 my ($settings) = @_;
1241 foreach my $opt (keys %$settings) {
1242 next if $opt !~ m/^net(\d+)$/;
1243 my $net = parse_net
($settings->{$opt});
1245 $settings->{$opt} = print_net
($net);
1249 sub add_unused_volume
{
1250 my ($config, $volid) = @_;
1253 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1254 my $test = "unused$ind";
1255 if (my $vid = $config->{$test}) {
1256 return if $vid eq $volid; # do not add duplicates
1262 die "To many unused volume - please delete them first.\n" if !$key;
1264 $config->{$key} = $volid;
1269 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1270 sub verify_bootdisk
{
1271 my ($value, $noerr) = @_;
1273 return $value if valid_drivename
($value);
1275 return undef if $noerr;
1277 die "invalid boot disk '$value'\n";
1280 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1282 my ($value, $noerr) = @_;
1284 return $value if parse_net
($value);
1286 return undef if $noerr;
1288 die "unable to parse network options\n";
1291 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1293 my ($value, $noerr) = @_;
1295 return $value if parse_drive
(undef, $value);
1297 return undef if $noerr;
1299 die "unable to parse drive options\n";
1302 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1303 sub verify_hostpci
{
1304 my ($value, $noerr) = @_;
1306 return $value if parse_hostpci
($value);
1308 return undef if $noerr;
1310 die "unable to parse pci id\n";
1313 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1314 sub verify_watchdog
{
1315 my ($value, $noerr) = @_;
1317 return $value if parse_watchdog
($value);
1319 return undef if $noerr;
1321 die "unable to parse watchdog options\n";
1324 sub parse_watchdog
{
1327 return undef if !$value;
1331 foreach my $p (split(/,/, $value)) {
1332 next if $p =~ m/^\s*$/;
1334 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1336 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1337 $res->{action
} = $2;
1346 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1347 sub verify_startup
{
1348 my ($value, $noerr) = @_;
1350 return $value if parse_startup
($value);
1352 return undef if $noerr;
1354 die "unable to parse startup options\n";
1360 return undef if !$value;
1364 foreach my $p (split(/,/, $value)) {
1365 next if $p =~ m/^\s*$/;
1367 if ($p =~ m/^(order=)?(\d+)$/) {
1369 } elsif ($p =~ m/^up=(\d+)$/) {
1371 } elsif ($p =~ m/^down=(\d+)$/) {
1381 sub parse_usb_device
{
1384 return undef if !$value;
1386 my @dl = split(/,/, $value);
1390 foreach my $v (@dl) {
1391 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1393 $res->{vendorid
} = $2;
1394 $res->{productid
} = $4;
1395 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1397 $res->{hostbus
} = $1;
1398 $res->{hostport
} = $2;
1403 return undef if !$found;
1408 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1409 sub verify_usb_device
{
1410 my ($value, $noerr) = @_;
1412 return $value if parse_usb_device
($value);
1414 return undef if $noerr;
1416 die "unable to parse usb device\n";
1419 # add JSON properties for create and set function
1420 sub json_config_properties
{
1423 foreach my $opt (keys %$confdesc) {
1424 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1425 $prop->{$opt} = $confdesc->{$opt};
1432 my ($key, $value) = @_;
1434 die "unknown setting '$key'\n" if !$confdesc->{$key};
1436 my $type = $confdesc->{$key}->{type
};
1438 if (!defined($value)) {
1439 die "got undefined value\n";
1442 if ($value =~ m/[\n\r]/) {
1443 die "property contains a line feed\n";
1446 if ($type eq 'boolean') {
1447 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1448 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1449 die "type check ('boolean') failed - got '$value'\n";
1450 } elsif ($type eq 'integer') {
1451 return int($1) if $value =~ m/^(\d+)$/;
1452 die "type check ('integer') failed - got '$value'\n";
1453 } elsif ($type eq 'number') {
1454 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1455 die "type check ('number') failed - got '$value'\n";
1456 } elsif ($type eq 'string') {
1457 if (my $fmt = $confdesc->{$key}->{format
}) {
1458 if ($fmt eq 'pve-qm-drive') {
1459 # special case - we need to pass $key to parse_drive()
1460 my $drive = parse_drive
($key, $value);
1461 return $value if $drive;
1462 die "unable to parse drive options\n";
1464 PVE
::JSONSchema
::check_format
($fmt, $value);
1467 $value =~ s/^\"(.*)\"$/$1/;
1470 die "internal error"
1474 sub lock_config_full
{
1475 my ($vmid, $timeout, $code, @param) = @_;
1477 my $filename = config_file_lock
($vmid);
1479 my $res = lock_file
($filename, $timeout, $code, @param);
1486 sub lock_config_mode
{
1487 my ($vmid, $timeout, $shared, $code, @param) = @_;
1489 my $filename = config_file_lock
($vmid);
1491 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1499 my ($vmid, $code, @param) = @_;
1501 return lock_config_full
($vmid, 10, $code, @param);
1504 sub cfs_config_path
{
1505 my ($vmid, $node) = @_;
1507 $node = $nodename if !$node;
1508 return "nodes/$node/qemu-server/$vmid.conf";
1511 sub check_iommu_support
{
1512 #fixme : need to check IOMMU support
1513 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1521 my ($vmid, $node) = @_;
1523 my $cfspath = cfs_config_path
($vmid, $node);
1524 return "/etc/pve/$cfspath";
1527 sub config_file_lock
{
1530 return "$lock_dir/lock-$vmid.conf";
1536 my $conf = config_file
($vmid);
1537 utime undef, undef, $conf;
1541 my ($storecfg, $vmid, $keep_empty_config) = @_;
1543 my $conffile = config_file
($vmid);
1545 my $conf = load_config
($vmid);
1549 # only remove disks owned by this VM
1550 foreach_drive
($conf, sub {
1551 my ($ds, $drive) = @_;
1553 return if drive_is_cdrom
($drive);
1555 my $volid = $drive->{file
};
1557 return if !$volid || $volid =~ m
|^/|;
1559 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1560 return if !$path || !$owner || ($owner != $vmid);
1562 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1565 if ($keep_empty_config) {
1566 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1571 # also remove unused disk
1573 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1576 PVE
::Storage
::foreach_volid
($dl, sub {
1577 my ($volid, $sid, $volname, $d) = @_;
1578 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1588 my ($vmid, $node) = @_;
1590 my $cfspath = cfs_config_path
($vmid, $node);
1592 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1594 die "no such VM ('$vmid')\n" if !defined($conf);
1599 sub parse_vm_config
{
1600 my ($filename, $raw) = @_;
1602 return undef if !defined($raw);
1605 digest
=> Digest
::SHA
::sha1_hex
($raw),
1609 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1610 || die "got strange filename '$filename'";
1617 my @lines = split(/\n/, $raw);
1618 foreach my $line (@lines) {
1619 next if $line =~ m/^\s*$/;
1621 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1623 $conf->{description
} = $descr if $descr;
1625 $conf = $res->{snapshots
}->{$snapname} = {};
1629 if ($line =~ m/^\#(.*)\s*$/) {
1630 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1634 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1635 $descr .= PVE
::Tools
::decode_text
($2);
1636 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1637 $conf->{snapstate
} = $1;
1638 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1641 $conf->{$key} = $value;
1642 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1645 eval { $value = check_type
($key, $value); };
1647 warn "vm $vmid - unable to parse value of '$key' - $@";
1649 my $fmt = $confdesc->{$key}->{format
};
1650 if ($fmt && $fmt eq 'pve-qm-drive') {
1651 my $v = parse_drive
($key, $value);
1652 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1653 $v->{file
} = $volid;
1654 $value = print_drive
($vmid, $v);
1656 warn "vm $vmid - unable to parse value of '$key'\n";
1661 if ($key eq 'cdrom') {
1662 $conf->{ide2
} = $value;
1664 $conf->{$key} = $value;
1670 $conf->{description
} = $descr if $descr;
1672 delete $res->{snapstate
}; # just to be sure
1677 sub write_vm_config
{
1678 my ($filename, $conf) = @_;
1680 delete $conf->{snapstate
}; # just to be sure
1682 if ($conf->{cdrom
}) {
1683 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1684 $conf->{ide2
} = $conf->{cdrom
};
1685 delete $conf->{cdrom
};
1688 # we do not use 'smp' any longer
1689 if ($conf->{sockets
}) {
1690 delete $conf->{smp
};
1691 } elsif ($conf->{smp
}) {
1692 $conf->{sockets
} = $conf->{smp
};
1693 delete $conf->{cores
};
1694 delete $conf->{smp
};
1697 my $used_volids = {};
1699 my $cleanup_config = sub {
1700 my ($cref, $snapname) = @_;
1702 foreach my $key (keys %$cref) {
1703 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1704 $key eq 'snapstate';
1705 my $value = $cref->{$key};
1706 eval { $value = check_type
($key, $value); };
1707 die "unable to parse value of '$key' - $@" if $@;
1709 $cref->{$key} = $value;
1711 if (!$snapname && valid_drivename
($key)) {
1712 my $drive = parse_drive
($key, $value);
1713 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1718 &$cleanup_config($conf);
1719 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1720 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1723 # remove 'unusedX' settings if we re-add a volume
1724 foreach my $key (keys %$conf) {
1725 my $value = $conf->{$key};
1726 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1727 delete $conf->{$key};
1731 my $generate_raw_config = sub {
1736 # add description as comment to top of file
1737 my $descr = $conf->{description
} || '';
1738 foreach my $cl (split(/\n/, $descr)) {
1739 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1742 foreach my $key (sort keys %$conf) {
1743 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1744 $raw .= "$key: $conf->{$key}\n";
1749 my $raw = &$generate_raw_config($conf);
1750 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1751 $raw .= "\n[$snapname]\n";
1752 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1758 sub update_config_nolock
{
1759 my ($vmid, $conf, $skiplock) = @_;
1761 check_lock
($conf) if !$skiplock;
1763 my $cfspath = cfs_config_path
($vmid);
1765 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1769 my ($vmid, $conf, $skiplock) = @_;
1771 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1778 # we use static defaults from our JSON schema configuration
1779 foreach my $key (keys %$confdesc) {
1780 if (defined(my $default = $confdesc->{$key}->{default})) {
1781 $res->{$key} = $default;
1785 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1786 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1792 my $vmlist = PVE
::Cluster
::get_vmlist
();
1794 return $res if !$vmlist || !$vmlist->{ids
};
1795 my $ids = $vmlist->{ids
};
1797 foreach my $vmid (keys %$ids) {
1798 my $d = $ids->{$vmid};
1799 next if !$d->{node
} || $d->{node
} ne $nodename;
1800 next if !$d->{type
} || $d->{type
} ne 'qemu';
1801 $res->{$vmid}->{exists} = 1;
1806 # test if VM uses local resources (to prevent migration)
1807 sub check_local_resources
{
1808 my ($conf, $noerr) = @_;
1812 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1813 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1815 foreach my $k (keys %$conf) {
1816 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1819 die "VM uses local resources\n" if $loc_res && !$noerr;
1824 # check if used storages are available on all nodes (use by migrate)
1825 sub check_storage_availability
{
1826 my ($storecfg, $conf, $node) = @_;
1828 foreach_drive
($conf, sub {
1829 my ($ds, $drive) = @_;
1831 my $volid = $drive->{file
};
1834 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1837 # check if storage is available on both nodes
1838 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1839 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1843 # list nodes where all VM images are available (used by has_feature API)
1845 my ($conf, $storecfg) = @_;
1847 my $nodelist = PVE
::Cluster
::get_nodelist
();
1848 my $nodehash = { map { $_ => 1 } @$nodelist };
1849 my $nodename = PVE
::INotify
::nodename
();
1851 foreach_drive
($conf, sub {
1852 my ($ds, $drive) = @_;
1854 my $volid = $drive->{file
};
1857 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1859 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1860 if ($scfg->{disable
}) {
1862 } elsif (my $avail = $scfg->{nodes
}) {
1863 foreach my $node (keys %$nodehash) {
1864 delete $nodehash->{$node} if !$avail->{$node};
1866 } elsif (!$scfg->{shared
}) {
1867 foreach my $node (keys %$nodehash) {
1868 delete $nodehash->{$node} if $node ne $nodename
1880 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1884 my ($pidfile, $pid) = @_;
1886 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1890 return undef if !$line;
1891 my @param = split(/\0/, $line);
1893 my $cmd = $param[0];
1894 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1896 for (my $i = 0; $i < scalar (@param); $i++) {
1899 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1900 my $p = $param[$i+1];
1901 return 1 if $p && ($p eq $pidfile);
1910 my ($vmid, $nocheck, $node) = @_;
1912 my $filename = config_file
($vmid, $node);
1914 die "unable to find configuration file for VM $vmid - no such machine\n"
1915 if !$nocheck && ! -f
$filename;
1917 my $pidfile = pidfile_name
($vmid);
1919 if (my $fd = IO
::File-
>new("<$pidfile")) {
1924 my $mtime = $st->mtime;
1925 if ($mtime > time()) {
1926 warn "file '$filename' modified in future\n";
1929 if ($line =~ m/^(\d+)$/) {
1931 if (check_cmdline
($pidfile, $pid)) {
1932 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1944 my $vzlist = config_list
();
1946 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1948 while (defined(my $de = $fd->read)) {
1949 next if $de !~ m/^(\d+)\.pid$/;
1951 next if !defined($vzlist->{$vmid});
1952 if (my $pid = check_running
($vmid)) {
1953 $vzlist->{$vmid}->{pid
} = $pid;
1961 my ($storecfg, $conf) = @_;
1963 my $bootdisk = $conf->{bootdisk
};
1964 return undef if !$bootdisk;
1965 return undef if !valid_drivename
($bootdisk);
1967 return undef if !$conf->{$bootdisk};
1969 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1970 return undef if !defined($drive);
1972 return undef if drive_is_cdrom
($drive);
1974 my $volid = $drive->{file
};
1975 return undef if !$volid;
1977 return $drive->{size
};
1980 my $last_proc_pid_stat;
1982 # get VM status information
1983 # This must be fast and should not block ($full == false)
1984 # We only query KVM using QMP if $full == true (this can be slow)
1986 my ($opt_vmid, $full) = @_;
1990 my $storecfg = PVE
::Storage
::config
();
1992 my $list = vzlist
();
1993 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
1995 my $cpucount = $cpuinfo->{cpus
} || 1;
1997 foreach my $vmid (keys %$list) {
1998 next if $opt_vmid && ($vmid ne $opt_vmid);
2000 my $cfspath = cfs_config_path
($vmid);
2001 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2004 $d->{pid
} = $list->{$vmid}->{pid
};
2006 # fixme: better status?
2007 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2009 my $size = disksize
($storecfg, $conf);
2010 if (defined($size)) {
2011 $d->{disk
} = 0; # no info available
2012 $d->{maxdisk
} = $size;
2018 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2019 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2021 $d->{name
} = $conf->{name
} || "VM $vmid";
2022 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2024 if ($conf->{balloon
}) {
2025 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2026 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2037 $d->{diskwrite
} = 0;
2039 $d->{template
} = is_template
($conf);
2044 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2045 foreach my $dev (keys %$netdev) {
2046 next if $dev !~ m/^tap([1-9]\d*)i/;
2048 my $d = $res->{$vmid};
2051 $d->{netout
} += $netdev->{$dev}->{receive
};
2052 $d->{netin
} += $netdev->{$dev}->{transmit
};
2055 my $ctime = gettimeofday
;
2057 foreach my $vmid (keys %$list) {
2059 my $d = $res->{$vmid};
2060 my $pid = $d->{pid
};
2063 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2064 next if !$pstat; # not running
2066 my $used = $pstat->{utime} + $pstat->{stime
};
2068 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2070 if ($pstat->{vsize
}) {
2071 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2074 my $old = $last_proc_pid_stat->{$pid};
2076 $last_proc_pid_stat->{$pid} = {
2084 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2086 if ($dtime > 1000) {
2087 my $dutime = $used - $old->{used
};
2089 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2090 $last_proc_pid_stat->{$pid} = {
2096 $d->{cpu
} = $old->{cpu
};
2100 return $res if !$full;
2102 my $qmpclient = PVE
::QMPClient-
>new();
2104 my $ballooncb = sub {
2105 my ($vmid, $resp) = @_;
2107 my $info = $resp->{'return'};
2108 return if !$info->{max_mem
};
2110 my $d = $res->{$vmid};
2112 # use memory assigned to VM
2113 $d->{maxmem
} = $info->{max_mem
};
2114 $d->{balloon
} = $info->{actual
};
2116 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2117 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2118 $d->{freemem
} = $info->{free_mem
};
2123 my $blockstatscb = sub {
2124 my ($vmid, $resp) = @_;
2125 my $data = $resp->{'return'} || [];
2126 my $totalrdbytes = 0;
2127 my $totalwrbytes = 0;
2128 for my $blockstat (@$data) {
2129 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2130 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2132 $res->{$vmid}->{diskread
} = $totalrdbytes;
2133 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2136 my $statuscb = sub {
2137 my ($vmid, $resp) = @_;
2139 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2140 # this fails if ballon driver is not loaded, so this must be
2141 # the last commnand (following command are aborted if this fails).
2142 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2144 my $status = 'unknown';
2145 if (!defined($status = $resp->{'return'}->{status
})) {
2146 warn "unable to get VM status\n";
2150 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2153 foreach my $vmid (keys %$list) {
2154 next if $opt_vmid && ($vmid ne $opt_vmid);
2155 next if !$res->{$vmid}->{pid
}; # not running
2156 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2159 $qmpclient->queue_execute();
2161 foreach my $vmid (keys %$list) {
2162 next if $opt_vmid && ($vmid ne $opt_vmid);
2163 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2170 my ($conf, $func) = @_;
2172 foreach my $ds (keys %$conf) {
2173 next if !valid_drivename
($ds);
2175 my $drive = parse_drive
($ds, $conf->{$ds});
2178 &$func($ds, $drive);
2183 my ($conf, $func) = @_;
2187 my $test_volid = sub {
2188 my ($volid, $is_cdrom) = @_;
2192 $volhash->{$volid} = $is_cdrom || 0;
2195 foreach_drive
($conf, sub {
2196 my ($ds, $drive) = @_;
2197 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2200 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2201 my $snap = $conf->{snapshots
}->{$snapname};
2202 &$test_volid($snap->{vmstate
}, 0);
2203 foreach_drive
($snap, sub {
2204 my ($ds, $drive) = @_;
2205 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2209 foreach my $volid (keys %$volhash) {
2210 &$func($volid, $volhash->{$volid});
2214 sub config_to_command
{
2215 my ($storecfg, $vmid, $conf, $defaults) = @_;
2218 my $globalFlags = [];
2219 my $machineFlags = [];
2224 my $kvmver = kvm_user_version
();
2225 my $vernum = 0; # unknown
2226 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2227 $vernum = $1*1000000+$2*1000;
2228 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2229 $vernum = $1*1000000+$2*1000+$3;
2232 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2234 my $have_ovz = -f
'/proc/vz/vestat';
2236 push @$cmd, '/usr/bin/kvm';
2238 push @$cmd, '-id', $vmid;
2242 my $qmpsocket = qmp_socket
($vmid);
2243 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2244 push @$cmd, '-mon', "chardev=qmp,mode=control";
2246 my $socket = vnc_socket
($vmid);
2247 push @$cmd, '-vnc', "unix:$socket,x509,password";
2249 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2251 push @$cmd, '-daemonize';
2253 $pciaddr = print_pci_addr
("piix3", $bridges);
2254 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2257 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2258 next if !$conf->{"usb$i"};
2261 # include usb device config
2262 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2264 # enable absolute mouse coordinates (needed by vnc)
2265 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2266 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2269 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2270 my $d = parse_hostpci
($conf->{"hostpci$i"});
2272 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2273 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2277 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2278 my $d = parse_usb_device
($conf->{"usb$i"});
2280 if ($d->{vendorid
} && $d->{productid
}) {
2281 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2282 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2283 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2288 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2289 if (my $path = $conf->{"serial$i"}) {
2290 die "no such serial device\n" if ! -c
$path;
2291 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2292 push @$devices, '-device', "isa-serial,chardev=serial$i";
2297 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2298 if (my $path = $conf->{"parallel$i"}) {
2299 die "no such parallel device\n" if ! -c
$path;
2300 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2301 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2305 my $vmname = $conf->{name
} || "vm$vmid";
2307 push @$cmd, '-name', $vmname;
2310 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2311 $sockets = $conf->{sockets
} if $conf->{sockets
};
2313 my $cores = $conf->{cores
} || 1;
2315 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2317 push @$cmd, '-cpu', $conf->{cpu
} if $conf->{cpu
};
2319 push @$cmd, '-nodefaults';
2321 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2323 my $bootindex_hash = {};
2325 foreach my $o (split(//, $bootorder)) {
2326 $bootindex_hash->{$o} = $i*100;
2330 push @$cmd, '-boot', "menu=on";
2332 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2334 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2336 my $vga = $conf->{vga
};
2338 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' || $conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2345 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2348 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2350 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2351 my $useLocaltime = $conf->{localtime};
2353 if (my $ost = $conf->{ostype
}) {
2354 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2356 if ($ost =~ m/^w/) { # windows
2357 $useLocaltime = 1 if !defined($conf->{localtime});
2359 # use time drift fix when acpi is enabled
2360 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2361 $tdf = 1 if !defined($conf->{tdf
});
2365 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2367 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2368 push @$cmd, '-no-hpet';
2372 push @$rtcFlags, 'driftfix=slew' if $tdf;
2375 push @$machineFlags, 'accel=tcg';
2377 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2380 if ($conf->{startdate
}) {
2381 push @$rtcFlags, "base=$conf->{startdate}";
2382 } elsif ($useLocaltime) {
2383 push @$rtcFlags, 'base=localtime';
2386 push @$cmd, '-S' if $conf->{freeze
};
2388 # set keyboard layout
2389 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2390 push @$cmd, '-k', $kb if $kb;
2393 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2394 #push @$cmd, '-soundhw', 'es1370';
2395 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2397 if($conf->{agent
}) {
2398 my $qgasocket = qga_socket
($vmid);
2399 my $pciaddr = print_pci_addr
("qga0", $bridges);
2400 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2401 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2402 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2405 # enable balloon by default, unless explicitly disabled
2406 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2407 $pciaddr = print_pci_addr
("balloon0", $bridges);
2408 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2411 if ($conf->{watchdog
}) {
2412 my $wdopts = parse_watchdog
($conf->{watchdog
});
2413 $pciaddr = print_pci_addr
("watchdog", $bridges);
2414 my $watchdog = $wdopts->{model
} || 'i6300esb';
2415 push @$devices, '-device', "$watchdog$pciaddr";
2416 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2420 my $scsicontroller = {};
2421 my $ahcicontroller = {};
2422 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2424 foreach_drive
($conf, sub {
2425 my ($ds, $drive) = @_;
2427 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2428 push @$vollist, $drive->{file
};
2431 $use_virtio = 1 if $ds =~ m/^virtio/;
2433 if (drive_is_cdrom
($drive)) {
2434 if ($bootindex_hash->{d
}) {
2435 $drive->{bootindex
} = $bootindex_hash->{d
};
2436 $bootindex_hash->{d
} += 1;
2439 if ($bootindex_hash->{c
}) {
2440 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2441 $bootindex_hash->{c
} += 1;
2445 if ($drive->{interface
} eq 'scsi') {
2447 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2448 my $controller = int($drive->{index} / $maxdev);
2449 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2450 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2451 $scsicontroller->{$controller}=1;
2454 if ($drive->{interface
} eq 'sata') {
2455 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2456 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2457 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2458 $ahcicontroller->{$controller}=1;
2461 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2462 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2465 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2467 for (my $i = 0; $i < $MAX_NETS; $i++) {
2468 next if !$conf->{"net$i"};
2469 my $d = parse_net
($conf->{"net$i"});
2472 $use_virtio = 1 if $d->{model
} eq 'virtio';
2474 if ($bootindex_hash->{n
}) {
2475 $d->{bootindex
} = $bootindex_hash->{n
};
2476 $bootindex_hash->{n
} += 1;
2479 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2480 push @$devices, '-netdev', $netdevfull;
2482 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2483 push @$devices, '-device', $netdevicefull;
2487 while (my ($k, $v) = each %$bridges) {
2488 $pciaddr = print_pci_addr
("pci.$k");
2489 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2493 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2494 # when the VM uses virtio devices.
2495 if (!$use_virtio && $have_ovz) {
2497 my $cpuunits = defined($conf->{cpuunits
}) ?
2498 $conf->{cpuunits
} : $defaults->{cpuunits
};
2500 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2502 # fixme: cpulimit is currently ignored
2503 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2507 if ($conf->{args
}) {
2508 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2512 push @$cmd, @$devices;
2513 push @$cmd, '-rtc', join(',', @$rtcFlags)
2514 if scalar(@$rtcFlags);
2515 push @$cmd, '-machine', join(',', @$machineFlags)
2516 if scalar(@$machineFlags);
2517 push @$cmd, '-global', join(',', @$globalFlags)
2518 if scalar(@$globalFlags);
2520 return wantarray ?
($cmd, $vollist) : $cmd;
2525 return "${var_run_tmpdir}/$vmid.vnc";
2530 return "${var_run_tmpdir}/$vmid.qmp";
2535 return "${var_run_tmpdir}/$vmid.qga";
2540 return "${var_run_tmpdir}/$vmid.pid";
2543 sub vm_devices_list
{
2546 my $res = vm_mon_cmd
($vmid, 'query-pci');
2549 foreach my $pcibus (@$res) {
2550 foreach my $device (@{$pcibus->{devices
}}) {
2551 next if !$device->{'qdev_id'};
2552 $devices->{$device->{'qdev_id'}} = $device;
2560 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2562 return 1 if !check_running
($vmid);
2564 if ($deviceid eq 'tablet') {
2565 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2566 qemu_deviceadd
($vmid, $devicefull);
2570 return 1 if !$conf->{hotplug
};
2572 my $devices_list = vm_devices_list
($vmid);
2573 return 1 if defined($devices_list->{$deviceid});
2575 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2577 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2578 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2579 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2580 qemu_deviceadd
($vmid, $devicefull);
2581 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2582 qemu_drivedel
($vmid, $deviceid);
2587 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2588 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2589 my $pciaddr = print_pci_addr
($deviceid);
2590 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2591 qemu_deviceadd
($vmid, $devicefull);
2592 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2595 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2596 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2597 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2598 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2599 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2600 if(!qemu_deviceadd
($vmid, $devicefull)) {
2601 qemu_drivedel
($vmid, $deviceid);
2606 if ($deviceid =~ m/^(net)(\d+)$/) {
2607 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2608 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2609 qemu_deviceadd
($vmid, $netdevicefull);
2610 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2611 qemu_netdevdel
($vmid, $deviceid);
2616 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2618 my $pciaddr = print_pci_addr
($deviceid);
2619 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2620 qemu_deviceadd
($vmid, $devicefull);
2621 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2627 sub vm_deviceunplug
{
2628 my ($vmid, $conf, $deviceid) = @_;
2630 return 1 if !check_running
($vmid);
2632 if ($deviceid eq 'tablet') {
2633 qemu_devicedel
($vmid, $deviceid);
2637 return 1 if !$conf->{hotplug
};
2639 my $devices_list = vm_devices_list
($vmid);
2640 return 1 if !defined($devices_list->{$deviceid});
2642 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2644 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2645 qemu_devicedel
($vmid, $deviceid);
2646 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2647 return undef if !qemu_drivedel
($vmid, $deviceid);
2650 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2651 return undef if !qemu_devicedel
($vmid, $deviceid);
2654 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2655 return undef if !qemu_devicedel
($vmid, $deviceid);
2656 return undef if !qemu_drivedel
($vmid, $deviceid);
2659 if ($deviceid =~ m/^(net)(\d+)$/) {
2660 qemu_devicedel
($vmid, $deviceid);
2661 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2662 return undef if !qemu_netdevdel
($vmid, $deviceid);
2668 sub qemu_deviceadd
{
2669 my ($vmid, $devicefull) = @_;
2671 $devicefull = "driver=".$devicefull;
2672 my %options = split(/[=,]/, $devicefull);
2674 vm_mon_cmd
($vmid, "device_add" , %options);
2678 sub qemu_devicedel
{
2679 my($vmid, $deviceid) = @_;
2680 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2685 my($storecfg, $vmid, $device) = @_;
2687 my $drive = print_drive_full
($storecfg, $vmid, $device);
2688 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2689 # If the command succeeds qemu prints: "OK"
2690 if ($ret !~ m/OK/s) {
2691 syslog
("err", "adding drive failed: $ret");
2698 my($vmid, $deviceid) = @_;
2700 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2702 if ($ret =~ m/Device \'.*?\' not found/s) {
2703 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2705 elsif ($ret ne "") {
2706 syslog
("err", "deleting drive $deviceid failed : $ret");
2712 sub qemu_deviceaddverify
{
2713 my ($vmid,$deviceid) = @_;
2715 for (my $i = 0; $i <= 5; $i++) {
2716 my $devices_list = vm_devices_list
($vmid);
2717 return 1 if defined($devices_list->{$deviceid});
2720 syslog
("err", "error on hotplug device $deviceid");
2725 sub qemu_devicedelverify
{
2726 my ($vmid,$deviceid) = @_;
2728 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2729 for (my $i = 0; $i <= 5; $i++) {
2730 my $devices_list = vm_devices_list
($vmid);
2731 return 1 if !defined($devices_list->{$deviceid});
2734 syslog
("err", "error on hot-unplugging device $deviceid");
2738 sub qemu_findorcreatescsihw
{
2739 my ($storecfg, $conf, $vmid, $device) = @_;
2741 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2742 my $controller = int($device->{index} / $maxdev);
2743 my $scsihwid="scsihw$controller";
2744 my $devices_list = vm_devices_list
($vmid);
2746 if(!defined($devices_list->{$scsihwid})) {
2747 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2752 sub qemu_bridgeadd
{
2753 my ($storecfg, $conf, $vmid, $device) = @_;
2756 my $bridgeid = undef;
2757 print_pci_addr
($device, $bridges);
2759 while (my ($k, $v) = each %$bridges) {
2762 return if $bridgeid < 1;
2763 my $bridge = "pci.$bridgeid";
2764 my $devices_list = vm_devices_list
($vmid);
2766 if(!defined($devices_list->{$bridge})) {
2767 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2772 sub qemu_netdevadd
{
2773 my ($vmid, $conf, $device, $deviceid) = @_;
2775 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2776 my %options = split(/[=,]/, $netdev);
2778 vm_mon_cmd
($vmid, "netdev_add", %options);
2782 sub qemu_netdevdel
{
2783 my ($vmid, $deviceid) = @_;
2785 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2789 sub qemu_block_set_io_throttle
{
2790 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2792 return if !check_running
($vmid) ;
2795 $bps_rd = 0 if !$bps_rd;
2796 $bps_wr = 0 if !$bps_wr;
2797 $iops = 0 if !$iops;
2798 $iops_rd = 0 if !$iops_rd;
2799 $iops_wr = 0 if !$iops_wr;
2801 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));
2805 # old code, only used to shutdown old VM after update
2807 my ($fh, $timeout) = @_;
2809 my $sel = new IO
::Select
;
2816 while (scalar (@ready = $sel->can_read($timeout))) {
2818 if ($count = $fh->sysread($buf, 8192)) {
2819 if ($buf =~ /^(.*)\(qemu\) $/s) {
2826 if (!defined($count)) {
2833 die "monitor read timeout\n" if !scalar(@ready);
2838 # old code, only used to shutdown old VM after update
2839 sub vm_monitor_command
{
2840 my ($vmid, $cmdstr, $nocheck) = @_;
2845 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2847 my $sname = "${var_run_tmpdir}/$vmid.mon";
2849 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2850 die "unable to connect to VM $vmid socket - $!\n";
2854 # hack: migrate sometime blocks the monitor (when migrate_downtime
2856 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2857 $timeout = 60*60; # 1 hour
2861 my $data = __read_avail
($sock, $timeout);
2863 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2864 die "got unexpected qemu monitor banner\n";
2867 my $sel = new IO
::Select
;
2870 if (!scalar(my @ready = $sel->can_write($timeout))) {
2871 die "monitor write error - timeout";
2874 my $fullcmd = "$cmdstr\r";
2876 # syslog('info', "VM $vmid monitor command: $cmdstr");
2879 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2880 die "monitor write error - $!";
2883 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2887 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2888 $timeout = 60*60; # 1 hour
2889 } elsif ($cmdstr =~ m/^(eject|change)/) {
2890 $timeout = 60; # note: cdrom mount command is slow
2892 if ($res = __read_avail
($sock, $timeout)) {
2894 my @lines = split("\r?\n", $res);
2896 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2898 $res = join("\n", @lines);
2906 syslog
("err", "VM $vmid monitor command failed - $err");
2913 sub qemu_block_resize
{
2914 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2916 my $running = check_running
($vmid);
2918 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2920 return if !$running;
2922 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2926 sub qemu_volume_snapshot
{
2927 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2929 my $running = check_running
($vmid);
2931 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2933 return if !$running;
2935 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2939 sub qemu_volume_snapshot_delete
{
2940 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2942 my $running = check_running
($vmid);
2944 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2946 return if !$running;
2948 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
2954 #need to impplement call to qemu-ga
2957 sub qga_unfreezefs
{
2960 #need to impplement call to qemu-ga
2964 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused) = @_;
2966 lock_config
($vmid, sub {
2967 my $conf = load_config
($vmid, $migratedfrom);
2969 die "you can't start a vm if it's a template\n" if is_template
($conf);
2971 check_lock
($conf) if !$skiplock;
2973 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
2975 my $defaults = load_defaults
();
2977 # set environment variable useful inside network script
2978 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
2980 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults);
2982 my $migrate_port = 0;
2985 if ($statefile eq 'tcp') {
2986 $migrate_port = PVE
::Tools
::next_migrate_port
();
2987 my $migrate_uri = "tcp:localhost:${migrate_port}";
2988 push @$cmd, '-incoming', $migrate_uri;
2991 push @$cmd, '-loadstate', $statefile;
2998 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2999 my $d = parse_hostpci
($conf->{"hostpci$i"});
3001 my $info = pci_device_info
("0000:$d->{pciid}");
3002 die "IOMMU not present\n" if !check_iommu_support
();
3003 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3004 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3005 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3008 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3010 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3013 die "start failed: $err" if $err;
3015 print "migration listens on port $migrate_port\n" if $migrate_port;
3017 if ($statefile && $statefile ne 'tcp') {
3018 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3023 my $capabilities = {};
3024 $capabilities->{capability
} = "xbzrle";
3025 $capabilities->{state} = JSON
::true
;
3026 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
3030 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3031 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3032 if $conf->{balloon
};
3033 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3034 path
=> "machine/peripheral/balloon0",
3035 property
=> "guest-stats-polling-interval",
3043 my ($vmid, $execute, %params) = @_;
3045 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3046 vm_qmp_command
($vmid, $cmd);
3049 sub vm_mon_cmd_nocheck
{
3050 my ($vmid, $execute, %params) = @_;
3052 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3053 vm_qmp_command
($vmid, $cmd, 1);
3056 sub vm_qmp_command
{
3057 my ($vmid, $cmd, $nocheck) = @_;
3062 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3063 $timeout = $cmd->{arguments
}->{timeout
};
3064 delete $cmd->{arguments
}->{timeout
};
3068 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3069 my $sname = qmp_socket
($vmid);
3071 my $qmpclient = PVE
::QMPClient-
>new();
3073 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3074 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3075 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3076 if scalar(%{$cmd->{arguments
}});
3077 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3079 die "unable to open monitor socket\n";
3083 syslog
("err", "VM $vmid qmp command failed - $err");
3090 sub vm_human_monitor_command
{
3091 my ($vmid, $cmdline) = @_;
3096 execute
=> 'human-monitor-command',
3097 arguments
=> { 'command-line' => $cmdline},
3100 return vm_qmp_command
($vmid, $cmd);
3103 sub vm_commandline
{
3104 my ($storecfg, $vmid) = @_;
3106 my $conf = load_config
($vmid);
3108 my $defaults = load_defaults
();
3110 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3112 return join(' ', @$cmd);
3116 my ($vmid, $skiplock) = @_;
3118 lock_config
($vmid, sub {
3120 my $conf = load_config
($vmid);
3122 check_lock
($conf) if !$skiplock;
3124 vm_mon_cmd
($vmid, "system_reset");
3128 sub get_vm_volumes
{
3132 foreach_volid
($conf, sub {
3133 my ($volid, $is_cdrom) = @_;
3135 return if $volid =~ m
|^/|;
3137 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3140 push @$vollist, $volid;
3146 sub vm_stop_cleanup
{
3147 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3150 fairsched_rmnod
($vmid); # try to destroy group
3153 my $vollist = get_vm_volumes
($conf);
3154 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3157 foreach my $ext (qw(mon qmp pid vnc qga)) {
3158 unlink "/var/run/qemu-server/${vmid}.$ext";
3161 warn $@ if $@; # avoid errors - just warn
3164 # Note: use $nockeck to skip tests if VM configuration file exists.
3165 # We need that when migration VMs to other nodes (files already moved)
3166 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3168 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3170 $force = 1 if !defined($force) && !$shutdown;
3173 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3174 kill 15, $pid if $pid;
3175 my $conf = load_config
($vmid, $migratedfrom);
3176 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3180 lock_config
($vmid, sub {
3182 my $pid = check_running
($vmid, $nocheck);
3187 $conf = load_config
($vmid);
3188 check_lock
($conf) if !$skiplock;
3189 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3190 my $opts = parse_startup
($conf->{startup
});
3191 $timeout = $opts->{down
} if $opts->{down
};
3195 $timeout = 60 if !defined($timeout);
3199 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3202 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3209 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3214 if ($count >= $timeout) {
3216 warn "VM still running - terminating now with SIGTERM\n";
3219 die "VM quit/powerdown failed - got timeout\n";
3222 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3227 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3230 die "VM quit/powerdown failed\n";
3238 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3243 if ($count >= $timeout) {
3244 warn "VM still running - terminating now with SIGKILL\n";
3249 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3254 my ($vmid, $skiplock) = @_;
3256 lock_config
($vmid, sub {
3258 my $conf = load_config
($vmid);
3260 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3262 vm_mon_cmd
($vmid, "stop");
3267 my ($vmid, $skiplock) = @_;
3269 lock_config
($vmid, sub {
3271 my $conf = load_config
($vmid);
3273 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3275 vm_mon_cmd
($vmid, "cont");
3280 my ($vmid, $skiplock, $key) = @_;
3282 lock_config
($vmid, sub {
3284 my $conf = load_config
($vmid);
3286 # there is no qmp command, so we use the human monitor command
3287 vm_human_monitor_command
($vmid, "sendkey $key");
3292 my ($storecfg, $vmid, $skiplock) = @_;
3294 lock_config
($vmid, sub {
3296 my $conf = load_config
($vmid);
3298 check_lock
($conf) if !$skiplock;
3300 if (!check_running
($vmid)) {
3301 fairsched_rmnod
($vmid); # try to destroy group
3302 destroy_vm
($storecfg, $vmid);
3304 die "VM $vmid is running - destroy failed\n";
3312 my ($filename, $buf) = @_;
3314 my $fh = IO
::File-
>new($filename, "w");
3315 return undef if !$fh;
3317 my $res = print $fh $buf;
3324 sub pci_device_info
{
3329 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3330 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3332 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3333 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3335 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3336 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3338 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3339 return undef if !defined($product) || $product !~ s/^0x//;
3344 product
=> $product,
3350 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3359 my $name = $dev->{name
};
3361 my $fn = "$pcisysfs/devices/$name/reset";
3363 return file_write
($fn, "1");
3366 sub pci_dev_bind_to_stub
{
3369 my $name = $dev->{name
};
3371 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3372 return 1 if -d
$testdir;
3374 my $data = "$dev->{vendor} $dev->{product}";
3375 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3377 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3378 if (!file_write
($fn, $name)) {
3379 return undef if -f
$fn;
3382 $fn = "$pcisysfs/drivers/pci-stub/bind";
3383 if (! -d
$testdir) {
3384 return undef if !file_write
($fn, $name);
3390 sub print_pci_addr
{
3391 my ($id, $bridges) = @_;
3395 piix3
=> { bus
=> 0, addr
=> 1 },
3396 #addr2 : first videocard
3397 balloon0
=> { bus
=> 0, addr
=> 3 },
3398 watchdog
=> { bus
=> 0, addr
=> 4 },
3399 scsihw0
=> { bus
=> 0, addr
=> 5 },
3400 scsihw1
=> { bus
=> 0, addr
=> 6 },
3401 ahci0
=> { bus
=> 0, addr
=> 7 },
3402 qga0
=> { bus
=> 0, addr
=> 8 },
3403 virtio0
=> { bus
=> 0, addr
=> 10 },
3404 virtio1
=> { bus
=> 0, addr
=> 11 },
3405 virtio2
=> { bus
=> 0, addr
=> 12 },
3406 virtio3
=> { bus
=> 0, addr
=> 13 },
3407 virtio4
=> { bus
=> 0, addr
=> 14 },
3408 virtio5
=> { bus
=> 0, addr
=> 15 },
3409 hostpci0
=> { bus
=> 0, addr
=> 16 },
3410 hostpci1
=> { bus
=> 0, addr
=> 17 },
3411 net0
=> { bus
=> 0, addr
=> 18 },
3412 net1
=> { bus
=> 0, addr
=> 19 },
3413 net2
=> { bus
=> 0, addr
=> 20 },
3414 net3
=> { bus
=> 0, addr
=> 21 },
3415 net4
=> { bus
=> 0, addr
=> 22 },
3416 net5
=> { bus
=> 0, addr
=> 23 },
3417 #addr29 : usb-host (pve-usb.cfg)
3418 'pci.1' => { bus
=> 0, addr
=> 30 },
3419 'pci.2' => { bus
=> 0, addr
=> 31 },
3420 'net6' => { bus
=> 1, addr
=> 1 },
3421 'net7' => { bus
=> 1, addr
=> 2 },
3422 'net8' => { bus
=> 1, addr
=> 3 },
3423 'net9' => { bus
=> 1, addr
=> 4 },
3424 'net10' => { bus
=> 1, addr
=> 5 },
3425 'net11' => { bus
=> 1, addr
=> 6 },
3426 'net12' => { bus
=> 1, addr
=> 7 },
3427 'net13' => { bus
=> 1, addr
=> 8 },
3428 'net14' => { bus
=> 1, addr
=> 9 },
3429 'net15' => { bus
=> 1, addr
=> 10 },
3430 'net16' => { bus
=> 1, addr
=> 11 },
3431 'net17' => { bus
=> 1, addr
=> 12 },
3432 'net18' => { bus
=> 1, addr
=> 13 },
3433 'net19' => { bus
=> 1, addr
=> 14 },
3434 'net20' => { bus
=> 1, addr
=> 15 },
3435 'net21' => { bus
=> 1, addr
=> 16 },
3436 'net22' => { bus
=> 1, addr
=> 17 },
3437 'net23' => { bus
=> 1, addr
=> 18 },
3438 'net24' => { bus
=> 1, addr
=> 19 },
3439 'net25' => { bus
=> 1, addr
=> 20 },
3440 'net26' => { bus
=> 1, addr
=> 21 },
3441 'net27' => { bus
=> 1, addr
=> 22 },
3442 'net28' => { bus
=> 1, addr
=> 23 },
3443 'net29' => { bus
=> 1, addr
=> 24 },
3444 'net30' => { bus
=> 1, addr
=> 25 },
3445 'net31' => { bus
=> 1, addr
=> 26 },
3446 'virtio6' => { bus
=> 2, addr
=> 1 },
3447 'virtio7' => { bus
=> 2, addr
=> 2 },
3448 'virtio8' => { bus
=> 2, addr
=> 3 },
3449 'virtio9' => { bus
=> 2, addr
=> 4 },
3450 'virtio10' => { bus
=> 2, addr
=> 5 },
3451 'virtio11' => { bus
=> 2, addr
=> 6 },
3452 'virtio12' => { bus
=> 2, addr
=> 7 },
3453 'virtio13' => { bus
=> 2, addr
=> 8 },
3454 'virtio14' => { bus
=> 2, addr
=> 9 },
3455 'virtio15' => { bus
=> 2, addr
=> 10 },
3458 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3459 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3460 my $bus = $devices->{$id}->{bus
};
3461 $res = ",bus=pci.$bus,addr=$addr";
3462 $bridges->{$bus} = 1 if $bridges;
3468 # vzdump restore implementaion
3470 sub tar_archive_read_firstfile
{
3471 my $archive = shift;
3473 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3475 # try to detect archive type first
3476 my $pid = open (TMP
, "tar tf '$archive'|") ||
3477 die "unable to open file '$archive'\n";
3478 my $firstfile = <TMP
>;
3482 die "ERROR: archive contaions no data\n" if !$firstfile;
3488 sub tar_restore_cleanup
{
3489 my ($storecfg, $statfile) = @_;
3491 print STDERR
"starting cleanup\n";
3493 if (my $fd = IO
::File-
>new($statfile, "r")) {
3494 while (defined(my $line = <$fd>)) {
3495 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3498 if ($volid =~ m
|^/|) {
3499 unlink $volid || die 'unlink failed\n';
3501 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3503 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3505 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3507 print STDERR
"unable to parse line in statfile - $line";
3514 sub restore_archive
{
3515 my ($archive, $vmid, $user, $opts) = @_;
3517 my $format = $opts->{format
};
3520 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3521 $format = 'tar' if !$format;
3523 } elsif ($archive =~ m/\.tar$/) {
3524 $format = 'tar' if !$format;
3525 } elsif ($archive =~ m/.tar.lzo$/) {
3526 $format = 'tar' if !$format;
3528 } elsif ($archive =~ m/\.vma$/) {
3529 $format = 'vma' if !$format;
3530 } elsif ($archive =~ m/\.vma\.gz$/) {
3531 $format = 'vma' if !$format;
3533 } elsif ($archive =~ m/\.vma\.lzo$/) {
3534 $format = 'vma' if !$format;
3537 $format = 'vma' if !$format; # default
3540 # try to detect archive format
3541 if ($format eq 'tar') {
3542 return restore_tar_archive
($archive, $vmid, $user, $opts);
3544 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3548 sub restore_update_config_line
{
3549 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3551 return if $line =~ m/^\#qmdump\#/;
3552 return if $line =~ m/^\#vzdump\#/;
3553 return if $line =~ m/^lock:/;
3554 return if $line =~ m/^unused\d+:/;
3555 return if $line =~ m/^parent:/;
3556 return if $line =~ m/^template:/; # restored VM is never a template
3558 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3559 # try to convert old 1.X settings
3560 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3561 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3562 my ($model, $macaddr) = split(/\=/, $devconfig);
3563 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3566 bridge
=> "vmbr$ind",
3567 macaddr
=> $macaddr,
3569 my $netstr = print_net
($net);
3571 print $outfd "net$cookie->{netcount}: $netstr\n";
3572 $cookie->{netcount
}++;
3574 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3575 my ($id, $netstr) = ($1, $2);
3576 my $net = parse_net
($netstr);
3577 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3578 $netstr = print_net
($net);
3579 print $outfd "$id: $netstr\n";
3580 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3583 if ($line =~ m/backup=no/) {
3584 print $outfd "#$line";
3585 } elsif ($virtdev && $map->{$virtdev}) {
3586 my $di = parse_drive
($virtdev, $value);
3587 delete $di->{format
}; # format can change on restore
3588 $di->{file
} = $map->{$virtdev};
3589 $value = print_drive
($vmid, $di);
3590 print $outfd "$virtdev: $value\n";
3600 my ($cfg, $vmid) = @_;
3602 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3604 my $volid_hash = {};
3605 foreach my $storeid (keys %$info) {
3606 foreach my $item (@{$info->{$storeid}}) {
3607 next if !($item->{volid
} && $item->{size
});
3608 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3609 $volid_hash->{$item->{volid
}} = $item;
3616 sub get_used_paths
{
3617 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3621 my $scan_config = sub {
3622 my ($cref, $snapname) = @_;
3624 foreach my $key (keys %$cref) {
3625 my $value = $cref->{$key};
3626 if (valid_drivename
($key)) {
3627 next if $skip_drive && $key eq $skip_drive;
3628 my $drive = parse_drive
($key, $value);
3629 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3630 if ($drive->{file
} =~ m!^/!) {
3631 $used_path->{$drive->{file
}}++; # = 1;
3633 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3635 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3637 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3638 $used_path->{$path}++; # = 1;
3644 &$scan_config($conf);
3648 if ($scan_snapshots) {
3649 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3650 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3657 sub update_disksize
{
3658 my ($vmid, $conf, $volid_hash) = @_;
3664 # Note: it is allowed to define multiple storages with same path (alias), so
3665 # we need to check both 'volid' and real 'path' (two different volid can point
3666 # to the same path).
3671 foreach my $opt (keys %$conf) {
3672 if (valid_drivename
($opt)) {
3673 my $drive = parse_drive
($opt, $conf->{$opt});
3674 my $volid = $drive->{file
};
3677 $used->{$volid} = 1;
3678 if ($volid_hash->{$volid} &&
3679 (my $path = $volid_hash->{$volid}->{path
})) {
3680 $usedpath->{$path} = 1;
3683 next if drive_is_cdrom
($drive);
3684 next if !$volid_hash->{$volid};
3686 $drive->{size
} = $volid_hash->{$volid}->{size
};
3687 my $new = print_drive
($vmid, $drive);
3688 if ($new ne $conf->{$opt}) {
3690 $conf->{$opt} = $new;
3695 # remove 'unusedX' entry if volume is used
3696 foreach my $opt (keys %$conf) {
3697 next if $opt !~ m/^unused\d+$/;
3698 my $volid = $conf->{$opt};
3699 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3700 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3702 delete $conf->{$opt};
3706 foreach my $volid (sort keys %$volid_hash) {
3707 next if $volid =~ m/vm-$vmid-state-/;
3708 next if $used->{$volid};
3709 my $path = $volid_hash->{$volid}->{path
};
3710 next if !$path; # just to be sure
3711 next if $usedpath->{$path};
3713 add_unused_volume
($conf, $volid);
3714 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3721 my ($vmid, $nolock) = @_;
3723 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3725 my $volid_hash = scan_volids
($cfg, $vmid);
3727 my $updatefn = sub {
3730 my $conf = load_config
($vmid);
3735 foreach my $volid (keys %$volid_hash) {
3736 my $info = $volid_hash->{$volid};
3737 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3740 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3742 update_config_nolock
($vmid, $conf, 1) if $changes;
3745 if (defined($vmid)) {
3749 lock_config
($vmid, $updatefn, $vmid);
3752 my $vmlist = config_list
();
3753 foreach my $vmid (keys %$vmlist) {
3757 lock_config
($vmid, $updatefn, $vmid);
3763 sub restore_vma_archive
{
3764 my ($archive, $vmid, $user, $opts, $comp) = @_;
3766 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3767 my $readfrom = $archive;
3772 my $qarchive = PVE
::Tools
::shellquote
($archive);
3773 if ($comp eq 'gzip') {
3774 $uncomp = "zcat $qarchive|";
3775 } elsif ($comp eq 'lzop') {
3776 $uncomp = "lzop -d -c $qarchive|";
3778 die "unknown compression method '$comp'\n";
3783 my $tmpdir = "/var/tmp/vzdumptmp$$";
3786 # disable interrupts (always do cleanups)
3787 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3788 warn "got interrupt - ignored\n";
3791 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3792 POSIX
::mkfifo
($mapfifo, 0600);
3795 my $openfifo = sub {
3796 open($fifofh, '>', $mapfifo) || die $!;
3799 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3806 my $rpcenv = PVE
::RPCEnvironment
::get
();
3808 my $conffile = config_file
($vmid);
3809 my $tmpfn = "$conffile.$$.tmp";
3811 # Note: $oldconf is undef if VM does not exists
3812 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3814 my $print_devmap = sub {
3815 my $virtdev_hash = {};
3817 my $cfgfn = "$tmpdir/qemu-server.conf";
3819 # we can read the config - that is already extracted
3820 my $fh = IO
::File-
>new($cfgfn, "r") ||
3821 "unable to read qemu-server.conf - $!\n";
3823 while (defined(my $line = <$fh>)) {
3824 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3825 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3826 die "archive does not contain data for drive '$virtdev'\n"
3827 if !$devinfo->{$devname};
3828 if (defined($opts->{storage
})) {
3829 $storeid = $opts->{storage
} || 'local';
3830 } elsif (!$storeid) {
3833 $format = 'raw' if !$format;
3834 $devinfo->{$devname}->{devname
} = $devname;
3835 $devinfo->{$devname}->{virtdev
} = $virtdev;
3836 $devinfo->{$devname}->{format
} = $format;
3837 $devinfo->{$devname}->{storeid
} = $storeid;
3839 # check permission on storage
3840 my $pool = $opts->{pool
}; # todo: do we need that?
3841 if ($user ne 'root@pam') {
3842 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3845 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3849 foreach my $devname (keys %$devinfo) {
3850 die "found no device mapping information for device '$devname'\n"
3851 if !$devinfo->{$devname}->{virtdev
};
3854 my $cfg = cfs_read_file
('storage.cfg');
3856 # create empty/temp config
3858 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3859 foreach_drive
($oldconf, sub {
3860 my ($ds, $drive) = @_;
3862 return if drive_is_cdrom
($drive);
3864 my $volid = $drive->{file
};
3866 return if !$volid || $volid =~ m
|^/|;
3868 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3869 return if !$path || !$owner || ($owner != $vmid);
3871 # Note: only delete disk we want to restore
3872 # other volumes will become unused
3873 if ($virtdev_hash->{$ds}) {
3874 PVE
::Storage
::vdisk_free
($cfg, $volid);
3880 foreach my $virtdev (sort keys %$virtdev_hash) {
3881 my $d = $virtdev_hash->{$virtdev};
3882 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3883 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3885 # test if requested format is supported
3886 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
3887 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
3888 $d->{format
} = $defFormat if !$supported;
3890 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3891 $d->{format
}, undef, $alloc_size);
3892 print STDERR
"new volume ID is '$volid'\n";
3893 $d->{volid
} = $volid;
3894 my $path = PVE
::Storage
::path
($cfg, $volid);
3896 my $write_zeros = 1;
3897 # fixme: what other storages types initialize volumes with zero?
3898 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' ||
3899 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
3903 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3905 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3906 $map->{$virtdev} = $volid;
3909 $fh->seek(0, 0) || die "seek failed - $!\n";
3911 my $outfd = new IO
::File
($tmpfn, "w") ||
3912 die "unable to write config for VM $vmid\n";
3914 my $cookie = { netcount
=> 0 };
3915 while (defined(my $line = <$fh>)) {
3916 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3925 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3926 die "interrupted by signal\n";
3928 local $SIG{ALRM
} = sub { die "got timeout\n"; };
3930 $oldtimeout = alarm($timeout);
3937 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
3938 my ($dev_id, $size, $devname) = ($1, $2, $3);
3939 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
3940 } elsif ($line =~ m/^CTIME: /) {
3942 print $fifofh "done\n";
3943 my $tmp = $oldtimeout || 0;
3944 $oldtimeout = undef;
3950 print "restore vma archive: $cmd\n";
3951 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
3955 alarm($oldtimeout) if $oldtimeout;
3963 my $cfg = cfs_read_file
('storage.cfg');
3964 foreach my $devname (keys %$devinfo) {
3965 my $volid = $devinfo->{$devname}->{volid
};
3968 if ($volid =~ m
|^/|) {
3969 unlink $volid || die 'unlink failed\n';
3971 PVE
::Storage
::vdisk_free
($cfg, $volid);
3973 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3975 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3982 rename($tmpfn, $conffile) ||
3983 die "unable to commit configuration file '$conffile'\n";
3985 PVE
::Cluster
::cfs_update
(); # make sure we read new file
3987 eval { rescan
($vmid, 1); };
3991 sub restore_tar_archive
{
3992 my ($archive, $vmid, $user, $opts) = @_;
3994 if ($archive ne '-') {
3995 my $firstfile = tar_archive_read_firstfile
($archive);
3996 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3997 if $firstfile ne 'qemu-server.conf';
4000 my $storecfg = cfs_read_file
('storage.cfg');
4002 # destroy existing data - keep empty config
4003 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4004 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4006 my $tocmd = "/usr/lib/qemu-server/qmextract";
4008 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4009 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4010 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4011 $tocmd .= ' --info' if $opts->{info
};
4013 # tar option "xf" does not autodetect compression when read from STDIN,
4014 # so we pipe to zcat
4015 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4016 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4018 my $tmpdir = "/var/tmp/vzdumptmp$$";
4021 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4022 local $ENV{VZDUMP_VMID
} = $vmid;
4023 local $ENV{VZDUMP_USER
} = $user;
4025 my $conffile = config_file
($vmid);
4026 my $tmpfn = "$conffile.$$.tmp";
4028 # disable interrupts (always do cleanups)
4029 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4030 print STDERR
"got interrupt - ignored\n";
4035 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4036 die "interrupted by signal\n";
4039 if ($archive eq '-') {
4040 print "extracting archive from STDIN\n";
4041 run_command
($cmd, input
=> "<&STDIN");
4043 print "extracting archive '$archive'\n";
4047 return if $opts->{info
};
4051 my $statfile = "$tmpdir/qmrestore.stat";
4052 if (my $fd = IO
::File-
>new($statfile, "r")) {
4053 while (defined (my $line = <$fd>)) {
4054 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4055 $map->{$1} = $2 if $1;
4057 print STDERR
"unable to parse line in statfile - $line\n";
4063 my $confsrc = "$tmpdir/qemu-server.conf";
4065 my $srcfd = new IO
::File
($confsrc, "r") ||
4066 die "unable to open file '$confsrc'\n";
4068 my $outfd = new IO
::File
($tmpfn, "w") ||
4069 die "unable to write config for VM $vmid\n";
4071 my $cookie = { netcount
=> 0 };
4072 while (defined (my $line = <$srcfd>)) {
4073 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4085 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4092 rename $tmpfn, $conffile ||
4093 die "unable to commit configuration file '$conffile'\n";
4095 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4097 eval { rescan
($vmid, 1); };
4102 # Internal snapshots
4104 # NOTE: Snapshot create/delete involves several non-atomic
4105 # action, and can take a long time.
4106 # So we try to avoid locking the file and use 'lock' variable
4107 # inside the config file instead.
4109 my $snapshot_copy_config = sub {
4110 my ($source, $dest) = @_;
4112 foreach my $k (keys %$source) {
4113 next if $k eq 'snapshots';
4114 next if $k eq 'snapstate';
4115 next if $k eq 'snaptime';
4116 next if $k eq 'vmstate';
4117 next if $k eq 'lock';
4118 next if $k eq 'digest';
4119 next if $k eq 'description';
4120 next if $k =~ m/^unused\d+$/;
4122 $dest->{$k} = $source->{$k};
4126 my $snapshot_apply_config = sub {
4127 my ($conf, $snap) = @_;
4129 # copy snapshot list
4131 snapshots
=> $conf->{snapshots
},
4134 # keep description and list of unused disks
4135 foreach my $k (keys %$conf) {
4136 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4137 $newconf->{$k} = $conf->{$k};
4140 &$snapshot_copy_config($snap, $newconf);
4145 sub foreach_writable_storage
{
4146 my ($conf, $func) = @_;
4150 foreach my $ds (keys %$conf) {
4151 next if !valid_drivename
($ds);
4153 my $drive = parse_drive
($ds, $conf->{$ds});
4155 next if drive_is_cdrom
($drive);
4157 my $volid = $drive->{file
};
4159 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4160 $sidhash->{$sid} = $sid if $sid;
4163 foreach my $sid (sort keys %$sidhash) {
4168 my $alloc_vmstate_volid = sub {
4169 my ($storecfg, $vmid, $conf, $snapname) = @_;
4171 # Note: we try to be smart when selecting a $target storage
4175 # search shared storage first
4176 foreach_writable_storage
($conf, sub {
4178 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4179 return if !$scfg->{shared
};
4181 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4185 # now search local storage
4186 foreach_writable_storage
($conf, sub {
4188 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4189 return if $scfg->{shared
};
4191 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4195 $target = 'local' if !$target;
4197 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4198 # we abort live save after $conf->{memory}, so we need at max twice that space
4199 my $size = $conf->{memory
}*2 + $driver_state_size;
4201 my $name = "vm-$vmid-state-$snapname";
4202 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4203 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4204 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4209 my $snapshot_prepare = sub {
4210 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4214 my $updatefn = sub {
4216 my $conf = load_config
($vmid);
4218 die "you can't take a snapshot if it's a template\n"
4219 if is_template
($conf);
4223 $conf->{lock} = 'snapshot';
4225 die "snapshot name '$snapname' already used\n"
4226 if defined($conf->{snapshots
}->{$snapname});
4228 my $storecfg = PVE
::Storage
::config
();
4229 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4231 $snap = $conf->{snapshots
}->{$snapname} = {};
4233 if ($save_vmstate && check_running
($vmid)) {
4234 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4237 &$snapshot_copy_config($conf, $snap);
4239 $snap->{snapstate
} = "prepare";
4240 $snap->{snaptime
} = time();
4241 $snap->{description
} = $comment if $comment;
4243 update_config_nolock
($vmid, $conf, 1);
4246 lock_config
($vmid, $updatefn);
4251 my $snapshot_commit = sub {
4252 my ($vmid, $snapname) = @_;
4254 my $updatefn = sub {
4256 my $conf = load_config
($vmid);
4258 die "missing snapshot lock\n"
4259 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4261 my $snap = $conf->{snapshots
}->{$snapname};
4263 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4265 die "wrong snapshot state\n"
4266 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4268 delete $snap->{snapstate
};
4269 delete $conf->{lock};
4271 my $newconf = &$snapshot_apply_config($conf, $snap);
4273 $newconf->{parent
} = $snapname;
4275 update_config_nolock
($vmid, $newconf, 1);
4278 lock_config
($vmid, $updatefn);
4281 sub snapshot_rollback
{
4282 my ($vmid, $snapname) = @_;
4288 my $storecfg = PVE
::Storage
::config
();
4290 my $updatefn = sub {
4292 my $conf = load_config
($vmid);
4294 die "you can't rollback if vm is a template\n" if is_template
($conf);
4296 $snap = $conf->{snapshots
}->{$snapname};
4298 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4300 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4301 if $snap->{snapstate
};
4305 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4308 die "unable to rollback vm $vmid: vm is running\n"
4309 if check_running
($vmid);
4312 $conf->{lock} = 'rollback';
4314 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4315 delete $conf->{lock};
4319 # copy snapshot config to current config
4320 $conf = &$snapshot_apply_config($conf, $snap);
4321 $conf->{parent
} = $snapname;
4324 update_config_nolock
($vmid, $conf, 1);
4326 if (!$prepare && $snap->{vmstate
}) {
4327 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4328 vm_start
($storecfg, $vmid, $statefile);
4332 lock_config
($vmid, $updatefn);
4334 foreach_drive
($snap, sub {
4335 my ($ds, $drive) = @_;
4337 return if drive_is_cdrom
($drive);
4339 my $volid = $drive->{file
};
4340 my $device = "drive-$ds";
4342 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4346 lock_config
($vmid, $updatefn);
4349 my $savevm_wait = sub {
4353 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4354 if (!$stat->{status
}) {
4355 die "savevm not active\n";
4356 } elsif ($stat->{status
} eq 'active') {
4359 } elsif ($stat->{status
} eq 'completed') {
4362 die "query-savevm returned status '$stat->{status}'\n";
4367 sub snapshot_create
{
4368 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4370 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4372 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4376 my $running = check_running
($vmid);
4379 # create internal snapshots of all drives
4381 my $storecfg = PVE
::Storage
::config
();
4384 if ($snap->{vmstate
}) {
4385 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4386 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4387 &$savevm_wait($vmid);
4389 vm_mon_cmd
($vmid, "savevm-start");
4393 qga_freezefs
($vmid) if $running && $freezefs;
4395 foreach_drive
($snap, sub {
4396 my ($ds, $drive) = @_;
4398 return if drive_is_cdrom
($drive);
4400 my $volid = $drive->{file
};
4401 my $device = "drive-$ds";
4403 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4404 $drivehash->{$ds} = 1;
4409 eval { gqa_unfreezefs
($vmid) if $running && $freezefs; };
4412 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4416 warn "snapshot create failed: starting cleanup\n";
4417 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4422 &$snapshot_commit($vmid, $snapname);
4425 # Note: $drivehash is only set when called from snapshot_create.
4426 sub snapshot_delete
{
4427 my ($vmid, $snapname, $force, $drivehash) = @_;
4434 my $unlink_parent = sub {
4435 my ($confref, $new_parent) = @_;
4437 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4439 $confref->{parent
} = $new_parent;
4441 delete $confref->{parent
};
4446 my $updatefn = sub {
4447 my ($remove_drive) = @_;
4449 my $conf = load_config
($vmid);
4453 die "you can't delete a snapshot if vm is a template\n"
4454 if is_template
($conf);
4457 $snap = $conf->{snapshots
}->{$snapname};
4459 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4461 # remove parent refs
4462 &$unlink_parent($conf, $snap->{parent
});
4463 foreach my $sn (keys %{$conf->{snapshots
}}) {
4464 next if $sn eq $snapname;
4465 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4468 if ($remove_drive) {
4469 if ($remove_drive eq 'vmstate') {
4470 delete $snap->{$remove_drive};
4472 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4473 my $volid = $drive->{file
};
4474 delete $snap->{$remove_drive};
4475 add_unused_volume
($conf, $volid);
4480 $snap->{snapstate
} = 'delete';
4482 delete $conf->{snapshots
}->{$snapname};
4483 delete $conf->{lock} if $drivehash;
4484 foreach my $volid (@$unused) {
4485 add_unused_volume
($conf, $volid);
4489 update_config_nolock
($vmid, $conf, 1);
4492 lock_config
($vmid, $updatefn);
4494 # now remove vmstate file
4496 my $storecfg = PVE
::Storage
::config
();
4498 if ($snap->{vmstate
}) {
4499 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4501 die $err if !$force;
4504 # save changes (remove vmstate from snapshot)
4505 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4508 # now remove all internal snapshots
4509 foreach_drive
($snap, sub {
4510 my ($ds, $drive) = @_;
4512 return if drive_is_cdrom
($drive);
4514 my $volid = $drive->{file
};
4515 my $device = "drive-$ds";
4517 if (!$drivehash || $drivehash->{$ds}) {
4518 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4520 die $err if !$force;
4525 # save changes (remove drive fron snapshot)
4526 lock_config
($vmid, $updatefn, $ds) if !$force;
4527 push @$unused, $volid;
4530 # now cleanup config
4532 lock_config
($vmid, $updatefn);
4536 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4539 foreach_drive
($conf, sub {
4540 my ($ds, $drive) = @_;
4542 return if drive_is_cdrom
($drive);
4543 my $volid = $drive->{file
};
4544 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4547 return $err ?
0 : 1;
4550 sub template_create
{
4551 my ($vmid, $conf, $disk) = @_;
4553 my $storecfg = PVE
::Storage
::config
();
4555 foreach_drive
($conf, sub {
4556 my ($ds, $drive) = @_;
4558 return if drive_is_cdrom
($drive);
4559 return if $disk && $ds ne $disk;
4561 my $volid = $drive->{file
};
4562 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4564 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4565 $drive->{file
} = $voliddst;
4566 $conf->{$ds} = print_drive
($vmid, $drive);
4567 update_config_nolock
($vmid, $conf, 1);
4574 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4577 sub qemu_img_convert
{
4578 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4580 my $storecfg = PVE
::Storage
::config
();
4581 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4582 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4584 if ($src_storeid && $dst_storeid) {
4585 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4586 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4588 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4589 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4591 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4592 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4595 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C';
4596 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4597 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4601 if($line =~ m/\((\S+)\/100\
%\)/){
4603 my $transferred = int($size * $percent / 100);
4604 my $remaining = $size - $transferred;
4606 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4611 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4613 die "copy failed: $err" if $err;
4617 sub qemu_img_format
{
4618 my ($scfg, $volname) = @_;
4620 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4622 } elsif ($scfg->{type
} eq 'iscsi') {
4623 return "host_device";
4629 sub qemu_drive_mirror
{
4630 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4636 my $storecfg = PVE
::Storage
::config
();
4637 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4640 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4643 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4647 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4650 #fixme : sometime drive-mirror timeout, but works fine after.
4651 # (I have see the problem with big volume > 200GB), so we need to eval
4652 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4653 sync
=> "full", target
=> $dst_path, format
=> $format); };
4655 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4656 sync
=> "full", target
=> $dst_path); };
4661 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4662 my $stat = @$stats[0];
4663 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4664 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4666 my $transferred = $stat->{offset
};
4667 my $total = $stat->{len
};
4668 my $remaining = $total - $transferred;
4669 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4671 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4673 last if ($stat->{len
} == $stat->{offset
});
4674 if ($old_len == $stat->{offset
}) {
4675 if ($maxwait && $count > $maxwait) {
4676 # if writes to disk occurs the disk needs to be freezed
4677 # to be able to complete the migration
4678 vm_suspend
($vmid,1);
4682 $count++ unless $frozen;
4688 $old_len = $stat->{offset
};
4693 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4694 die "mirroring error: $err";
4697 if ($vmiddst != $vmid){
4698 #if we clone a disk for a new target vm, we don't switch the disk
4699 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4701 #if source and destination are on the same guest
4702 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4708 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4709 $newvmid, $storage, $format, $full, $newvollist) = @_;
4714 print "create linked clone of drive $drivename ($drive->{file})\n";
4715 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4716 push @$newvollist, $newvolid;
4718 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4719 $storeid = $storage if $storage;
4721 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4723 $format = $drive->{format
} || $defFormat;
4726 # test if requested format is supported - else use default
4727 my $supported = grep { $_ eq $format } @$validFormats;
4728 $format = $defFormat if !$supported;
4730 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4732 print "create full clone of drive $drivename ($drive->{file})\n";
4733 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4734 push @$newvollist, $newvolid;
4736 if (!$running || $snapname) {
4737 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4739 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4743 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4746 $disk->{format
} = undef;
4747 $disk->{file
} = $newvolid;
4748 $disk->{size
} = $size;