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 {
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 (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});
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 is 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);
1846 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1850 my ($pidfile, $pid) = @_;
1852 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1856 return undef if !$line;
1857 my @param = split(/\0/, $line);
1859 my $cmd = $param[0];
1860 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1862 for (my $i = 0; $i < scalar (@param); $i++) {
1865 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1866 my $p = $param[$i+1];
1867 return 1 if $p && ($p eq $pidfile);
1876 my ($vmid, $nocheck, $node) = @_;
1878 my $filename = config_file
($vmid, $node);
1880 die "unable to find configuration file for VM $vmid - no such machine\n"
1881 if !$nocheck && ! -f
$filename;
1883 my $pidfile = pidfile_name
($vmid);
1885 if (my $fd = IO
::File-
>new("<$pidfile")) {
1890 my $mtime = $st->mtime;
1891 if ($mtime > time()) {
1892 warn "file '$filename' modified in future\n";
1895 if ($line =~ m/^(\d+)$/) {
1897 if (check_cmdline
($pidfile, $pid)) {
1898 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1910 my $vzlist = config_list
();
1912 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1914 while (defined(my $de = $fd->read)) {
1915 next if $de !~ m/^(\d+)\.pid$/;
1917 next if !defined($vzlist->{$vmid});
1918 if (my $pid = check_running
($vmid)) {
1919 $vzlist->{$vmid}->{pid
} = $pid;
1927 my ($storecfg, $conf) = @_;
1929 my $bootdisk = $conf->{bootdisk
};
1930 return undef if !$bootdisk;
1931 return undef if !valid_drivename
($bootdisk);
1933 return undef if !$conf->{$bootdisk};
1935 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1936 return undef if !defined($drive);
1938 return undef if drive_is_cdrom
($drive);
1940 my $volid = $drive->{file
};
1941 return undef if !$volid;
1943 return $drive->{size
};
1946 my $last_proc_pid_stat;
1948 # get VM status information
1949 # This must be fast and should not block ($full == false)
1950 # We only query KVM using QMP if $full == true (this can be slow)
1952 my ($opt_vmid, $full) = @_;
1956 my $storecfg = PVE
::Storage
::config
();
1958 my $list = vzlist
();
1959 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
1961 my $cpucount = $cpuinfo->{cpus
} || 1;
1963 foreach my $vmid (keys %$list) {
1964 next if $opt_vmid && ($vmid ne $opt_vmid);
1966 my $cfspath = cfs_config_path
($vmid);
1967 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
1970 $d->{pid
} = $list->{$vmid}->{pid
};
1972 # fixme: better status?
1973 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
1975 my $size = disksize
($storecfg, $conf);
1976 if (defined($size)) {
1977 $d->{disk
} = 0; # no info available
1978 $d->{maxdisk
} = $size;
1984 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
1985 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
1987 $d->{name
} = $conf->{name
} || "VM $vmid";
1988 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
1990 if ($conf->{balloon
}) {
1991 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
1992 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2003 $d->{diskwrite
} = 0;
2005 $d->{template
} = is_template
($conf);
2010 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2011 foreach my $dev (keys %$netdev) {
2012 next if $dev !~ m/^tap([1-9]\d*)i/;
2014 my $d = $res->{$vmid};
2017 $d->{netout
} += $netdev->{$dev}->{receive
};
2018 $d->{netin
} += $netdev->{$dev}->{transmit
};
2021 my $ctime = gettimeofday
;
2023 foreach my $vmid (keys %$list) {
2025 my $d = $res->{$vmid};
2026 my $pid = $d->{pid
};
2029 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2030 next if !$pstat; # not running
2032 my $used = $pstat->{utime} + $pstat->{stime
};
2034 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2036 if ($pstat->{vsize
}) {
2037 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2040 my $old = $last_proc_pid_stat->{$pid};
2042 $last_proc_pid_stat->{$pid} = {
2050 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2052 if ($dtime > 1000) {
2053 my $dutime = $used - $old->{used
};
2055 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2056 $last_proc_pid_stat->{$pid} = {
2062 $d->{cpu
} = $old->{cpu
};
2066 return $res if !$full;
2068 my $qmpclient = PVE
::QMPClient-
>new();
2070 my $ballooncb = sub {
2071 my ($vmid, $resp) = @_;
2073 my $info = $resp->{'return'};
2074 return if !$info->{max_mem
};
2076 my $d = $res->{$vmid};
2078 # use memory assigned to VM
2079 $d->{maxmem
} = $info->{max_mem
};
2080 $d->{balloon
} = $info->{actual
};
2082 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2083 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2084 $d->{freemem
} = $info->{free_mem
};
2089 my $blockstatscb = sub {
2090 my ($vmid, $resp) = @_;
2091 my $data = $resp->{'return'} || [];
2092 my $totalrdbytes = 0;
2093 my $totalwrbytes = 0;
2094 for my $blockstat (@$data) {
2095 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2096 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2098 $res->{$vmid}->{diskread
} = $totalrdbytes;
2099 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2102 my $statuscb = sub {
2103 my ($vmid, $resp) = @_;
2105 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2106 # this fails if ballon driver is not loaded, so this must be
2107 # the last commnand (following command are aborted if this fails).
2108 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2110 my $status = 'unknown';
2111 if (!defined($status = $resp->{'return'}->{status
})) {
2112 warn "unable to get VM status\n";
2116 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2119 foreach my $vmid (keys %$list) {
2120 next if $opt_vmid && ($vmid ne $opt_vmid);
2121 next if !$res->{$vmid}->{pid
}; # not running
2122 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2125 $qmpclient->queue_execute();
2127 foreach my $vmid (keys %$list) {
2128 next if $opt_vmid && ($vmid ne $opt_vmid);
2129 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2136 my ($conf, $func) = @_;
2138 foreach my $ds (keys %$conf) {
2139 next if !valid_drivename
($ds);
2141 my $drive = parse_drive
($ds, $conf->{$ds});
2144 &$func($ds, $drive);
2149 my ($conf, $func) = @_;
2153 my $test_volid = sub {
2154 my ($volid, $is_cdrom) = @_;
2158 $volhash->{$volid} = $is_cdrom || 0;
2161 foreach_drive
($conf, sub {
2162 my ($ds, $drive) = @_;
2163 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2166 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2167 my $snap = $conf->{snapshots
}->{$snapname};
2168 &$test_volid($snap->{vmstate
}, 0);
2169 foreach_drive
($snap, sub {
2170 my ($ds, $drive) = @_;
2171 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2175 foreach my $volid (keys %$volhash) {
2176 &$func($volid, $volhash->{$volid});
2180 sub config_to_command
{
2181 my ($storecfg, $vmid, $conf, $defaults) = @_;
2184 my $globalFlags = [];
2185 my $machineFlags = [];
2190 my $kvmver = kvm_user_version
();
2191 my $vernum = 0; # unknown
2192 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2193 $vernum = $1*1000000+$2*1000;
2194 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2195 $vernum = $1*1000000+$2*1000+$3;
2198 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2200 my $have_ovz = -f
'/proc/vz/vestat';
2202 push @$cmd, '/usr/bin/kvm';
2204 push @$cmd, '-id', $vmid;
2208 my $qmpsocket = qmp_socket
($vmid);
2209 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2210 push @$cmd, '-mon', "chardev=qmp,mode=control";
2212 my $socket = vnc_socket
($vmid);
2213 push @$cmd, '-vnc', "unix:$socket,x509,password";
2215 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2217 push @$cmd, '-daemonize';
2219 $pciaddr = print_pci_addr
("piix3", $bridges);
2220 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2223 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2224 next if !$conf->{"usb$i"};
2227 # include usb device config
2228 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2230 # enable absolute mouse coordinates (needed by vnc)
2231 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2232 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2235 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2236 my $d = parse_hostpci
($conf->{"hostpci$i"});
2238 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2239 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2243 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2244 my $d = parse_usb_device
($conf->{"usb$i"});
2246 if ($d->{vendorid
} && $d->{productid
}) {
2247 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2248 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2249 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2254 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2255 if (my $path = $conf->{"serial$i"}) {
2256 die "no such serial device\n" if ! -c
$path;
2257 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2258 push @$devices, '-device', "isa-serial,chardev=serial$i";
2263 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2264 if (my $path = $conf->{"parallel$i"}) {
2265 die "no such parallel device\n" if ! -c
$path;
2266 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2267 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2271 my $vmname = $conf->{name
} || "vm$vmid";
2273 push @$cmd, '-name', $vmname;
2276 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2277 $sockets = $conf->{sockets
} if $conf->{sockets
};
2279 my $cores = $conf->{cores
} || 1;
2281 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2283 push @$cmd, '-cpu', $conf->{cpu
} if $conf->{cpu
};
2285 push @$cmd, '-nodefaults';
2287 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2289 my $bootindex_hash = {};
2291 foreach my $o (split(//, $bootorder)) {
2292 $bootindex_hash->{$o} = $i*100;
2296 push @$cmd, '-boot', "menu=on";
2298 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2300 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2302 my $vga = $conf->{vga
};
2304 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' || $conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2311 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2314 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2316 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2317 my $useLocaltime = $conf->{localtime};
2319 if (my $ost = $conf->{ostype
}) {
2320 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2322 if ($ost =~ m/^w/) { # windows
2323 $useLocaltime = 1 if !defined($conf->{localtime});
2325 # use time drift fix when acpi is enabled
2326 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2327 $tdf = 1 if !defined($conf->{tdf
});
2331 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2333 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2334 push @$cmd, '-no-hpet';
2338 push @$rtcFlags, 'driftfix=slew' if $tdf;
2341 push @$machineFlags, 'accel=tcg';
2343 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2346 if ($conf->{startdate
}) {
2347 push @$rtcFlags, "base=$conf->{startdate}";
2348 } elsif ($useLocaltime) {
2349 push @$rtcFlags, 'base=localtime';
2352 push @$cmd, '-S' if $conf->{freeze
};
2354 # set keyboard layout
2355 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2356 push @$cmd, '-k', $kb if $kb;
2359 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2360 #push @$cmd, '-soundhw', 'es1370';
2361 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2363 if($conf->{agent
}) {
2364 my $qgasocket = qga_socket
($vmid);
2365 my $pciaddr = print_pci_addr
("qga0", $bridges);
2366 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2367 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2368 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2371 # enable balloon by default, unless explicitly disabled
2372 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2373 $pciaddr = print_pci_addr
("balloon0", $bridges);
2374 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2377 if ($conf->{watchdog
}) {
2378 my $wdopts = parse_watchdog
($conf->{watchdog
});
2379 $pciaddr = print_pci_addr
("watchdog", $bridges);
2380 my $watchdog = $wdopts->{model
} || 'i6300esb';
2381 push @$devices, '-device', "$watchdog$pciaddr";
2382 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2386 my $scsicontroller = {};
2387 my $ahcicontroller = {};
2388 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2390 foreach_drive
($conf, sub {
2391 my ($ds, $drive) = @_;
2393 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2394 push @$vollist, $drive->{file
};
2397 $use_virtio = 1 if $ds =~ m/^virtio/;
2399 if (drive_is_cdrom
($drive)) {
2400 if ($bootindex_hash->{d
}) {
2401 $drive->{bootindex
} = $bootindex_hash->{d
};
2402 $bootindex_hash->{d
} += 1;
2405 if ($bootindex_hash->{c
}) {
2406 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2407 $bootindex_hash->{c
} += 1;
2411 if ($drive->{interface
} eq 'scsi') {
2413 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2414 my $controller = int($drive->{index} / $maxdev);
2415 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2416 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2417 $scsicontroller->{$controller}=1;
2420 if ($drive->{interface
} eq 'sata') {
2421 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2422 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2423 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2424 $ahcicontroller->{$controller}=1;
2427 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2428 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2431 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2433 for (my $i = 0; $i < $MAX_NETS; $i++) {
2434 next if !$conf->{"net$i"};
2435 my $d = parse_net
($conf->{"net$i"});
2438 $use_virtio = 1 if $d->{model
} eq 'virtio';
2440 if ($bootindex_hash->{n
}) {
2441 $d->{bootindex
} = $bootindex_hash->{n
};
2442 $bootindex_hash->{n
} += 1;
2445 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2446 push @$devices, '-netdev', $netdevfull;
2448 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2449 push @$devices, '-device', $netdevicefull;
2453 while (my ($k, $v) = each %$bridges) {
2454 $pciaddr = print_pci_addr
("pci.$k");
2455 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2459 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2460 # when the VM uses virtio devices.
2461 if (!$use_virtio && $have_ovz) {
2463 my $cpuunits = defined($conf->{cpuunits
}) ?
2464 $conf->{cpuunits
} : $defaults->{cpuunits
};
2466 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2468 # fixme: cpulimit is currently ignored
2469 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2473 if ($conf->{args
}) {
2474 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2478 push @$cmd, @$devices;
2479 push @$cmd, '-rtc', join(',', @$rtcFlags)
2480 if scalar(@$rtcFlags);
2481 push @$cmd, '-machine', join(',', @$machineFlags)
2482 if scalar(@$machineFlags);
2483 push @$cmd, '-global', join(',', @$globalFlags)
2484 if scalar(@$globalFlags);
2486 return wantarray ?
($cmd, $vollist) : $cmd;
2491 return "${var_run_tmpdir}/$vmid.vnc";
2496 return "${var_run_tmpdir}/$vmid.qmp";
2501 return "${var_run_tmpdir}/$vmid.qga";
2506 return "${var_run_tmpdir}/$vmid.pid";
2509 sub next_migrate_port
{
2511 for (my $p = 60000; $p < 60010; $p++) {
2513 my $sock = IO
::Socket
::INET-
>new(Listen
=> 5,
2514 LocalAddr
=> 'localhost',
2525 die "unable to find free migration port";
2528 sub vm_devices_list
{
2531 my $res = vm_mon_cmd
($vmid, 'query-pci');
2534 foreach my $pcibus (@$res) {
2535 foreach my $device (@{$pcibus->{devices
}}) {
2536 next if !$device->{'qdev_id'};
2537 $devices->{$device->{'qdev_id'}} = $device;
2545 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2547 return 1 if !check_running
($vmid);
2549 if ($deviceid eq 'tablet') {
2550 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2551 qemu_deviceadd
($vmid, $devicefull);
2555 return 1 if !$conf->{hotplug
};
2557 my $devices_list = vm_devices_list
($vmid);
2558 return 1 if defined($devices_list->{$deviceid});
2560 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2562 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2563 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2564 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2565 qemu_deviceadd
($vmid, $devicefull);
2566 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2567 qemu_drivedel
($vmid, $deviceid);
2572 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2573 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2574 my $pciaddr = print_pci_addr
($deviceid);
2575 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2576 qemu_deviceadd
($vmid, $devicefull);
2577 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2580 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2581 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2582 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2583 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2584 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2585 if(!qemu_deviceadd
($vmid, $devicefull)) {
2586 qemu_drivedel
($vmid, $deviceid);
2591 if ($deviceid =~ m/^(net)(\d+)$/) {
2592 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2593 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2594 qemu_deviceadd
($vmid, $netdevicefull);
2595 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2596 qemu_netdevdel
($vmid, $deviceid);
2601 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2603 my $pciaddr = print_pci_addr
($deviceid);
2604 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2605 qemu_deviceadd
($vmid, $devicefull);
2606 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2612 sub vm_deviceunplug
{
2613 my ($vmid, $conf, $deviceid) = @_;
2615 return 1 if !check_running
($vmid);
2617 if ($deviceid eq 'tablet') {
2618 qemu_devicedel
($vmid, $deviceid);
2622 return 1 if !$conf->{hotplug
};
2624 my $devices_list = vm_devices_list
($vmid);
2625 return 1 if !defined($devices_list->{$deviceid});
2627 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2629 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2630 qemu_devicedel
($vmid, $deviceid);
2631 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2632 return undef if !qemu_drivedel
($vmid, $deviceid);
2635 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2636 return undef if !qemu_devicedel
($vmid, $deviceid);
2639 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2640 return undef if !qemu_devicedel
($vmid, $deviceid);
2641 return undef if !qemu_drivedel
($vmid, $deviceid);
2644 if ($deviceid =~ m/^(net)(\d+)$/) {
2645 qemu_devicedel
($vmid, $deviceid);
2646 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2647 return undef if !qemu_netdevdel
($vmid, $deviceid);
2653 sub qemu_deviceadd
{
2654 my ($vmid, $devicefull) = @_;
2656 $devicefull = "driver=".$devicefull;
2657 my %options = split(/[=,]/, $devicefull);
2659 vm_mon_cmd
($vmid, "device_add" , %options);
2663 sub qemu_devicedel
{
2664 my($vmid, $deviceid) = @_;
2665 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2670 my($storecfg, $vmid, $device) = @_;
2672 my $drive = print_drive_full
($storecfg, $vmid, $device);
2673 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2674 # If the command succeeds qemu prints: "OK"
2675 if ($ret !~ m/OK/s) {
2676 syslog
("err", "adding drive failed: $ret");
2683 my($vmid, $deviceid) = @_;
2685 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2687 if ($ret =~ m/Device \'.*?\' not found/s) {
2688 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2690 elsif ($ret ne "") {
2691 syslog
("err", "deleting drive $deviceid failed : $ret");
2697 sub qemu_deviceaddverify
{
2698 my ($vmid,$deviceid) = @_;
2700 for (my $i = 0; $i <= 5; $i++) {
2701 my $devices_list = vm_devices_list
($vmid);
2702 return 1 if defined($devices_list->{$deviceid});
2705 syslog
("err", "error on hotplug device $deviceid");
2710 sub qemu_devicedelverify
{
2711 my ($vmid,$deviceid) = @_;
2713 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2714 for (my $i = 0; $i <= 5; $i++) {
2715 my $devices_list = vm_devices_list
($vmid);
2716 return 1 if !defined($devices_list->{$deviceid});
2719 syslog
("err", "error on hot-unplugging device $deviceid");
2723 sub qemu_findorcreatescsihw
{
2724 my ($storecfg, $conf, $vmid, $device) = @_;
2726 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2727 my $controller = int($device->{index} / $maxdev);
2728 my $scsihwid="scsihw$controller";
2729 my $devices_list = vm_devices_list
($vmid);
2731 if(!defined($devices_list->{$scsihwid})) {
2732 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2737 sub qemu_bridgeadd
{
2738 my ($storecfg, $conf, $vmid, $device) = @_;
2741 my $bridgeid = undef;
2742 print_pci_addr
($device, $bridges);
2744 while (my ($k, $v) = each %$bridges) {
2747 return if $bridgeid < 1;
2748 my $bridge = "pci.$bridgeid";
2749 my $devices_list = vm_devices_list
($vmid);
2751 if(!defined($devices_list->{$bridge})) {
2752 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2757 sub qemu_netdevadd
{
2758 my ($vmid, $conf, $device, $deviceid) = @_;
2760 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2761 my %options = split(/[=,]/, $netdev);
2763 vm_mon_cmd
($vmid, "netdev_add", %options);
2767 sub qemu_netdevdel
{
2768 my ($vmid, $deviceid) = @_;
2770 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2774 sub qemu_block_set_io_throttle
{
2775 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2777 return if !check_running
($vmid) ;
2780 $bps_rd = 0 if !$bps_rd;
2781 $bps_wr = 0 if !$bps_wr;
2782 $iops = 0 if !$iops;
2783 $iops_rd = 0 if !$iops_rd;
2784 $iops_wr = 0 if !$iops_wr;
2786 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));
2790 # old code, only used to shutdown old VM after update
2792 my ($fh, $timeout) = @_;
2794 my $sel = new IO
::Select
;
2801 while (scalar (@ready = $sel->can_read($timeout))) {
2803 if ($count = $fh->sysread($buf, 8192)) {
2804 if ($buf =~ /^(.*)\(qemu\) $/s) {
2811 if (!defined($count)) {
2818 die "monitor read timeout\n" if !scalar(@ready);
2823 # old code, only used to shutdown old VM after update
2824 sub vm_monitor_command
{
2825 my ($vmid, $cmdstr, $nocheck) = @_;
2830 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2832 my $sname = "${var_run_tmpdir}/$vmid.mon";
2834 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2835 die "unable to connect to VM $vmid socket - $!\n";
2839 # hack: migrate sometime blocks the monitor (when migrate_downtime
2841 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2842 $timeout = 60*60; # 1 hour
2846 my $data = __read_avail
($sock, $timeout);
2848 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2849 die "got unexpected qemu monitor banner\n";
2852 my $sel = new IO
::Select
;
2855 if (!scalar(my @ready = $sel->can_write($timeout))) {
2856 die "monitor write error - timeout";
2859 my $fullcmd = "$cmdstr\r";
2861 # syslog('info', "VM $vmid monitor command: $cmdstr");
2864 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2865 die "monitor write error - $!";
2868 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2872 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2873 $timeout = 60*60; # 1 hour
2874 } elsif ($cmdstr =~ m/^(eject|change)/) {
2875 $timeout = 60; # note: cdrom mount command is slow
2877 if ($res = __read_avail
($sock, $timeout)) {
2879 my @lines = split("\r?\n", $res);
2881 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2883 $res = join("\n", @lines);
2891 syslog
("err", "VM $vmid monitor command failed - $err");
2898 sub qemu_block_resize
{
2899 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2901 my $running = check_running
($vmid);
2903 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2905 return if !$running;
2907 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2911 sub qemu_volume_snapshot
{
2912 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2914 my $running = check_running
($vmid);
2916 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2918 return if !$running;
2920 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2924 sub qemu_volume_snapshot_delete
{
2925 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2927 my $running = check_running
($vmid);
2929 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2931 return if !$running;
2933 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
2939 #need to impplement call to qemu-ga
2942 sub qga_unfreezefs
{
2945 #need to impplement call to qemu-ga
2949 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused) = @_;
2951 lock_config
($vmid, sub {
2952 my $conf = load_config
($vmid, $migratedfrom);
2954 die "you can't start a vm if it's a template\n" if is_template
($conf);
2956 check_lock
($conf) if !$skiplock;
2958 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
2960 my $defaults = load_defaults
();
2962 # set environment variable useful inside network script
2963 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
2965 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults);
2967 my $migrate_port = 0;
2970 if ($statefile eq 'tcp') {
2971 $migrate_port = next_migrate_port
();
2972 my $migrate_uri = "tcp:localhost:${migrate_port}";
2973 push @$cmd, '-incoming', $migrate_uri;
2976 push @$cmd, '-loadstate', $statefile;
2983 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2984 my $d = parse_hostpci
($conf->{"hostpci$i"});
2986 my $info = pci_device_info
("0000:$d->{pciid}");
2987 die "IOMMU not present\n" if !check_iommu_support
();
2988 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2989 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
2990 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
2993 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
2995 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
2998 die "start failed: $err" if $err;
3000 print "migration listens on port $migrate_port\n" if $migrate_port;
3002 if ($statefile && $statefile ne 'tcp') {
3003 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3008 my $capabilities = {};
3009 $capabilities->{capability
} = "xbzrle";
3010 $capabilities->{state} = JSON
::true
;
3011 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
3015 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3016 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3017 if $conf->{balloon
};
3018 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3019 path
=> "machine/peripheral/balloon0",
3020 property
=> "guest-stats-polling-interval",
3028 my ($vmid, $execute, %params) = @_;
3030 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3031 vm_qmp_command
($vmid, $cmd);
3034 sub vm_mon_cmd_nocheck
{
3035 my ($vmid, $execute, %params) = @_;
3037 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3038 vm_qmp_command
($vmid, $cmd, 1);
3041 sub vm_qmp_command
{
3042 my ($vmid, $cmd, $nocheck) = @_;
3047 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3048 $timeout = $cmd->{arguments
}->{timeout
};
3049 delete $cmd->{arguments
}->{timeout
};
3053 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3054 my $sname = qmp_socket
($vmid);
3056 my $qmpclient = PVE
::QMPClient-
>new();
3058 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3059 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3060 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3061 if scalar(%{$cmd->{arguments
}});
3062 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3064 die "unable to open monitor socket\n";
3068 syslog
("err", "VM $vmid qmp command failed - $err");
3075 sub vm_human_monitor_command
{
3076 my ($vmid, $cmdline) = @_;
3081 execute
=> 'human-monitor-command',
3082 arguments
=> { 'command-line' => $cmdline},
3085 return vm_qmp_command
($vmid, $cmd);
3088 sub vm_commandline
{
3089 my ($storecfg, $vmid) = @_;
3091 my $conf = load_config
($vmid);
3093 my $defaults = load_defaults
();
3095 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3097 return join(' ', @$cmd);
3101 my ($vmid, $skiplock) = @_;
3103 lock_config
($vmid, sub {
3105 my $conf = load_config
($vmid);
3107 check_lock
($conf) if !$skiplock;
3109 vm_mon_cmd
($vmid, "system_reset");
3113 sub get_vm_volumes
{
3117 foreach_volid
($conf, sub {
3118 my ($volid, $is_cdrom) = @_;
3120 return if $volid =~ m
|^/|;
3122 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3125 push @$vollist, $volid;
3131 sub vm_stop_cleanup
{
3132 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3135 fairsched_rmnod
($vmid); # try to destroy group
3138 my $vollist = get_vm_volumes
($conf);
3139 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3142 foreach my $ext (qw(mon qmp pid vnc qga)) {
3143 unlink "/var/run/qemu-server/${vmid}.$ext";
3146 warn $@ if $@; # avoid errors - just warn
3149 # Note: use $nockeck to skip tests if VM configuration file exists.
3150 # We need that when migration VMs to other nodes (files already moved)
3151 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3153 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3155 $force = 1 if !defined($force) && !$shutdown;
3158 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3159 kill 15, $pid if $pid;
3160 my $conf = load_config
($vmid, $migratedfrom);
3161 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3165 lock_config
($vmid, sub {
3167 my $pid = check_running
($vmid, $nocheck);
3172 $conf = load_config
($vmid);
3173 check_lock
($conf) if !$skiplock;
3174 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3175 my $opts = parse_startup
($conf->{startup
});
3176 $timeout = $opts->{down
} if $opts->{down
};
3180 $timeout = 60 if !defined($timeout);
3184 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3187 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3194 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3199 if ($count >= $timeout) {
3201 warn "VM still running - terminating now with SIGTERM\n";
3204 die "VM quit/powerdown failed - got timeout\n";
3207 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3212 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3215 die "VM quit/powerdown failed\n";
3223 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3228 if ($count >= $timeout) {
3229 warn "VM still running - terminating now with SIGKILL\n";
3234 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3239 my ($vmid, $skiplock) = @_;
3241 lock_config
($vmid, sub {
3243 my $conf = load_config
($vmid);
3245 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3247 vm_mon_cmd
($vmid, "stop");
3252 my ($vmid, $skiplock) = @_;
3254 lock_config
($vmid, sub {
3256 my $conf = load_config
($vmid);
3258 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3260 vm_mon_cmd
($vmid, "cont");
3265 my ($vmid, $skiplock, $key) = @_;
3267 lock_config
($vmid, sub {
3269 my $conf = load_config
($vmid);
3271 # there is no qmp command, so we use the human monitor command
3272 vm_human_monitor_command
($vmid, "sendkey $key");
3277 my ($storecfg, $vmid, $skiplock) = @_;
3279 lock_config
($vmid, sub {
3281 my $conf = load_config
($vmid);
3283 check_lock
($conf) if !$skiplock;
3285 if (!check_running
($vmid)) {
3286 fairsched_rmnod
($vmid); # try to destroy group
3287 destroy_vm
($storecfg, $vmid);
3289 die "VM $vmid is running - destroy failed\n";
3297 my ($filename, $buf) = @_;
3299 my $fh = IO
::File-
>new($filename, "w");
3300 return undef if !$fh;
3302 my $res = print $fh $buf;
3309 sub pci_device_info
{
3314 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3315 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3317 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3318 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3320 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3321 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3323 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3324 return undef if !defined($product) || $product !~ s/^0x//;
3329 product
=> $product,
3335 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3344 my $name = $dev->{name
};
3346 my $fn = "$pcisysfs/devices/$name/reset";
3348 return file_write
($fn, "1");
3351 sub pci_dev_bind_to_stub
{
3354 my $name = $dev->{name
};
3356 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3357 return 1 if -d
$testdir;
3359 my $data = "$dev->{vendor} $dev->{product}";
3360 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3362 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3363 if (!file_write
($fn, $name)) {
3364 return undef if -f
$fn;
3367 $fn = "$pcisysfs/drivers/pci-stub/bind";
3368 if (! -d
$testdir) {
3369 return undef if !file_write
($fn, $name);
3375 sub print_pci_addr
{
3376 my ($id, $bridges) = @_;
3380 piix3
=> { bus
=> 0, addr
=> 1 },
3381 #addr2 : first videocard
3382 balloon0
=> { bus
=> 0, addr
=> 3 },
3383 watchdog
=> { bus
=> 0, addr
=> 4 },
3384 scsihw0
=> { bus
=> 0, addr
=> 5 },
3385 scsihw1
=> { bus
=> 0, addr
=> 6 },
3386 ahci0
=> { bus
=> 0, addr
=> 7 },
3387 qga0
=> { bus
=> 0, addr
=> 8 },
3388 virtio0
=> { bus
=> 0, addr
=> 10 },
3389 virtio1
=> { bus
=> 0, addr
=> 11 },
3390 virtio2
=> { bus
=> 0, addr
=> 12 },
3391 virtio3
=> { bus
=> 0, addr
=> 13 },
3392 virtio4
=> { bus
=> 0, addr
=> 14 },
3393 virtio5
=> { bus
=> 0, addr
=> 15 },
3394 hostpci0
=> { bus
=> 0, addr
=> 16 },
3395 hostpci1
=> { bus
=> 0, addr
=> 17 },
3396 net0
=> { bus
=> 0, addr
=> 18 },
3397 net1
=> { bus
=> 0, addr
=> 19 },
3398 net2
=> { bus
=> 0, addr
=> 20 },
3399 net3
=> { bus
=> 0, addr
=> 21 },
3400 net4
=> { bus
=> 0, addr
=> 22 },
3401 net5
=> { bus
=> 0, addr
=> 23 },
3402 #addr29 : usb-host (pve-usb.cfg)
3403 'pci.1' => { bus
=> 0, addr
=> 30 },
3404 'pci.2' => { bus
=> 0, addr
=> 31 },
3405 'net6' => { bus
=> 1, addr
=> 1 },
3406 'net7' => { bus
=> 1, addr
=> 2 },
3407 'net8' => { bus
=> 1, addr
=> 3 },
3408 'net9' => { bus
=> 1, addr
=> 4 },
3409 'net10' => { bus
=> 1, addr
=> 5 },
3410 'net11' => { bus
=> 1, addr
=> 6 },
3411 'net12' => { bus
=> 1, addr
=> 7 },
3412 'net13' => { bus
=> 1, addr
=> 8 },
3413 'net14' => { bus
=> 1, addr
=> 9 },
3414 'net15' => { bus
=> 1, addr
=> 10 },
3415 'net16' => { bus
=> 1, addr
=> 11 },
3416 'net17' => { bus
=> 1, addr
=> 12 },
3417 'net18' => { bus
=> 1, addr
=> 13 },
3418 'net19' => { bus
=> 1, addr
=> 14 },
3419 'net20' => { bus
=> 1, addr
=> 15 },
3420 'net21' => { bus
=> 1, addr
=> 16 },
3421 'net22' => { bus
=> 1, addr
=> 17 },
3422 'net23' => { bus
=> 1, addr
=> 18 },
3423 'net24' => { bus
=> 1, addr
=> 19 },
3424 'net25' => { bus
=> 1, addr
=> 20 },
3425 'net26' => { bus
=> 1, addr
=> 21 },
3426 'net27' => { bus
=> 1, addr
=> 22 },
3427 'net28' => { bus
=> 1, addr
=> 23 },
3428 'net29' => { bus
=> 1, addr
=> 24 },
3429 'net30' => { bus
=> 1, addr
=> 25 },
3430 'net31' => { bus
=> 1, addr
=> 26 },
3431 'virtio6' => { bus
=> 2, addr
=> 1 },
3432 'virtio7' => { bus
=> 2, addr
=> 2 },
3433 'virtio8' => { bus
=> 2, addr
=> 3 },
3434 'virtio9' => { bus
=> 2, addr
=> 4 },
3435 'virtio10' => { bus
=> 2, addr
=> 5 },
3436 'virtio11' => { bus
=> 2, addr
=> 6 },
3437 'virtio12' => { bus
=> 2, addr
=> 7 },
3438 'virtio13' => { bus
=> 2, addr
=> 8 },
3439 'virtio14' => { bus
=> 2, addr
=> 9 },
3440 'virtio15' => { bus
=> 2, addr
=> 10 },
3443 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3444 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3445 my $bus = $devices->{$id}->{bus
};
3446 $res = ",bus=pci.$bus,addr=$addr";
3447 $bridges->{$bus} = 1 if $bridges;
3453 # vzdump restore implementaion
3455 sub tar_archive_read_firstfile
{
3456 my $archive = shift;
3458 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3460 # try to detect archive type first
3461 my $pid = open (TMP
, "tar tf '$archive'|") ||
3462 die "unable to open file '$archive'\n";
3463 my $firstfile = <TMP
>;
3467 die "ERROR: archive contaions no data\n" if !$firstfile;
3473 sub tar_restore_cleanup
{
3474 my ($storecfg, $statfile) = @_;
3476 print STDERR
"starting cleanup\n";
3478 if (my $fd = IO
::File-
>new($statfile, "r")) {
3479 while (defined(my $line = <$fd>)) {
3480 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3483 if ($volid =~ m
|^/|) {
3484 unlink $volid || die 'unlink failed\n';
3486 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3488 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3490 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3492 print STDERR
"unable to parse line in statfile - $line";
3499 sub restore_archive
{
3500 my ($archive, $vmid, $user, $opts) = @_;
3502 my $format = $opts->{format
};
3505 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3506 $format = 'tar' if !$format;
3508 } elsif ($archive =~ m/\.tar$/) {
3509 $format = 'tar' if !$format;
3510 } elsif ($archive =~ m/.tar.lzo$/) {
3511 $format = 'tar' if !$format;
3513 } elsif ($archive =~ m/\.vma$/) {
3514 $format = 'vma' if !$format;
3515 } elsif ($archive =~ m/\.vma\.gz$/) {
3516 $format = 'vma' if !$format;
3518 } elsif ($archive =~ m/\.vma\.lzo$/) {
3519 $format = 'vma' if !$format;
3522 $format = 'vma' if !$format; # default
3525 # try to detect archive format
3526 if ($format eq 'tar') {
3527 return restore_tar_archive
($archive, $vmid, $user, $opts);
3529 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3533 sub restore_update_config_line
{
3534 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3536 return if $line =~ m/^\#qmdump\#/;
3537 return if $line =~ m/^\#vzdump\#/;
3538 return if $line =~ m/^lock:/;
3539 return if $line =~ m/^unused\d+:/;
3540 return if $line =~ m/^parent:/;
3542 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3543 # try to convert old 1.X settings
3544 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3545 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3546 my ($model, $macaddr) = split(/\=/, $devconfig);
3547 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3550 bridge
=> "vmbr$ind",
3551 macaddr
=> $macaddr,
3553 my $netstr = print_net
($net);
3555 print $outfd "net$cookie->{netcount}: $netstr\n";
3556 $cookie->{netcount
}++;
3558 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3559 my ($id, $netstr) = ($1, $2);
3560 my $net = parse_net
($netstr);
3561 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3562 $netstr = print_net
($net);
3563 print $outfd "$id: $netstr\n";
3564 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3567 if ($line =~ m/backup=no/) {
3568 print $outfd "#$line";
3569 } elsif ($virtdev && $map->{$virtdev}) {
3570 my $di = parse_drive
($virtdev, $value);
3571 $di->{file
} = $map->{$virtdev};
3572 $value = print_drive
($vmid, $di);
3573 print $outfd "$virtdev: $value\n";
3583 my ($cfg, $vmid) = @_;
3585 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3587 my $volid_hash = {};
3588 foreach my $storeid (keys %$info) {
3589 foreach my $item (@{$info->{$storeid}}) {
3590 next if !($item->{volid
} && $item->{size
});
3591 $volid_hash->{$item->{volid
}} = $item;
3598 sub update_disksize
{
3599 my ($vmid, $conf, $volid_hash) = @_;
3606 foreach my $opt (keys %$conf) {
3607 if (valid_drivename
($opt)) {
3608 my $drive = parse_drive
($opt, $conf->{$opt});
3609 my $volid = $drive->{file
};
3612 $used->{$volid} = 1;
3614 next if drive_is_cdrom
($drive);
3615 next if !$volid_hash->{$volid};
3617 $drive->{size
} = $volid_hash->{$volid}->{size
};
3619 $conf->{$opt} = print_drive
($vmid, $drive);
3623 foreach my $volid (sort keys %$volid_hash) {
3624 next if $volid =~ m/vm-$vmid-state-/;
3625 next if $used->{$volid};
3627 add_unused_volume
($conf, $volid);
3634 my ($vmid, $nolock) = @_;
3636 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3638 my $volid_hash = scan_volids
($cfg, $vmid);
3640 my $updatefn = sub {
3643 my $conf = load_config
($vmid);
3648 foreach my $volid (keys %$volid_hash) {
3649 my $info = $volid_hash->{$volid};
3650 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3653 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3655 update_config_nolock
($vmid, $conf, 1) if $changes;
3658 if (defined($vmid)) {
3662 lock_config
($vmid, $updatefn, $vmid);
3665 my $vmlist = config_list
();
3666 foreach my $vmid (keys %$vmlist) {
3670 lock_config
($vmid, $updatefn, $vmid);
3676 sub restore_vma_archive
{
3677 my ($archive, $vmid, $user, $opts, $comp) = @_;
3679 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3680 my $readfrom = $archive;
3685 my $qarchive = PVE
::Tools
::shellquote
($archive);
3686 if ($comp eq 'gzip') {
3687 $uncomp = "zcat $qarchive|";
3688 } elsif ($comp eq 'lzop') {
3689 $uncomp = "lzop -d -c $qarchive|";
3691 die "unknown compression method '$comp'\n";
3696 my $tmpdir = "/var/tmp/vzdumptmp$$";
3699 # disable interrupts (always do cleanups)
3700 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3701 warn "got interrupt - ignored\n";
3704 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3705 POSIX
::mkfifo
($mapfifo, 0600);
3708 my $openfifo = sub {
3709 open($fifofh, '>', $mapfifo) || die $!;
3712 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3719 my $rpcenv = PVE
::RPCEnvironment
::get
();
3721 my $conffile = config_file
($vmid);
3722 my $tmpfn = "$conffile.$$.tmp";
3724 # Note: $oldconf is undef if VM does not exists
3725 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3727 my $print_devmap = sub {
3728 my $virtdev_hash = {};
3730 my $cfgfn = "$tmpdir/qemu-server.conf";
3732 # we can read the config - that is already extracted
3733 my $fh = IO
::File-
>new($cfgfn, "r") ||
3734 "unable to read qemu-server.conf - $!\n";
3736 while (defined(my $line = <$fh>)) {
3737 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3738 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3739 die "archive does not contain data for drive '$virtdev'\n"
3740 if !$devinfo->{$devname};
3741 if (defined($opts->{storage
})) {
3742 $storeid = $opts->{storage
} || 'local';
3743 } elsif (!$storeid) {
3746 $format = 'raw' if !$format;
3747 $devinfo->{$devname}->{devname
} = $devname;
3748 $devinfo->{$devname}->{virtdev
} = $virtdev;
3749 $devinfo->{$devname}->{format
} = $format;
3750 $devinfo->{$devname}->{storeid
} = $storeid;
3752 # check permission on storage
3753 my $pool = $opts->{pool
}; # todo: do we need that?
3754 if ($user ne 'root@pam') {
3755 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3758 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3762 foreach my $devname (keys %$devinfo) {
3763 die "found no device mapping information for device '$devname'\n"
3764 if !$devinfo->{$devname}->{virtdev
};
3767 my $cfg = cfs_read_file
('storage.cfg');
3769 # create empty/temp config
3771 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3772 foreach_drive
($oldconf, sub {
3773 my ($ds, $drive) = @_;
3775 return if drive_is_cdrom
($drive);
3777 my $volid = $drive->{file
};
3779 return if !$volid || $volid =~ m
|^/|;
3781 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3782 return if !$path || !$owner || ($owner != $vmid);
3784 # Note: only delete disk we want to restore
3785 # other volumes will become unused
3786 if ($virtdev_hash->{$ds}) {
3787 PVE
::Storage
::vdisk_free
($cfg, $volid);
3793 foreach my $virtdev (sort keys %$virtdev_hash) {
3794 my $d = $virtdev_hash->{$virtdev};
3795 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3796 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3797 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3798 $d->{format
}, undef, $alloc_size);
3799 print STDERR
"new volume ID is '$volid'\n";
3800 $d->{volid
} = $volid;
3801 my $path = PVE
::Storage
::path
($cfg, $volid);
3803 my $write_zeros = 1;
3804 # fixme: what other storages types initialize volumes with zero?
3805 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' ||
3806 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
3810 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3812 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3813 $map->{$virtdev} = $volid;
3816 $fh->seek(0, 0) || die "seek failed - $!\n";
3818 my $outfd = new IO
::File
($tmpfn, "w") ||
3819 die "unable to write config for VM $vmid\n";
3821 my $cookie = { netcount
=> 0 };
3822 while (defined(my $line = <$fh>)) {
3823 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3832 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3833 die "interrupted by signal\n";
3835 local $SIG{ALRM
} = sub { die "got timeout\n"; };
3837 $oldtimeout = alarm($timeout);
3844 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
3845 my ($dev_id, $size, $devname) = ($1, $2, $3);
3846 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
3847 } elsif ($line =~ m/^CTIME: /) {
3849 print $fifofh "done\n";
3850 my $tmp = $oldtimeout || 0;
3851 $oldtimeout = undef;
3857 print "restore vma archive: $cmd\n";
3858 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
3862 alarm($oldtimeout) if $oldtimeout;
3870 my $cfg = cfs_read_file
('storage.cfg');
3871 foreach my $devname (keys %$devinfo) {
3872 my $volid = $devinfo->{$devname}->{volid
};
3875 if ($volid =~ m
|^/|) {
3876 unlink $volid || die 'unlink failed\n';
3878 PVE
::Storage
::vdisk_free
($cfg, $volid);
3880 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3882 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3889 rename($tmpfn, $conffile) ||
3890 die "unable to commit configuration file '$conffile'\n";
3892 PVE
::Cluster
::cfs_update
(); # make sure we read new file
3894 eval { rescan
($vmid, 1); };
3898 sub restore_tar_archive
{
3899 my ($archive, $vmid, $user, $opts) = @_;
3901 if ($archive ne '-') {
3902 my $firstfile = tar_archive_read_firstfile
($archive);
3903 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3904 if $firstfile ne 'qemu-server.conf';
3907 my $storecfg = cfs_read_file
('storage.cfg');
3909 # destroy existing data - keep empty config
3910 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
3911 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
3913 my $tocmd = "/usr/lib/qemu-server/qmextract";
3915 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
3916 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
3917 $tocmd .= ' --prealloc' if $opts->{prealloc
};
3918 $tocmd .= ' --info' if $opts->{info
};
3920 # tar option "xf" does not autodetect compression when read from STDIN,
3921 # so we pipe to zcat
3922 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
3923 PVE
::Tools
::shellquote
("--to-command=$tocmd");
3925 my $tmpdir = "/var/tmp/vzdumptmp$$";
3928 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
3929 local $ENV{VZDUMP_VMID
} = $vmid;
3930 local $ENV{VZDUMP_USER
} = $user;
3932 my $conffile = config_file
($vmid);
3933 my $tmpfn = "$conffile.$$.tmp";
3935 # disable interrupts (always do cleanups)
3936 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3937 print STDERR
"got interrupt - ignored\n";
3942 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3943 die "interrupted by signal\n";
3946 if ($archive eq '-') {
3947 print "extracting archive from STDIN\n";
3948 run_command
($cmd, input
=> "<&STDIN");
3950 print "extracting archive '$archive'\n";
3954 return if $opts->{info
};
3958 my $statfile = "$tmpdir/qmrestore.stat";
3959 if (my $fd = IO
::File-
>new($statfile, "r")) {
3960 while (defined (my $line = <$fd>)) {
3961 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3962 $map->{$1} = $2 if $1;
3964 print STDERR
"unable to parse line in statfile - $line\n";
3970 my $confsrc = "$tmpdir/qemu-server.conf";
3972 my $srcfd = new IO
::File
($confsrc, "r") ||
3973 die "unable to open file '$confsrc'\n";
3975 my $outfd = new IO
::File
($tmpfn, "w") ||
3976 die "unable to write config for VM $vmid\n";
3978 my $cookie = { netcount
=> 0 };
3979 while (defined (my $line = <$srcfd>)) {
3980 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3992 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
3999 rename $tmpfn, $conffile ||
4000 die "unable to commit configuration file '$conffile'\n";
4002 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4004 eval { rescan
($vmid, 1); };
4009 # Internal snapshots
4011 # NOTE: Snapshot create/delete involves several non-atomic
4012 # action, and can take a long time.
4013 # So we try to avoid locking the file and use 'lock' variable
4014 # inside the config file instead.
4016 my $snapshot_copy_config = sub {
4017 my ($source, $dest) = @_;
4019 foreach my $k (keys %$source) {
4020 next if $k eq 'snapshots';
4021 next if $k eq 'snapstate';
4022 next if $k eq 'snaptime';
4023 next if $k eq 'vmstate';
4024 next if $k eq 'lock';
4025 next if $k eq 'digest';
4026 next if $k eq 'description';
4027 next if $k =~ m/^unused\d+$/;
4029 $dest->{$k} = $source->{$k};
4033 my $snapshot_apply_config = sub {
4034 my ($conf, $snap) = @_;
4036 # copy snapshot list
4038 snapshots
=> $conf->{snapshots
},
4041 # keep description and list of unused disks
4042 foreach my $k (keys %$conf) {
4043 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4044 $newconf->{$k} = $conf->{$k};
4047 &$snapshot_copy_config($snap, $newconf);
4052 sub foreach_writable_storage
{
4053 my ($conf, $func) = @_;
4057 foreach my $ds (keys %$conf) {
4058 next if !valid_drivename
($ds);
4060 my $drive = parse_drive
($ds, $conf->{$ds});
4062 next if drive_is_cdrom
($drive);
4064 my $volid = $drive->{file
};
4066 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4067 $sidhash->{$sid} = $sid if $sid;
4070 foreach my $sid (sort keys %$sidhash) {
4075 my $alloc_vmstate_volid = sub {
4076 my ($storecfg, $vmid, $conf, $snapname) = @_;
4078 # Note: we try to be smart when selecting a $target storage
4082 # search shared storage first
4083 foreach_writable_storage
($conf, sub {
4085 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4086 return if !$scfg->{shared
};
4088 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4092 # now search local storage
4093 foreach_writable_storage
($conf, sub {
4095 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4096 return if $scfg->{shared
};
4098 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4102 $target = 'local' if !$target;
4104 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4105 # we abort live save after $conf->{memory}, so we need at max twice that space
4106 my $size = $conf->{memory
}*2 + $driver_state_size;
4108 my $name = "vm-$vmid-state-$snapname";
4109 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4110 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4111 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4116 my $snapshot_prepare = sub {
4117 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4121 my $updatefn = sub {
4123 my $conf = load_config
($vmid);
4125 die "you can't take a snapshot if it's a template\n"
4126 if is_template
($conf);
4130 $conf->{lock} = 'snapshot';
4132 die "snapshot name '$snapname' already used\n"
4133 if defined($conf->{snapshots
}->{$snapname});
4135 my $storecfg = PVE
::Storage
::config
();
4136 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4138 $snap = $conf->{snapshots
}->{$snapname} = {};
4140 if ($save_vmstate && check_running
($vmid)) {
4141 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4144 &$snapshot_copy_config($conf, $snap);
4146 $snap->{snapstate
} = "prepare";
4147 $snap->{snaptime
} = time();
4148 $snap->{description
} = $comment if $comment;
4150 update_config_nolock
($vmid, $conf, 1);
4153 lock_config
($vmid, $updatefn);
4158 my $snapshot_commit = sub {
4159 my ($vmid, $snapname) = @_;
4161 my $updatefn = sub {
4163 my $conf = load_config
($vmid);
4165 die "missing snapshot lock\n"
4166 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4168 my $snap = $conf->{snapshots
}->{$snapname};
4170 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4172 die "wrong snapshot state\n"
4173 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4175 delete $snap->{snapstate
};
4176 delete $conf->{lock};
4178 my $newconf = &$snapshot_apply_config($conf, $snap);
4180 $newconf->{parent
} = $snapname;
4182 update_config_nolock
($vmid, $newconf, 1);
4185 lock_config
($vmid, $updatefn);
4188 sub snapshot_rollback
{
4189 my ($vmid, $snapname) = @_;
4195 my $storecfg = PVE
::Storage
::config
();
4197 my $updatefn = sub {
4199 my $conf = load_config
($vmid);
4201 die "you can't rollback if vm is a template\n" if is_template
($conf);
4203 $snap = $conf->{snapshots
}->{$snapname};
4205 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4207 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4208 if $snap->{snapstate
};
4212 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4215 die "unable to rollback vm $vmid: vm is running\n"
4216 if check_running
($vmid);
4219 $conf->{lock} = 'rollback';
4221 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4222 delete $conf->{lock};
4226 # copy snapshot config to current config
4227 $conf = &$snapshot_apply_config($conf, $snap);
4228 $conf->{parent
} = $snapname;
4231 update_config_nolock
($vmid, $conf, 1);
4233 if (!$prepare && $snap->{vmstate
}) {
4234 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4235 vm_start
($storecfg, $vmid, $statefile);
4239 lock_config
($vmid, $updatefn);
4241 foreach_drive
($snap, sub {
4242 my ($ds, $drive) = @_;
4244 return if drive_is_cdrom
($drive);
4246 my $volid = $drive->{file
};
4247 my $device = "drive-$ds";
4249 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4253 lock_config
($vmid, $updatefn);
4256 my $savevm_wait = sub {
4260 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4261 if (!$stat->{status
}) {
4262 die "savevm not active\n";
4263 } elsif ($stat->{status
} eq 'active') {
4266 } elsif ($stat->{status
} eq 'completed') {
4269 die "query-savevm returned status '$stat->{status}'\n";
4274 sub snapshot_create
{
4275 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4277 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4279 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4283 my $running = check_running
($vmid);
4286 # create internal snapshots of all drives
4288 my $storecfg = PVE
::Storage
::config
();
4291 if ($snap->{vmstate
}) {
4292 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4293 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4294 &$savevm_wait($vmid);
4296 vm_mon_cmd
($vmid, "savevm-start");
4300 qga_freezefs
($vmid) if $running && $freezefs;
4302 foreach_drive
($snap, sub {
4303 my ($ds, $drive) = @_;
4305 return if drive_is_cdrom
($drive);
4307 my $volid = $drive->{file
};
4308 my $device = "drive-$ds";
4310 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4311 $drivehash->{$ds} = 1;
4316 eval { gqa_unfreezefs
($vmid) if $running && $freezefs; };
4319 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4323 warn "snapshot create failed: starting cleanup\n";
4324 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4329 &$snapshot_commit($vmid, $snapname);
4332 # Note: $drivehash is only set when called from snapshot_create.
4333 sub snapshot_delete
{
4334 my ($vmid, $snapname, $force, $drivehash) = @_;
4341 my $unlink_parent = sub {
4342 my ($confref, $new_parent) = @_;
4344 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4346 $confref->{parent
} = $new_parent;
4348 delete $confref->{parent
};
4353 my $updatefn = sub {
4354 my ($remove_drive) = @_;
4356 my $conf = load_config
($vmid);
4360 die "you can't delete a snapshot if vm is a template\n"
4361 if is_template
($conf);
4364 $snap = $conf->{snapshots
}->{$snapname};
4366 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4368 # remove parent refs
4369 &$unlink_parent($conf, $snap->{parent
});
4370 foreach my $sn (keys %{$conf->{snapshots
}}) {
4371 next if $sn eq $snapname;
4372 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4375 if ($remove_drive) {
4376 if ($remove_drive eq 'vmstate') {
4377 delete $snap->{$remove_drive};
4379 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4380 my $volid = $drive->{file
};
4381 delete $snap->{$remove_drive};
4382 add_unused_volume
($conf, $volid);
4387 $snap->{snapstate
} = 'delete';
4389 delete $conf->{snapshots
}->{$snapname};
4390 delete $conf->{lock} if $drivehash;
4391 foreach my $volid (@$unused) {
4392 add_unused_volume
($conf, $volid);
4396 update_config_nolock
($vmid, $conf, 1);
4399 lock_config
($vmid, $updatefn);
4401 # now remove vmstate file
4403 my $storecfg = PVE
::Storage
::config
();
4405 if ($snap->{vmstate
}) {
4406 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4408 die $err if !$force;
4411 # save changes (remove vmstate from snapshot)
4412 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4415 # now remove all internal snapshots
4416 foreach_drive
($snap, sub {
4417 my ($ds, $drive) = @_;
4419 return if drive_is_cdrom
($drive);
4421 my $volid = $drive->{file
};
4422 my $device = "drive-$ds";
4424 if (!$drivehash || $drivehash->{$ds}) {
4425 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4427 die $err if !$force;
4432 # save changes (remove drive fron snapshot)
4433 lock_config
($vmid, $updatefn, $ds) if !$force;
4434 push @$unused, $volid;
4437 # now cleanup config
4439 lock_config
($vmid, $updatefn);
4443 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4446 foreach_drive
($conf, sub {
4447 my ($ds, $drive) = @_;
4449 return if drive_is_cdrom
($drive);
4450 my $volid = $drive->{file
};
4451 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4457 sub template_create
{
4458 my ($vmid, $conf, $disk) = @_;
4460 my $storecfg = PVE
::Storage
::config
();
4462 foreach_drive
($conf, sub {
4463 my ($ds, $drive) = @_;
4465 return if drive_is_cdrom
($drive);
4466 return if $disk && $ds ne $disk;
4468 my $volid = $drive->{file
};
4469 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4471 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4472 $drive->{file
} = $voliddst;
4473 $conf->{$ds} = PVE
::QemuServer
::print_drive
($vmid, $drive);
4474 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1);
4481 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4484 sub qemu_img_convert
{
4485 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4487 my $storecfg = PVE
::Storage
::config
();
4488 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4489 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4491 if ($src_storeid && $dst_storeid) {
4492 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4493 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4495 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4496 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4498 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4499 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4502 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C';
4503 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4504 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4508 if($line =~ m/\((\S+)\/100\
%\)/){
4510 my $transferred = int($size * $percent / 100);
4511 my $remaining = $size - $transferred;
4513 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4518 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4520 die "copy failed: $err" if $err;
4524 sub qemu_img_format
{
4525 my ($scfg, $volname) = @_;
4527 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/){
4530 elsif ($scfg->{type
} eq 'nexenta' || $scfg->{type
} eq 'iscsidirect'){
4533 elsif ($scfg->{type
} eq 'lvm' || $scfg->{type
} eq 'iscsi'){
4534 return "host_device";
4536 elsif ($scfg->{type
} eq 'rbd'){
4539 #sheepdog other qemu block driver
4541 return $scfg->{type
};