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 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
=> "Activate 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.",
215 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
216 enum
=> PVE
::Tools
::kvmkeymaplist
(),
221 type
=> 'string', format
=> 'dns-name',
222 description
=> "Set a name for the VM. Only used on the configuration web interface.",
227 description
=> "scsi controller model",
228 enum
=> [qw(lsi virtio-scsi-pci megasas)],
234 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
239 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
240 description
=> <<EODESC,
241 Used to enable special optimization/features for specific
244 other => unspecified OS
245 wxp => Microsoft Windows XP
246 w2k => Microsoft Windows 2000
247 w2k3 => Microsoft Windows 2003
248 w2k8 => Microsoft Windows 2008
249 wvista => Microsoft Windows Vista
250 win7 => Microsoft Windows 7
251 win8 => Microsoft Windows 8/2012
252 l24 => Linux 2.4 Kernel
253 l26 => Linux 2.6/3.X Kernel
255 other|l24|l26 ... no special behaviour
256 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
262 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
263 pattern
=> '[acdn]{1,4}',
268 type
=> 'string', format
=> 'pve-qm-bootdisk',
269 description
=> "Enable booting from specified disk.",
270 pattern
=> '(ide|sata|scsi|virtio)\d+',
275 description
=> "The number of CPUs. Please use option -sockets instead.",
282 description
=> "The number of CPU sockets.",
289 description
=> "The number of cores per socket.",
296 description
=> "Enable/disable ACPI.",
302 description
=> "Enable/disable Qemu GuestAgent.",
308 description
=> "Enable/disable KVM hardware virtualization.",
314 description
=> "Enable/disable time drift fix.",
320 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
325 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
330 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",
331 enum
=> [qw(std cirrus vmware)],
335 type
=> 'string', format
=> 'pve-qm-watchdog',
336 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
337 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)",
342 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
343 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'.",
344 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
349 type
=> 'string', format
=> 'pve-qm-startup',
350 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
351 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.",
356 description
=> <<EODESCR,
357 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
359 args: -no-reboot -no-hpet
366 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.",
371 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
375 migrate_downtime
=> {
378 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
384 type
=> 'string', format
=> 'pve-qm-drive',
385 typetext
=> 'volume',
386 description
=> "This is an alias for option -ide2",
390 description
=> "Emulated CPU type.",
392 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) ],
395 parent
=> get_standard_option
('pve-snapshot-name', {
397 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
401 description
=> "Timestamp for snapshots.",
407 type
=> 'string', format
=> 'pve-volume-id',
408 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
412 # what about other qemu settings ?
414 #machine => 'string',
427 ##soundhw => 'string',
429 while (my ($k, $v) = each %$confdesc) {
430 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
433 my $MAX_IDE_DISKS = 4;
434 my $MAX_SCSI_DISKS = 14;
435 my $MAX_VIRTIO_DISKS = 16;
436 my $MAX_SATA_DISKS = 6;
437 my $MAX_USB_DEVICES = 5;
439 my $MAX_UNUSED_DISKS = 8;
440 my $MAX_HOSTPCI_DEVICES = 2;
441 my $MAX_SERIAL_PORTS = 4;
442 my $MAX_PARALLEL_PORTS = 3;
444 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
445 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
446 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
450 type
=> 'string', format
=> 'pve-qm-net',
451 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
452 description
=> <<EODESCR,
453 Specify network devices.
455 MODEL is one of: $nic_model_list_txt
457 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
458 automatically generated if not specified.
460 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
462 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'.
464 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
470 The DHCP server assign addresses to the guest starting from 10.0.2.15.
474 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
476 for (my $i = 0; $i < $MAX_NETS; $i++) {
477 $confdesc->{"net$i"} = $netdesc;
484 type
=> 'string', format
=> 'pve-qm-drive',
485 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]',
486 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
488 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
492 type
=> 'string', format
=> 'pve-qm-drive',
493 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]',
494 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
496 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
500 type
=> 'string', format
=> 'pve-qm-drive',
501 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]',
502 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
508 type
=> 'string', format
=> 'pve-qm-drive',
509 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]',
510 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
512 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
516 type
=> 'string', format
=> 'pve-qm-usb-device',
517 typetext
=> 'host=HOSTUSBDEVICE',
518 description
=> <<EODESCR,
519 Configure an USB device (n is 0 to 4). This can be used to
520 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
522 'bus-port(.port)*' (decimal numbers) or
523 'vendor_id:product_id' (hexadeciaml numbers)
525 You can use the 'lsusb -t' command to list existing usb devices.
527 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
531 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
535 type
=> 'string', format
=> 'pve-qm-hostpci',
536 typetext
=> "HOSTPCIDEVICE",
537 description
=> <<EODESCR,
538 Map host pci devices. HOSTPCIDEVICE syntax is:
540 'bus:dev.func' (hexadecimal numbers)
542 You can us the 'lspci' command to list existing pci devices.
544 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
546 Experimental: user reported problems with this option.
549 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
554 pattern
=> '/dev/ttyS\d+',
555 description
=> <<EODESCR,
556 Map host serial devices (n is 0 to 3).
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.
567 pattern
=> '/dev/parport\d+',
568 description
=> <<EODESCR,
569 Map host parallel devices (n is 0 to 2).
571 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
573 Experimental: user reported problems with this option.
577 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
578 $confdesc->{"parallel$i"} = $paralleldesc;
581 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
582 $confdesc->{"serial$i"} = $serialdesc;
585 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
586 $confdesc->{"hostpci$i"} = $hostpcidesc;
589 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
590 $drivename_hash->{"ide$i"} = 1;
591 $confdesc->{"ide$i"} = $idedesc;
594 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
595 $drivename_hash->{"sata$i"} = 1;
596 $confdesc->{"sata$i"} = $satadesc;
599 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
600 $drivename_hash->{"scsi$i"} = 1;
601 $confdesc->{"scsi$i"} = $scsidesc ;
604 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
605 $drivename_hash->{"virtio$i"} = 1;
606 $confdesc->{"virtio$i"} = $virtiodesc;
609 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
610 $confdesc->{"usb$i"} = $usbdesc;
615 type
=> 'string', format
=> 'pve-volume-id',
616 description
=> "Reference to unused volumes.",
619 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
620 $confdesc->{"unused$i"} = $unuseddesc;
623 my $kvm_api_version = 0;
627 return $kvm_api_version if $kvm_api_version;
629 my $fh = IO
::File-
>new("</dev/kvm") ||
632 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
633 $kvm_api_version = $v;
638 return $kvm_api_version;
641 my $kvm_user_version;
643 sub kvm_user_version
{
645 return $kvm_user_version if $kvm_user_version;
647 $kvm_user_version = 'unknown';
649 my $tmp = `kvm -help 2>/dev/null`;
651 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
652 $kvm_user_version = $2;
655 return $kvm_user_version;
659 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
662 # order is important - used to autoselect boot disk
663 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
664 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
665 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
666 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
669 sub valid_drivename
{
672 return defined($drivename_hash->{$dev});
677 return defined($confdesc->{$key});
681 return $nic_model_list;
684 sub os_list_description
{
689 w2k
=> 'Windows 2000',
690 w2k3
=>, 'Windows 2003',
691 w2k8
=> 'Windows 2008',
692 wvista
=> 'Windows Vista',
694 win8
=> 'Windows 8/2012',
704 return $cdrom_path if $cdrom_path;
706 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
707 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
708 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
712 my ($storecfg, $vmid, $cdrom) = @_;
714 if ($cdrom eq 'cdrom') {
715 return get_cdrom_path
();
716 } elsif ($cdrom eq 'none') {
718 } elsif ($cdrom =~ m
|^/|) {
721 return PVE
::Storage
::path
($storecfg, $cdrom);
725 # try to convert old style file names to volume IDs
726 sub filename_to_volume_id
{
727 my ($vmid, $file, $media) = @_;
729 if (!($file eq 'none' || $file eq 'cdrom' ||
730 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
732 return undef if $file =~ m
|/|;
734 if ($media && $media eq 'cdrom') {
735 $file = "local:iso/$file";
737 $file = "local:$vmid/$file";
744 sub verify_media_type
{
745 my ($opt, $vtype, $media) = @_;
750 if ($media eq 'disk') {
752 } elsif ($media eq 'cdrom') {
755 die "internal error";
758 return if ($vtype eq $etype);
760 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
763 sub cleanup_drive_path
{
764 my ($opt, $storecfg, $drive) = @_;
766 # try to convert filesystem paths to volume IDs
768 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
769 ($drive->{file
} !~ m
|^/dev/.+|) &&
770 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
771 ($drive->{file
} !~ m/^\d+$/)) {
772 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
773 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
774 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
775 verify_media_type
($opt, $vtype, $drive->{media
});
776 $drive->{file
} = $volid;
779 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
782 sub create_conf_nolock
{
783 my ($vmid, $settings) = @_;
785 my $filename = config_file
($vmid);
787 die "configuration file '$filename' already exists\n" if -f
$filename;
789 my $defaults = load_defaults
();
791 $settings->{name
} = "vm$vmid" if !$settings->{name
};
792 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
795 foreach my $opt (keys %$settings) {
796 next if !$confdesc->{$opt};
798 my $value = $settings->{$opt};
801 $data .= "$opt: $value\n";
804 PVE
::Tools
::file_set_contents
($filename, $data);
807 my $parse_size = sub {
810 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
811 my ($size, $unit) = ($1, $3);
814 $size = $size * 1024;
815 } elsif ($unit eq 'M') {
816 $size = $size * 1024 * 1024;
817 } elsif ($unit eq 'G') {
818 $size = $size * 1024 * 1024 * 1024;
824 my $format_size = sub {
829 my $kb = int($size/1024);
830 return $size if $kb*1024 != $size;
832 my $mb = int($kb/1024);
833 return "${kb}K" if $mb*1024 != $kb;
835 my $gb = int($mb/1024);
836 return "${mb}M" if $gb*1024 != $mb;
841 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
842 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
843 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
844 # [,aio=native|threads]
847 my ($key, $data) = @_;
851 # $key may be undefined - used to verify JSON parameters
852 if (!defined($key)) {
853 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
855 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
856 $res->{interface
} = $1;
862 foreach my $p (split (/,/, $data)) {
863 next if $p =~ m/^\s*$/;
865 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)=(.+)$/) {
866 my ($k, $v) = ($1, $2);
868 $k = 'file' if $k eq 'volume';
870 return undef if defined $res->{$k};
872 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
873 return undef if !$v || $v !~ m/^\d+/;
875 $v = sprintf("%.3f", $v / (1024*1024));
879 if (!$res->{file
} && $p !~ m/=/) {
887 return undef if !$res->{file
};
889 return undef if $res->{cache
} &&
890 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
891 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
892 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
893 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
894 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
895 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
896 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
897 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
898 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
899 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
900 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
901 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
904 return undef if $res->{mbps_rd
} && $res->{mbps
};
905 return undef if $res->{mbps_wr
} && $res->{mbps
};
907 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
908 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
909 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
911 return undef if $res->{iops_rd
} && $res->{iops
};
912 return undef if $res->{iops_wr
} && $res->{iops
};
913 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
914 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
915 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
919 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
922 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
923 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
924 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
925 return undef if $res->{interface
} eq 'virtio';
928 # rerror does not work with scsi drives
929 if ($res->{rerror
}) {
930 return undef if $res->{interface
} eq 'scsi';
936 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
939 my ($vmid, $drive) = @_;
942 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
943 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
946 if ($drive->{size
}) {
947 $opts .= ",size=" . &$format_size($drive->{size
});
950 return "$drive->{file}$opts";
954 my($fh, $noerr) = @_;
957 my $SG_GET_VERSION_NUM = 0x2282;
959 my $versionbuf = "\x00" x
8;
960 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
962 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
965 my $version = unpack("I", $versionbuf);
966 if ($version < 30000) {
967 die "scsi generic interface too old\n" if !$noerr;
971 my $buf = "\x00" x
36;
972 my $sensebuf = "\x00" x
8;
973 my $cmd = pack("C x3 C x11", 0x12, 36);
975 # see /usr/include/scsi/sg.h
976 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";
978 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
979 length($sensebuf), 0, length($buf), $buf,
980 $cmd, $sensebuf, 6000);
982 $ret = ioctl($fh, $SG_IO, $packet);
984 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
988 my @res = unpack($sg_io_hdr_t, $packet);
989 if ($res[17] || $res[18]) {
990 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
995 ($res->{device
}, $res->{removable
}, $res->{venodor
},
996 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1004 my $fh = IO
::File-
>new("+<$path") || return undef;
1005 my $res = scsi_inquiry
($fh, 1);
1011 sub print_drivedevice_full
{
1012 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1017 if ($drive->{interface
} eq 'virtio') {
1018 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1019 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1020 } elsif ($drive->{interface
} eq 'scsi') {
1021 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1022 my $controller = int($drive->{index} / $maxdev);
1023 my $unit = $drive->{index} % $maxdev;
1024 my $devicetype = 'hd';
1026 if (drive_is_cdrom
($drive)) {
1029 if ($drive->{file
} =~ m
|^/|) {
1030 $path = $drive->{file
};
1032 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1035 if($path =~ m/^iscsi\:\/\
//){
1036 $devicetype = 'generic';
1039 $devicetype = 'block' if path_is_scsi
($path);
1043 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1044 $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';
1046 $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}";
1049 } elsif ($drive->{interface
} eq 'ide'){
1051 my $controller = int($drive->{index} / $maxdev);
1052 my $unit = $drive->{index} % $maxdev;
1053 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1055 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1056 } elsif ($drive->{interface
} eq 'sata'){
1057 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1058 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1059 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1060 } elsif ($drive->{interface
} eq 'usb') {
1062 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1064 die "unsupported interface type";
1067 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1072 sub print_drive_full
{
1073 my ($storecfg, $vmid, $drive) = @_;
1076 foreach my $o (@qemu_drive_options) {
1077 next if $o eq 'bootindex';
1078 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1081 foreach my $o (qw(bps bps_rd bps_wr)) {
1082 my $v = $drive->{"m$o"};
1083 $opts .= ",$o=" . int($v*1024*1024) if $v;
1086 # use linux-aio by default (qemu default is threads)
1087 $opts .= ",aio=native" if !$drive->{aio
};
1090 my $volid = $drive->{file
};
1091 if (drive_is_cdrom
($drive)) {
1092 $path = get_iso_path
($storecfg, $vmid, $volid);
1094 if ($volid =~ m
|^/|) {
1097 $path = PVE
::Storage
::path
($storecfg, $volid);
1099 if (!$drive->{cache
} && ($path =~ m
|^/dev/| || $path =~ m
|\
.raw
$|)) {
1100 $opts .= ",cache=none";
1104 my $pathinfo = $path ?
"file=$path," : '';
1106 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1109 sub print_netdevice_full
{
1110 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1112 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1114 my $device = $net->{model
};
1115 if ($net->{model
} eq 'virtio') {
1116 $device = 'virtio-net-pci';
1119 # qemu > 0.15 always try to boot from network - we disable that by
1120 # not loading the pxe rom file
1121 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1122 my $pciaddr = print_pci_addr
("$netid", $bridges);
1123 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1124 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1128 sub print_netdev_full
{
1129 my ($vmid, $conf, $net, $netid) = @_;
1132 if ($netid =~ m/^net(\d+)$/) {
1136 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1138 my $ifname = "tap${vmid}i$i";
1140 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1141 die "interface name '$ifname' is too long (max 15 character)\n"
1142 if length($ifname) >= 16;
1144 my $vhostparam = '';
1145 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1147 my $vmname = $conf->{name
} || "vm$vmid";
1149 if ($net->{bridge
}) {
1150 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1152 return "type=user,id=$netid,hostname=$vmname";
1156 sub drive_is_cdrom
{
1159 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1166 return undef if !$value;
1170 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1171 $res->{pciid
} = $value;
1179 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1185 foreach my $kvp (split(/,/, $data)) {
1187 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1189 my $mac = uc($3) || PVE
::Tools
::random_ether_addr
();
1190 $res->{model
} = $model;
1191 $res->{macaddr
} = $mac;
1192 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1193 $res->{bridge
} = $1;
1194 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1196 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1204 return undef if !$res->{model
};
1212 my $res = "$net->{model}";
1213 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1214 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1215 $res .= ",rate=$net->{rate}" if $net->{rate
};
1216 $res .= ",tag=$net->{tag}" if $net->{tag
};
1221 sub add_random_macs
{
1222 my ($settings) = @_;
1224 foreach my $opt (keys %$settings) {
1225 next if $opt !~ m/^net(\d+)$/;
1226 my $net = parse_net
($settings->{$opt});
1228 $settings->{$opt} = print_net
($net);
1232 sub add_unused_volume
{
1233 my ($config, $volid) = @_;
1236 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1237 my $test = "unused$ind";
1238 if (my $vid = $config->{$test}) {
1239 return if $vid eq $volid; # do not add duplicates
1245 die "To many unused volume - please delete them first.\n" if !$key;
1247 $config->{$key} = $volid;
1252 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1253 sub verify_bootdisk
{
1254 my ($value, $noerr) = @_;
1256 return $value if valid_drivename
($value);
1258 return undef if $noerr;
1260 die "invalid boot disk '$value'\n";
1263 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1265 my ($value, $noerr) = @_;
1267 return $value if parse_net
($value);
1269 return undef if $noerr;
1271 die "unable to parse network options\n";
1274 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1276 my ($value, $noerr) = @_;
1278 return $value if parse_drive
(undef, $value);
1280 return undef if $noerr;
1282 die "unable to parse drive options\n";
1285 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1286 sub verify_hostpci
{
1287 my ($value, $noerr) = @_;
1289 return $value if parse_hostpci
($value);
1291 return undef if $noerr;
1293 die "unable to parse pci id\n";
1296 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1297 sub verify_watchdog
{
1298 my ($value, $noerr) = @_;
1300 return $value if parse_watchdog
($value);
1302 return undef if $noerr;
1304 die "unable to parse watchdog options\n";
1307 sub parse_watchdog
{
1310 return undef if !$value;
1314 foreach my $p (split(/,/, $value)) {
1315 next if $p =~ m/^\s*$/;
1317 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1319 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1320 $res->{action
} = $2;
1329 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1330 sub verify_startup
{
1331 my ($value, $noerr) = @_;
1333 return $value if parse_startup
($value);
1335 return undef if $noerr;
1337 die "unable to parse startup options\n";
1343 return undef if !$value;
1347 foreach my $p (split(/,/, $value)) {
1348 next if $p =~ m/^\s*$/;
1350 if ($p =~ m/^(order=)?(\d+)$/) {
1352 } elsif ($p =~ m/^up=(\d+)$/) {
1354 } elsif ($p =~ m/^down=(\d+)$/) {
1364 sub parse_usb_device
{
1367 return undef if !$value;
1369 my @dl = split(/,/, $value);
1373 foreach my $v (@dl) {
1374 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1376 $res->{vendorid
} = $2;
1377 $res->{productid
} = $4;
1378 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1380 $res->{hostbus
} = $1;
1381 $res->{hostport
} = $2;
1386 return undef if !$found;
1391 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1392 sub verify_usb_device
{
1393 my ($value, $noerr) = @_;
1395 return $value if parse_usb_device
($value);
1397 return undef if $noerr;
1399 die "unable to parse usb device\n";
1402 # add JSON properties for create and set function
1403 sub json_config_properties
{
1406 foreach my $opt (keys %$confdesc) {
1407 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1408 $prop->{$opt} = $confdesc->{$opt};
1415 my ($key, $value) = @_;
1417 die "unknown setting '$key'\n" if !$confdesc->{$key};
1419 my $type = $confdesc->{$key}->{type
};
1421 if (!defined($value)) {
1422 die "got undefined value\n";
1425 if ($value =~ m/[\n\r]/) {
1426 die "property contains a line feed\n";
1429 if ($type eq 'boolean') {
1430 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1431 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1432 die "type check ('boolean') failed - got '$value'\n";
1433 } elsif ($type eq 'integer') {
1434 return int($1) if $value =~ m/^(\d+)$/;
1435 die "type check ('integer') failed - got '$value'\n";
1436 } elsif ($type eq 'string') {
1437 if (my $fmt = $confdesc->{$key}->{format
}) {
1438 if ($fmt eq 'pve-qm-drive') {
1439 # special case - we need to pass $key to parse_drive()
1440 my $drive = parse_drive
($key, $value);
1441 return $value if $drive;
1442 die "unable to parse drive options\n";
1444 PVE
::JSONSchema
::check_format
($fmt, $value);
1447 $value =~ s/^\"(.*)\"$/$1/;
1450 die "internal error"
1454 sub lock_config_full
{
1455 my ($vmid, $timeout, $code, @param) = @_;
1457 my $filename = config_file_lock
($vmid);
1459 my $res = lock_file
($filename, $timeout, $code, @param);
1467 my ($vmid, $code, @param) = @_;
1469 return lock_config_full
($vmid, 10, $code, @param);
1472 sub cfs_config_path
{
1473 my ($vmid, $node) = @_;
1475 $node = $nodename if !$node;
1476 return "nodes/$node/qemu-server/$vmid.conf";
1479 sub check_iommu_support
{
1480 #fixme : need to check IOMMU support
1481 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1489 my ($vmid, $node) = @_;
1491 my $cfspath = cfs_config_path
($vmid, $node);
1492 return "/etc/pve/$cfspath";
1495 sub config_file_lock
{
1498 return "$lock_dir/lock-$vmid.conf";
1504 my $conf = config_file
($vmid);
1505 utime undef, undef, $conf;
1509 my ($storecfg, $vmid, $keep_empty_config) = @_;
1511 my $conffile = config_file
($vmid);
1513 my $conf = load_config
($vmid);
1517 # only remove disks owned by this VM
1518 foreach_drive
($conf, sub {
1519 my ($ds, $drive) = @_;
1521 return if drive_is_cdrom
($drive);
1523 my $volid = $drive->{file
};
1524 return if !$volid || $volid =~ m
|^/|;
1526 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1527 return if !$path || !$owner || ($owner != $vmid);
1529 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1532 if ($keep_empty_config) {
1533 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1538 # also remove unused disk
1540 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1543 PVE
::Storage
::foreach_volid
($dl, sub {
1544 my ($volid, $sid, $volname, $d) = @_;
1545 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1555 my ($vmid, $node) = @_;
1557 my $cfspath = cfs_config_path
($vmid, $node);
1559 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1561 die "no such VM ('$vmid')\n" if !defined($conf);
1566 sub parse_vm_config
{
1567 my ($filename, $raw) = @_;
1569 return undef if !defined($raw);
1572 digest
=> Digest
::SHA
::sha1_hex
($raw),
1576 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1577 || die "got strange filename '$filename'";
1584 my @lines = split(/\n/, $raw);
1585 foreach my $line (@lines) {
1586 next if $line =~ m/^\s*$/;
1588 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1590 $conf->{description
} = $descr if $descr;
1592 $conf = $res->{snapshots
}->{$snapname} = {};
1596 if ($line =~ m/^\#(.*)\s*$/) {
1597 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1601 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1602 $descr .= PVE
::Tools
::decode_text
($2);
1603 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1604 $conf->{snapstate
} = $1;
1605 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1608 $conf->{$key} = $value;
1609 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1612 eval { $value = check_type
($key, $value); };
1614 warn "vm $vmid - unable to parse value of '$key' - $@";
1616 my $fmt = $confdesc->{$key}->{format
};
1617 if ($fmt && $fmt eq 'pve-qm-drive') {
1618 my $v = parse_drive
($key, $value);
1619 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1620 $v->{file
} = $volid;
1621 $value = print_drive
($vmid, $v);
1623 warn "vm $vmid - unable to parse value of '$key'\n";
1628 if ($key eq 'cdrom') {
1629 $conf->{ide2
} = $value;
1631 $conf->{$key} = $value;
1637 $conf->{description
} = $descr if $descr;
1639 delete $res->{snapstate
}; # just to be sure
1644 sub write_vm_config
{
1645 my ($filename, $conf) = @_;
1647 delete $conf->{snapstate
}; # just to be sure
1649 if ($conf->{cdrom
}) {
1650 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1651 $conf->{ide2
} = $conf->{cdrom
};
1652 delete $conf->{cdrom
};
1655 # we do not use 'smp' any longer
1656 if ($conf->{sockets
}) {
1657 delete $conf->{smp
};
1658 } elsif ($conf->{smp
}) {
1659 $conf->{sockets
} = $conf->{smp
};
1660 delete $conf->{cores
};
1661 delete $conf->{smp
};
1664 my $used_volids = {};
1666 my $cleanup_config = sub {
1669 foreach my $key (keys %$cref) {
1670 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1671 $key eq 'snapstate';
1672 my $value = $cref->{$key};
1673 eval { $value = check_type
($key, $value); };
1674 die "unable to parse value of '$key' - $@" if $@;
1676 $cref->{$key} = $value;
1678 if (valid_drivename
($key)) {
1679 my $drive = PVE
::QemuServer
::parse_drive
($key, $value);
1680 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1685 &$cleanup_config($conf);
1686 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1687 &$cleanup_config($conf->{snapshots
}->{$snapname});
1690 # remove 'unusedX' settings if we re-add a volume
1691 foreach my $key (keys %$conf) {
1692 my $value = $conf->{$key};
1693 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1694 delete $conf->{$key};
1698 my $generate_raw_config = sub {
1703 # add description as comment to top of file
1704 my $descr = $conf->{description
} || '';
1705 foreach my $cl (split(/\n/, $descr)) {
1706 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1709 foreach my $key (sort keys %$conf) {
1710 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1711 $raw .= "$key: $conf->{$key}\n";
1716 my $raw = &$generate_raw_config($conf);
1717 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1718 $raw .= "\n[$snapname]\n";
1719 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1725 sub update_config_nolock
{
1726 my ($vmid, $conf, $skiplock) = @_;
1728 check_lock
($conf) if !$skiplock;
1730 my $cfspath = cfs_config_path
($vmid);
1732 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1736 my ($vmid, $conf, $skiplock) = @_;
1738 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1745 # we use static defaults from our JSON schema configuration
1746 foreach my $key (keys %$confdesc) {
1747 if (defined(my $default = $confdesc->{$key}->{default})) {
1748 $res->{$key} = $default;
1752 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1753 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1759 my $vmlist = PVE
::Cluster
::get_vmlist
();
1761 return $res if !$vmlist || !$vmlist->{ids
};
1762 my $ids = $vmlist->{ids
};
1764 foreach my $vmid (keys %$ids) {
1765 my $d = $ids->{$vmid};
1766 next if !$d->{node
} || $d->{node
} ne $nodename;
1767 next if !$d->{type
} || $d->{type
} ne 'qemu';
1768 $res->{$vmid}->{exists} = 1;
1773 # test if VM uses local resources (to prevent migration)
1774 sub check_local_resources
{
1775 my ($conf, $noerr) = @_;
1779 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1780 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1782 foreach my $k (keys %$conf) {
1783 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1786 die "VM uses local resources\n" if $loc_res && !$noerr;
1791 # check is used storages are available on all nodes (use by migrate)
1792 sub check_storage_availability
{
1793 my ($storecfg, $conf, $node) = @_;
1795 foreach_drive
($conf, sub {
1796 my ($ds, $drive) = @_;
1798 my $volid = $drive->{file
};
1801 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1804 # check if storage is available on both nodes
1805 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1806 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1813 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1817 my ($pidfile, $pid) = @_;
1819 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1823 return undef if !$line;
1824 my @param = split(/\0/, $line);
1826 my $cmd = $param[0];
1827 return if !$cmd || ($cmd !~ m
|kvm
$|);
1829 for (my $i = 0; $i < scalar (@param); $i++) {
1832 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1833 my $p = $param[$i+1];
1834 return 1 if $p && ($p eq $pidfile);
1843 my ($vmid, $nocheck, $node) = @_;
1845 my $filename = config_file
($vmid, $node);
1847 die "unable to find configuration file for VM $vmid - no such machine\n"
1848 if !$nocheck && ! -f
$filename;
1850 my $pidfile = pidfile_name
($vmid);
1852 if (my $fd = IO
::File-
>new("<$pidfile")) {
1857 my $mtime = $st->mtime;
1858 if ($mtime > time()) {
1859 warn "file '$filename' modified in future\n";
1862 if ($line =~ m/^(\d+)$/) {
1864 if (check_cmdline
($pidfile, $pid)) {
1865 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1877 my $vzlist = config_list
();
1879 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1881 while (defined(my $de = $fd->read)) {
1882 next if $de !~ m/^(\d+)\.pid$/;
1884 next if !defined($vzlist->{$vmid});
1885 if (my $pid = check_running
($vmid)) {
1886 $vzlist->{$vmid}->{pid
} = $pid;
1894 my ($storecfg, $conf) = @_;
1896 my $bootdisk = $conf->{bootdisk
};
1897 return undef if !$bootdisk;
1898 return undef if !valid_drivename
($bootdisk);
1900 return undef if !$conf->{$bootdisk};
1902 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1903 return undef if !defined($drive);
1905 return undef if drive_is_cdrom
($drive);
1907 my $volid = $drive->{file
};
1908 return undef if !$volid;
1910 return $drive->{size
};
1913 my $last_proc_pid_stat;
1915 # get VM status information
1916 # This must be fast and should not block ($full == false)
1917 # We only query KVM using QMP if $full == true (this can be slow)
1919 my ($opt_vmid, $full) = @_;
1923 my $storecfg = PVE
::Storage
::config
();
1925 my $list = vzlist
();
1926 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
1928 my $cpucount = $cpuinfo->{cpus
} || 1;
1930 foreach my $vmid (keys %$list) {
1931 next if $opt_vmid && ($vmid ne $opt_vmid);
1933 my $cfspath = cfs_config_path
($vmid);
1934 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
1937 $d->{pid
} = $list->{$vmid}->{pid
};
1939 # fixme: better status?
1940 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
1942 my $size = disksize
($storecfg, $conf);
1943 if (defined($size)) {
1944 $d->{disk
} = 0; # no info available
1945 $d->{maxdisk
} = $size;
1951 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
1952 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
1954 $d->{name
} = $conf->{name
} || "VM $vmid";
1955 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
1965 $d->{diskwrite
} = 0;
1970 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
1971 foreach my $dev (keys %$netdev) {
1972 next if $dev !~ m/^tap([1-9]\d*)i/;
1974 my $d = $res->{$vmid};
1977 $d->{netout
} += $netdev->{$dev}->{receive
};
1978 $d->{netin
} += $netdev->{$dev}->{transmit
};
1981 my $ctime = gettimeofday
;
1983 foreach my $vmid (keys %$list) {
1985 my $d = $res->{$vmid};
1986 my $pid = $d->{pid
};
1989 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
1990 next if !$pstat; # not running
1992 my $used = $pstat->{utime} + $pstat->{stime
};
1994 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
1996 if ($pstat->{vsize
}) {
1997 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2000 my $old = $last_proc_pid_stat->{$pid};
2002 $last_proc_pid_stat->{$pid} = {
2010 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2012 if ($dtime > 1000) {
2013 my $dutime = $used - $old->{used
};
2015 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2016 $last_proc_pid_stat->{$pid} = {
2022 $d->{cpu
} = $old->{cpu
};
2026 return $res if !$full;
2028 my $qmpclient = PVE
::QMPClient-
>new();
2030 my $blockstatscb = sub {
2031 my ($vmid, $resp) = @_;
2032 my $data = $resp->{'return'} || [];
2033 my $totalrdbytes = 0;
2034 my $totalwrbytes = 0;
2035 for my $blockstat (@$data) {
2036 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2037 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2039 $res->{$vmid}->{diskread
} = $totalrdbytes;
2040 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2043 my $statuscb = sub {
2044 my ($vmid, $resp) = @_;
2045 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2047 my $status = 'unknown';
2048 if (!defined($status = $resp->{'return'}->{status
})) {
2049 warn "unable to get VM status\n";
2053 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2056 foreach my $vmid (keys %$list) {
2057 next if $opt_vmid && ($vmid ne $opt_vmid);
2058 next if !$res->{$vmid}->{pid
}; # not running
2059 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2062 $qmpclient->queue_execute();
2064 foreach my $vmid (keys %$list) {
2065 next if $opt_vmid && ($vmid ne $opt_vmid);
2066 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2073 my ($conf, $func) = @_;
2075 foreach my $ds (keys %$conf) {
2076 next if !valid_drivename
($ds);
2078 my $drive = parse_drive
($ds, $conf->{$ds});
2081 &$func($ds, $drive);
2086 my ($conf, $func) = @_;
2090 my $test_volid = sub {
2091 my ($volid, $is_cdrom) = @_;
2095 $volhash->{$volid} = $is_cdrom || 0;
2098 PVE
::QemuServer
::foreach_drive
($conf, sub {
2099 my ($ds, $drive) = @_;
2100 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2103 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2104 my $snap = $conf->{snapshots
}->{$snapname};
2105 &$test_volid($snap->{vmstate
}, 0);
2106 PVE
::QemuServer
::foreach_drive
($snap, sub {
2107 my ($ds, $drive) = @_;
2108 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2112 foreach my $volid (keys %$volhash) {
2113 &$func($volid, $volhash->{$volid});
2117 sub config_to_command
{
2118 my ($storecfg, $vmid, $conf, $defaults) = @_;
2121 my $globalFlags = [];
2122 my $machineFlags = [];
2127 my $kvmver = kvm_user_version
();
2128 my $vernum = 0; # unknown
2129 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2130 $vernum = $1*1000000+$2*1000;
2131 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2132 $vernum = $1*1000000+$2*1000+$3;
2135 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2137 my $have_ovz = -f
'/proc/vz/vestat';
2139 push @$cmd, '/usr/bin/kvm';
2141 push @$cmd, '-id', $vmid;
2145 my $qmpsocket = qmp_socket
($vmid);
2146 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2147 push @$cmd, '-mon', "chardev=qmp,mode=control";
2149 my $socket = vnc_socket
($vmid);
2150 push @$cmd, '-vnc', "unix:$socket,x509,password";
2152 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2154 push @$cmd, '-daemonize';
2157 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2158 next if !$conf->{"usb$i"};
2161 # include usb device config
2162 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2164 # enable absolute mouse coordinates (needed by vnc)
2165 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2168 push @$devices, '-device', 'usb-tablet,bus=ehci.0,port=6';
2170 push @$devices, '-usbdevice', 'tablet';
2175 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2176 my $d = parse_hostpci
($conf->{"hostpci$i"});
2178 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2179 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2183 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2184 my $d = parse_usb_device
($conf->{"usb$i"});
2186 if ($d->{vendorid
} && $d->{productid
}) {
2187 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2188 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2189 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2194 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2195 if (my $path = $conf->{"serial$i"}) {
2196 die "no such serial device\n" if ! -c
$path;
2197 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2198 push @$devices, '-device', "isa-serial,chardev=serial$i";
2203 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2204 if (my $path = $conf->{"parallel$i"}) {
2205 die "no such parallel device\n" if ! -c
$path;
2206 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2207 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2211 my $vmname = $conf->{name
} || "vm$vmid";
2213 push @$cmd, '-name', $vmname;
2216 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2217 $sockets = $conf->{sockets
} if $conf->{sockets
};
2219 my $cores = $conf->{cores
} || 1;
2221 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2223 push @$cmd, '-cpu', $conf->{cpu
} if $conf->{cpu
};
2225 push @$cmd, '-nodefaults';
2227 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2229 my $bootindex_hash = {};
2231 foreach my $o (split(//, $bootorder)) {
2232 $bootindex_hash->{$o} = $i*100;
2236 push @$cmd, '-boot', "menu=on";
2238 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2240 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2242 my $vga = $conf->{vga
};
2244 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' || $conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2251 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2254 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2256 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2257 my $useLocaltime = $conf->{localtime};
2259 if (my $ost = $conf->{ostype
}) {
2260 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2262 if ($ost =~ m/^w/) { # windows
2263 $useLocaltime = 1 if !defined($conf->{localtime});
2265 # use time drift fix when acpi is enabled
2266 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2267 $tdf = 1 if !defined($conf->{tdf
});
2271 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2273 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2274 push @$cmd, '-no-hpet';
2278 push @$rtcFlags, 'driftfix=slew' if $tdf;
2281 push @$machineFlags, 'accel=tcg';
2283 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2286 if ($conf->{startdate
}) {
2287 push @$rtcFlags, "base=$conf->{startdate}";
2288 } elsif ($useLocaltime) {
2289 push @$rtcFlags, 'base=localtime';
2292 push @$cmd, '-S' if $conf->{freeze
};
2294 # set keyboard layout
2295 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2296 push @$cmd, '-k', $kb if $kb;
2299 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2300 #push @$cmd, '-soundhw', 'es1370';
2301 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2303 if($conf->{agent
}) {
2304 my $qgasocket = qga_socket
($vmid);
2305 my $pciaddr = print_pci_addr
("qga0", $bridges);
2306 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2307 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2308 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2311 $pciaddr = print_pci_addr
("balloon0", $bridges);
2312 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon
};
2314 if ($conf->{watchdog
}) {
2315 my $wdopts = parse_watchdog
($conf->{watchdog
});
2316 $pciaddr = print_pci_addr
("watchdog", $bridges);
2317 my $watchdog = $wdopts->{model
} || 'i6300esb';
2318 push @$devices, '-device', "$watchdog$pciaddr";
2319 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2323 my $scsicontroller = {};
2324 my $ahcicontroller = {};
2325 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2327 foreach_drive
($conf, sub {
2328 my ($ds, $drive) = @_;
2330 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2331 push @$vollist, $drive->{file
};
2334 $use_virtio = 1 if $ds =~ m/^virtio/;
2336 if (drive_is_cdrom
($drive)) {
2337 if ($bootindex_hash->{d
}) {
2338 $drive->{bootindex
} = $bootindex_hash->{d
};
2339 $bootindex_hash->{d
} += 1;
2342 if ($bootindex_hash->{c
}) {
2343 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2344 $bootindex_hash->{c
} += 1;
2348 if ($drive->{interface
} eq 'scsi') {
2350 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2351 my $controller = int($drive->{index} / $maxdev);
2352 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2353 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2354 $scsicontroller->{$controller}=1;
2357 if ($drive->{interface
} eq 'sata') {
2358 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2359 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2360 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2361 $ahcicontroller->{$controller}=1;
2364 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2365 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2368 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2370 for (my $i = 0; $i < $MAX_NETS; $i++) {
2371 next if !$conf->{"net$i"};
2372 my $d = parse_net
($conf->{"net$i"});
2375 $use_virtio = 1 if $d->{model
} eq 'virtio';
2377 if ($bootindex_hash->{n
}) {
2378 $d->{bootindex
} = $bootindex_hash->{n
};
2379 $bootindex_hash->{n
} += 1;
2382 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2383 push @$devices, '-netdev', $netdevfull;
2385 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2386 push @$devices, '-device', $netdevicefull;
2390 while (my ($k, $v) = each %$bridges) {
2391 $pciaddr = print_pci_addr
("pci.$k");
2392 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2396 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2397 # when the VM uses virtio devices.
2398 if (!$use_virtio && $have_ovz) {
2400 my $cpuunits = defined($conf->{cpuunits
}) ?
2401 $conf->{cpuunits
} : $defaults->{cpuunits
};
2403 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2405 # fixme: cpulimit is currently ignored
2406 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2410 if ($conf->{args
}) {
2411 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2415 push @$cmd, @$devices;
2416 push @$cmd, '-rtc', join(',', @$rtcFlags)
2417 if scalar(@$rtcFlags);
2418 push @$cmd, '-machine', join(',', @$machineFlags)
2419 if scalar(@$machineFlags);
2420 push @$cmd, '-global', join(',', @$globalFlags)
2421 if scalar(@$globalFlags);
2423 return wantarray ?
($cmd, $vollist) : $cmd;
2428 return "${var_run_tmpdir}/$vmid.vnc";
2433 return "${var_run_tmpdir}/$vmid.qmp";
2438 return "${var_run_tmpdir}/$vmid.qga";
2443 return "${var_run_tmpdir}/$vmid.pid";
2446 sub next_migrate_port
{
2448 for (my $p = 60000; $p < 60010; $p++) {
2450 my $sock = IO
::Socket
::INET-
>new(Listen
=> 5,
2451 LocalAddr
=> 'localhost',
2462 die "unable to find free migration port";
2465 sub vm_devices_list
{
2468 my $res = vm_mon_cmd
($vmid, 'query-pci');
2471 foreach my $pcibus (@$res) {
2472 foreach my $device (@{$pcibus->{devices
}}) {
2473 next if !$device->{'qdev_id'};
2474 $devices->{$device->{'qdev_id'}} = $device;
2482 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2484 return 1 if !check_running
($vmid) || !$conf->{hotplug
};
2486 my $devices_list = vm_devices_list
($vmid);
2487 return 1 if defined($devices_list->{$deviceid});
2489 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2491 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2492 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2493 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2494 qemu_deviceadd
($vmid, $devicefull);
2495 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2496 qemu_drivedel
($vmid, $deviceid);
2501 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2502 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2503 my $pciaddr = print_pci_addr
($deviceid);
2504 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2505 qemu_deviceadd
($vmid, $devicefull);
2506 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2509 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2510 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2511 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2512 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2513 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2514 if(!qemu_deviceadd
($vmid, $devicefull)) {
2515 qemu_drivedel
($vmid, $deviceid);
2520 if ($deviceid =~ m/^(net)(\d+)$/) {
2521 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2522 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2523 qemu_deviceadd
($vmid, $netdevicefull);
2524 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2525 qemu_netdevdel
($vmid, $deviceid);
2530 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2532 my $pciaddr = print_pci_addr
($deviceid);
2533 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2534 qemu_deviceadd
($vmid, $devicefull);
2535 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2541 sub vm_deviceunplug
{
2542 my ($vmid, $conf, $deviceid) = @_;
2544 return 1 if !check_running
($vmid) || !$conf->{hotplug
};
2546 my $devices_list = vm_devices_list
($vmid);
2547 return 1 if !defined($devices_list->{$deviceid});
2549 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2551 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2552 return undef if !qemu_drivedel
($vmid, $deviceid);
2553 qemu_devicedel
($vmid, $deviceid);
2554 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2557 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2558 return undef if !qemu_devicedel
($vmid, $deviceid);
2561 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2562 return undef if !qemu_devicedel
($vmid, $deviceid);
2563 return undef if !qemu_drivedel
($vmid, $deviceid);
2566 if ($deviceid =~ m/^(net)(\d+)$/) {
2567 return undef if !qemu_netdevdel
($vmid, $deviceid);
2568 qemu_devicedel
($vmid, $deviceid);
2569 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2575 sub qemu_deviceadd
{
2576 my ($vmid, $devicefull) = @_;
2578 my $ret = vm_human_monitor_command
($vmid, "device_add $devicefull");
2580 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2581 return 1 if $ret eq "";
2582 syslog
("err", "error on hotplug device : $ret");
2587 sub qemu_devicedel
{
2588 my($vmid, $deviceid) = @_;
2590 my $ret = vm_human_monitor_command
($vmid, "device_del $deviceid");
2592 return 1 if $ret eq "";
2593 syslog
("err", "detaching device $deviceid failed : $ret");
2598 my($storecfg, $vmid, $device) = @_;
2600 my $drive = print_drive_full
($storecfg, $vmid, $device);
2601 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2602 # If the command succeeds qemu prints: "OK"
2603 if ($ret !~ m/OK/s) {
2604 syslog
("err", "adding drive failed: $ret");
2611 my($vmid, $deviceid) = @_;
2613 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2615 if ($ret =~ m/Device \'.*?\' not found/s) {
2616 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2618 elsif ($ret ne "") {
2619 syslog
("err", "deleting drive $deviceid failed : $ret");
2625 sub qemu_deviceaddverify
{
2626 my ($vmid,$deviceid) = @_;
2628 for (my $i = 0; $i <= 5; $i++) {
2629 my $devices_list = vm_devices_list
($vmid);
2630 return 1 if defined($devices_list->{$deviceid});
2633 syslog
("err", "error on hotplug device $deviceid");
2638 sub qemu_devicedelverify
{
2639 my ($vmid,$deviceid) = @_;
2641 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2642 for (my $i = 0; $i <= 5; $i++) {
2643 my $devices_list = vm_devices_list
($vmid);
2644 return 1 if !defined($devices_list->{$deviceid});
2647 syslog
("err", "error on hot-unplugging device $deviceid");
2651 sub qemu_findorcreatescsihw
{
2652 my ($storecfg, $conf, $vmid, $device) = @_;
2654 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2655 my $controller = int($device->{index} / $maxdev);
2656 my $scsihwid="scsihw$controller";
2657 my $devices_list = vm_devices_list
($vmid);
2659 if(!defined($devices_list->{$scsihwid})) {
2660 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2665 sub qemu_bridgeadd
{
2666 my ($storecfg, $conf, $vmid, $device) = @_;
2669 my $bridgeid = undef;
2670 print_pci_addr
($device, $bridges);
2672 while (my ($k, $v) = each %$bridges) {
2675 return if $bridgeid < 1;
2676 my $bridge = "pci.$bridgeid";
2677 my $devices_list = vm_devices_list
($vmid);
2679 if(!defined($devices_list->{$bridge})) {
2680 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2685 sub qemu_netdevadd
{
2686 my ($vmid, $conf, $device, $deviceid) = @_;
2688 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2689 my $ret = vm_human_monitor_command
($vmid, "netdev_add $netdev");
2692 #if the command succeeds, no output is sent. So any non-empty string shows an error
2693 return 1 if $ret eq "";
2694 syslog
("err", "adding netdev failed: $ret");
2698 sub qemu_netdevdel
{
2699 my ($vmid, $deviceid) = @_;
2701 my $ret = vm_human_monitor_command
($vmid, "netdev_del $deviceid");
2703 #if the command succeeds, no output is sent. So any non-empty string shows an error
2704 return 1 if $ret eq "";
2705 syslog
("err", "deleting netdev failed: $ret");
2709 sub qemu_block_set_io_throttle
{
2710 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2712 return if !check_running
($vmid) ;
2715 $bps_rd = 0 if !$bps_rd;
2716 $bps_wr = 0 if !$bps_wr;
2717 $iops = 0 if !$iops;
2718 $iops_rd = 0 if !$iops_rd;
2719 $iops_wr = 0 if !$iops_wr;
2721 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));
2725 # old code, only used to shutdown old VM after update
2727 my ($fh, $timeout) = @_;
2729 my $sel = new IO
::Select
;
2736 while (scalar (@ready = $sel->can_read($timeout))) {
2738 if ($count = $fh->sysread($buf, 8192)) {
2739 if ($buf =~ /^(.*)\(qemu\) $/s) {
2746 if (!defined($count)) {
2753 die "monitor read timeout\n" if !scalar(@ready);
2758 # old code, only used to shutdown old VM after update
2759 sub vm_monitor_command
{
2760 my ($vmid, $cmdstr, $nocheck) = @_;
2765 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2767 my $sname = "${var_run_tmpdir}/$vmid.mon";
2769 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2770 die "unable to connect to VM $vmid socket - $!\n";
2774 # hack: migrate sometime blocks the monitor (when migrate_downtime
2776 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2777 $timeout = 60*60; # 1 hour
2781 my $data = __read_avail
($sock, $timeout);
2783 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2784 die "got unexpected qemu monitor banner\n";
2787 my $sel = new IO
::Select
;
2790 if (!scalar(my @ready = $sel->can_write($timeout))) {
2791 die "monitor write error - timeout";
2794 my $fullcmd = "$cmdstr\r";
2796 # syslog('info', "VM $vmid monitor command: $cmdstr");
2799 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2800 die "monitor write error - $!";
2803 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2807 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2808 $timeout = 60*60; # 1 hour
2809 } elsif ($cmdstr =~ m/^(eject|change)/) {
2810 $timeout = 60; # note: cdrom mount command is slow
2812 if ($res = __read_avail
($sock, $timeout)) {
2814 my @lines = split("\r?\n", $res);
2816 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2818 $res = join("\n", @lines);
2826 syslog
("err", "VM $vmid monitor command failed - $err");
2833 sub qemu_block_resize
{
2834 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2836 my $running = PVE
::QemuServer
::check_running
($vmid);
2838 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2840 return if !$running;
2842 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2846 sub qemu_volume_snapshot
{
2847 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2849 my $running = PVE
::QemuServer
::check_running
($vmid);
2851 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2853 return if !$running;
2855 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2859 sub qemu_volume_snapshot_delete
{
2860 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2862 my $running = PVE
::QemuServer
::check_running
($vmid);
2864 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2866 return if !$running;
2868 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
2874 #need to impplement call to qemu-ga
2877 sub qga_unfreezefs
{
2880 #need to impplement call to qemu-ga
2884 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused) = @_;
2886 lock_config
($vmid, sub {
2887 my $conf = load_config
($vmid, $migratedfrom);
2889 check_lock
($conf) if !$skiplock;
2891 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
2893 my $defaults = load_defaults
();
2895 # set environment variable useful inside network script
2896 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
2898 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults);
2900 my $migrate_port = 0;
2903 if ($statefile eq 'tcp') {
2904 $migrate_port = next_migrate_port
();
2905 my $migrate_uri = "tcp:localhost:${migrate_port}";
2906 push @$cmd, '-incoming', $migrate_uri;
2909 push @$cmd, '-loadstate', $statefile;
2916 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2917 my $d = parse_hostpci
($conf->{"hostpci$i"});
2919 my $info = pci_device_info
("0000:$d->{pciid}");
2920 die "IOMMU not present\n" if !check_iommu_support
();
2921 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2922 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
2923 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
2926 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
2928 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
2931 die "start failed: $err" if $err;
2933 print "migration listens on port $migrate_port\n" if $migrate_port;
2935 if ($statefile && $statefile ne 'tcp') {
2936 eval { vm_mon_cmd
($vmid, "cont"); };
2940 # always set migrate speed (overwrite kvm default of 32m)
2941 # we set a very hight default of 8192m which is basically unlimited
2942 my $migrate_speed = $defaults->{migrate_speed
} || 8192;
2943 $migrate_speed = $conf->{migrate_speed
} || $migrate_speed;
2944 $migrate_speed = $migrate_speed * 1048576;
2946 vm_mon_cmd
($vmid, "migrate_set_speed", value
=> $migrate_speed);
2949 my $migrate_downtime = $defaults->{migrate_downtime
};
2950 $migrate_downtime = $conf->{migrate_downtime
} if defined($conf->{migrate_downtime
});
2951 if (defined($migrate_downtime)) {
2952 eval { vm_mon_cmd
($vmid, "migrate_set_downtime", value
=> $migrate_downtime); };
2956 my $capabilities = {};
2957 $capabilities->{capability
} = "xbzrle";
2958 $capabilities->{state} = JSON
::true
;
2959 eval { PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
2962 vm_balloonset
($vmid, $conf->{balloon
}) if $conf->{balloon
};
2968 my ($vmid, $execute, %params) = @_;
2970 my $cmd = { execute
=> $execute, arguments
=> \
%params };
2971 vm_qmp_command
($vmid, $cmd);
2974 sub vm_mon_cmd_nocheck
{
2975 my ($vmid, $execute, %params) = @_;
2977 my $cmd = { execute
=> $execute, arguments
=> \
%params };
2978 vm_qmp_command
($vmid, $cmd, 1);
2981 sub vm_qmp_command
{
2982 my ($vmid, $cmd, $nocheck) = @_;
2987 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
2988 $timeout = $cmd->{arguments
}->{timeout
};
2989 delete $cmd->{arguments
}->{timeout
};
2993 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2994 my $sname = PVE
::QemuServer
::qmp_socket
($vmid);
2996 my $qmpclient = PVE
::QMPClient-
>new();
2998 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
2999 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3000 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3001 if scalar(%{$cmd->{arguments
}});
3002 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3004 die "unable to open monitor socket\n";
3008 syslog
("err", "VM $vmid qmp command failed - $err");
3015 sub vm_human_monitor_command
{
3016 my ($vmid, $cmdline) = @_;
3021 execute
=> 'human-monitor-command',
3022 arguments
=> { 'command-line' => $cmdline},
3025 return vm_qmp_command
($vmid, $cmd);
3028 sub vm_commandline
{
3029 my ($storecfg, $vmid) = @_;
3031 my $conf = load_config
($vmid);
3033 my $defaults = load_defaults
();
3035 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3037 return join(' ', @$cmd);
3041 my ($vmid, $skiplock) = @_;
3043 lock_config
($vmid, sub {
3045 my $conf = load_config
($vmid);
3047 check_lock
($conf) if !$skiplock;
3049 vm_mon_cmd
($vmid, "system_reset");
3053 sub get_vm_volumes
{
3057 foreach_volid
($conf, sub {
3058 my ($volid, $is_cdrom) = @_;
3060 return if $volid =~ m
|^/|;
3062 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3065 push @$vollist, $volid;
3071 sub vm_stop_cleanup
{
3072 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3075 fairsched_rmnod
($vmid); # try to destroy group
3078 my $vollist = get_vm_volumes
($conf);
3079 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3082 foreach my $ext (qw(mon qmp pid vnc qga)) {
3083 unlink "/var/run/qemu-server/${vmid}.$ext";
3086 warn $@ if $@; # avoid errors - just warn
3089 # Note: use $nockeck to skip tests if VM configuration file exists.
3090 # We need that when migration VMs to other nodes (files already moved)
3091 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3093 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3095 $force = 1 if !defined($force) && !$shutdown;
3098 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3099 kill 15, $pid if $pid;
3100 my $conf = load_config
($vmid, $migratedfrom);
3101 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3105 lock_config
($vmid, sub {
3107 my $pid = check_running
($vmid, $nocheck);
3112 $conf = load_config
($vmid);
3113 check_lock
($conf) if !$skiplock;
3114 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3115 my $opts = parse_startup
($conf->{startup
});
3116 $timeout = $opts->{down
} if $opts->{down
};
3120 $timeout = 60 if !defined($timeout);
3124 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3127 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3134 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3139 if ($count >= $timeout) {
3141 warn "VM still running - terminating now with SIGTERM\n";
3144 die "VM quit/powerdown failed - got timeout\n";
3147 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3152 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3155 die "VM quit/powerdown failed\n";
3163 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3168 if ($count >= $timeout) {
3169 warn "VM still running - terminating now with SIGKILL\n";
3174 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3179 my ($vmid, $skiplock) = @_;
3181 lock_config
($vmid, sub {
3183 my $conf = load_config
($vmid);
3185 check_lock
($conf) if !$skiplock;
3187 vm_mon_cmd
($vmid, "stop");
3192 my ($vmid, $skiplock) = @_;
3194 lock_config
($vmid, sub {
3196 my $conf = load_config
($vmid);
3198 check_lock
($conf) if !$skiplock;
3200 vm_mon_cmd
($vmid, "cont");
3205 my ($vmid, $skiplock, $key) = @_;
3207 lock_config
($vmid, sub {
3209 my $conf = load_config
($vmid);
3211 # there is no qmp command, so we use the human monitor command
3212 vm_human_monitor_command
($vmid, "sendkey $key");
3217 my ($storecfg, $vmid, $skiplock) = @_;
3219 lock_config
($vmid, sub {
3221 my $conf = load_config
($vmid);
3223 check_lock
($conf) if !$skiplock;
3225 if (!check_running
($vmid)) {
3226 fairsched_rmnod
($vmid); # try to destroy group
3227 destroy_vm
($storecfg, $vmid);
3229 die "VM $vmid is running - destroy failed\n";
3237 my ($filename, $buf) = @_;
3239 my $fh = IO
::File-
>new($filename, "w");
3240 return undef if !$fh;
3242 my $res = print $fh $buf;
3249 sub pci_device_info
{
3254 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3255 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3257 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3258 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3260 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3261 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3263 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3264 return undef if !defined($product) || $product !~ s/^0x//;
3269 product
=> $product,
3275 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3284 my $name = $dev->{name
};
3286 my $fn = "$pcisysfs/devices/$name/reset";
3288 return file_write
($fn, "1");
3291 sub pci_dev_bind_to_stub
{
3294 my $name = $dev->{name
};
3296 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3297 return 1 if -d
$testdir;
3299 my $data = "$dev->{vendor} $dev->{product}";
3300 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3302 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3303 if (!file_write
($fn, $name)) {
3304 return undef if -f
$fn;
3307 $fn = "$pcisysfs/drivers/pci-stub/bind";
3308 if (! -d
$testdir) {
3309 return undef if !file_write
($fn, $name);
3315 sub print_pci_addr
{
3316 my ($id, $bridges) = @_;
3320 #addr1 : ide,parallel,serial (motherboard)
3321 #addr2 : first videocard
3322 balloon0
=> { bus
=> 0, addr
=> 3 },
3323 watchdog
=> { bus
=> 0, addr
=> 4 },
3324 scsihw0
=> { bus
=> 0, addr
=> 5 },
3325 scsihw1
=> { bus
=> 0, addr
=> 6 },
3326 ahci0
=> { bus
=> 0, addr
=> 7 },
3327 qga0
=> { bus
=> 0, addr
=> 8 },
3328 virtio0
=> { bus
=> 0, addr
=> 10 },
3329 virtio1
=> { bus
=> 0, addr
=> 11 },
3330 virtio2
=> { bus
=> 0, addr
=> 12 },
3331 virtio3
=> { bus
=> 0, addr
=> 13 },
3332 virtio4
=> { bus
=> 0, addr
=> 14 },
3333 virtio5
=> { bus
=> 0, addr
=> 15 },
3334 hostpci0
=> { bus
=> 0, addr
=> 16 },
3335 hostpci1
=> { bus
=> 0, addr
=> 17 },
3336 net0
=> { bus
=> 0, addr
=> 18 },
3337 net1
=> { bus
=> 0, addr
=> 19 },
3338 net2
=> { bus
=> 0, addr
=> 20 },
3339 net3
=> { bus
=> 0, addr
=> 21 },
3340 net4
=> { bus
=> 0, addr
=> 22 },
3341 net5
=> { bus
=> 0, addr
=> 23 },
3342 #addr29 : usb-host (pve-usb.cfg)
3343 'pci.1' => { bus
=> 0, addr
=> 30 },
3344 'pci.2' => { bus
=> 0, addr
=> 31 },
3345 'net6' => { bus
=> 1, addr
=> 1 },
3346 'net7' => { bus
=> 1, addr
=> 2 },
3347 'net8' => { bus
=> 1, addr
=> 3 },
3348 'net9' => { bus
=> 1, addr
=> 4 },
3349 'net10' => { bus
=> 1, addr
=> 5 },
3350 'net11' => { bus
=> 1, addr
=> 6 },
3351 'net12' => { bus
=> 1, addr
=> 7 },
3352 'net13' => { bus
=> 1, addr
=> 8 },
3353 'net14' => { bus
=> 1, addr
=> 9 },
3354 'net15' => { bus
=> 1, addr
=> 10 },
3355 'net16' => { bus
=> 1, addr
=> 11 },
3356 'net17' => { bus
=> 1, addr
=> 12 },
3357 'net18' => { bus
=> 1, addr
=> 13 },
3358 'net19' => { bus
=> 1, addr
=> 14 },
3359 'net20' => { bus
=> 1, addr
=> 15 },
3360 'net21' => { bus
=> 1, addr
=> 16 },
3361 'net22' => { bus
=> 1, addr
=> 17 },
3362 'net23' => { bus
=> 1, addr
=> 18 },
3363 'net24' => { bus
=> 1, addr
=> 19 },
3364 'net25' => { bus
=> 1, addr
=> 20 },
3365 'net26' => { bus
=> 1, addr
=> 21 },
3366 'net27' => { bus
=> 1, addr
=> 22 },
3367 'net28' => { bus
=> 1, addr
=> 23 },
3368 'net29' => { bus
=> 1, addr
=> 24 },
3369 'net30' => { bus
=> 1, addr
=> 25 },
3370 'net31' => { bus
=> 1, addr
=> 26 },
3371 'virtio6' => { bus
=> 2, addr
=> 1 },
3372 'virtio7' => { bus
=> 2, addr
=> 2 },
3373 'virtio8' => { bus
=> 2, addr
=> 3 },
3374 'virtio9' => { bus
=> 2, addr
=> 4 },
3375 'virtio10' => { bus
=> 2, addr
=> 5 },
3376 'virtio11' => { bus
=> 2, addr
=> 6 },
3377 'virtio12' => { bus
=> 2, addr
=> 7 },
3378 'virtio13' => { bus
=> 2, addr
=> 8 },
3379 'virtio14' => { bus
=> 2, addr
=> 9 },
3380 'virtio15' => { bus
=> 2, addr
=> 10 },
3383 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3384 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3385 my $bus = $devices->{$id}->{bus
};
3386 $res = ",bus=pci.$bus,addr=$addr";
3387 $bridges->{$bus} = 1 if $bridges;
3394 my ($vmid, $value) = @_;
3396 vm_mon_cmd
($vmid, "balloon", value
=> $value*1024*1024);
3399 # vzdump restore implementaion
3401 sub archive_read_firstfile
{
3402 my $archive = shift;
3404 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3406 # try to detect archive type first
3407 my $pid = open (TMP
, "tar tf '$archive'|") ||
3408 die "unable to open file '$archive'\n";
3409 my $firstfile = <TMP
>;
3413 die "ERROR: archive contaions no data\n" if !$firstfile;
3419 sub restore_cleanup
{
3420 my $statfile = shift;
3422 print STDERR
"starting cleanup\n";
3424 if (my $fd = IO
::File-
>new($statfile, "r")) {
3425 while (defined(my $line = <$fd>)) {
3426 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3429 if ($volid =~ m
|^/|) {
3430 unlink $volid || die 'unlink failed\n';
3432 my $cfg = cfs_read_file
('storage.cfg');
3433 PVE
::Storage
::vdisk_free
($cfg, $volid);
3435 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3437 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3439 print STDERR
"unable to parse line in statfile - $line";
3446 sub restore_archive
{
3447 my ($archive, $vmid, $user, $opts) = @_;
3449 my $format = $opts->{format
};
3452 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3453 $format = 'tar' if !$format;
3455 } elsif ($archive =~ m/\.tar$/) {
3456 $format = 'tar' if !$format;
3457 } elsif ($archive =~ m/.tar.lzo$/) {
3458 $format = 'tar' if !$format;
3460 } elsif ($archive =~ m/\.vma$/) {
3461 $format = 'vma' if !$format;
3462 } elsif ($archive =~ m/\.vma\.gz$/) {
3463 $format = 'vma' if !$format;
3465 } elsif ($archive =~ m/\.vma\.lzo$/) {
3466 $format = 'vma' if !$format;
3469 $format = 'vma' if !$format; # default
3472 # try to detect archive format
3473 if ($format eq 'tar') {
3474 return restore_tar_archive
($archive, $vmid, $user, $opts);
3476 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3480 sub restore_update_config_line
{
3481 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3483 return if $line =~ m/^\#qmdump\#/;
3484 return if $line =~ m/^\#vzdump\#/;
3485 return if $line =~ m/^lock:/;
3486 return if $line =~ m/^unused\d+:/;
3487 return if $line =~ m/^parent:/;
3489 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3490 # try to convert old 1.X settings
3491 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3492 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3493 my ($model, $macaddr) = split(/\=/, $devconfig);
3494 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3497 bridge
=> "vmbr$ind",
3498 macaddr
=> $macaddr,
3500 my $netstr = print_net
($net);
3502 print $outfd "net$cookie->{netcount}: $netstr\n";
3503 $cookie->{netcount
}++;
3505 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3506 my ($id, $netstr) = ($1, $2);
3507 my $net = parse_net
($netstr);
3508 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3509 $netstr = print_net
($net);
3510 print $outfd "$id: $netstr\n";
3511 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3514 if ($line =~ m/backup=no/) {
3515 print $outfd "#$line";
3516 } elsif ($virtdev && $map->{$virtdev}) {
3517 my $di = PVE
::QemuServer
::parse_drive
($virtdev, $value);
3518 $di->{file
} = $map->{$virtdev};
3519 $value = PVE
::QemuServer
::print_drive
($vmid, $di);
3520 print $outfd "$virtdev: $value\n";
3530 my ($cfg, $vmid) = @_;
3532 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3534 my $volid_hash = {};
3535 foreach my $storeid (keys %$info) {
3536 foreach my $item (@{$info->{$storeid}}) {
3537 next if !($item->{volid
} && $item->{size
});
3538 $volid_hash->{$item->{volid
}} = $item;
3545 sub update_disksize
{
3546 my ($vmid, $conf, $volid_hash) = @_;
3553 foreach my $opt (keys %$conf) {
3554 if (PVE
::QemuServer
::valid_drivename
($opt)) {
3555 my $drive = PVE
::QemuServer
::parse_drive
($opt, $conf->{$opt});
3556 my $volid = $drive->{file
};
3559 $used->{$volid} = 1;
3561 next if PVE
::QemuServer
::drive_is_cdrom
($drive);
3562 next if !$volid_hash->{$volid};
3564 $drive->{size
} = $volid_hash->{$volid}->{size
};
3566 $conf->{$opt} = PVE
::QemuServer
::print_drive
($vmid, $drive);
3570 foreach my $volid (sort keys %$volid_hash) {
3571 next if $volid =~ m/vm-$vmid-state-/;
3572 next if $used->{$volid};
3574 PVE
::QemuServer
::add_unused_volume
($conf, $volid);
3581 my ($vmid, $nolock) = @_;
3583 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3585 my $volid_hash = scan_volids
($cfg, $vmid);
3587 my $updatefn = sub {
3590 my $conf = PVE
::QemuServer
::load_config
($vmid);
3592 PVE
::QemuServer
::check_lock
($conf);
3594 my $changes = PVE
::QemuServer
::update_disksize
($vmid, $conf, $volid_hash);
3596 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1) if $changes;
3599 if (defined($vmid)) {
3603 PVE
::QemuServer
::lock_config
($vmid, $updatefn, $vmid);
3606 my $vmlist = config_list
();
3607 foreach my $vmid (keys %$vmlist) {
3611 PVE
::QemuServer
::lock_config
($vmid, $updatefn, $vmid);
3617 sub restore_vma_archive
{
3618 my ($archive, $vmid, $user, $opts, $comp) = @_;
3620 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3621 my $readfrom = $archive;
3626 my $qarchive = PVE
::Tools
::shellquote
($archive);
3627 if ($comp eq 'gzip') {
3628 $uncomp = "zcat $qarchive|";
3629 } elsif ($comp eq 'lzop') {
3630 $uncomp = "lzop -d -c $qarchive|";
3632 die "unknown compression method '$comp'\n";
3637 my $tmpdir = "/var/tmp/vzdumptmp$$";
3640 # disable interrupts (always do cleanups)
3641 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3642 warn "got interrupt - ignored\n";
3645 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3646 POSIX
::mkfifo
($mapfifo, 0600);
3649 my $openfifo = sub {
3650 open($fifofh, '>', $mapfifo) || die $!;
3653 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3660 my $rpcenv = PVE
::RPCEnvironment
::get
();
3662 my $conffile = PVE
::QemuServer
::config_file
($vmid);
3663 my $tmpfn = "$conffile.$$.tmp";
3665 my $print_devmap = sub {
3666 my $virtdev_hash = {};
3668 my $cfgfn = "$tmpdir/qemu-server.conf";
3670 # we can read the config - that is already extracted
3671 my $fh = IO
::File-
>new($cfgfn, "r") ||
3672 "unable to read qemu-server.conf - $!\n";
3674 while (defined(my $line = <$fh>)) {
3675 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3676 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3677 die "archive does not contain data for drive '$virtdev'\n"
3678 if !$devinfo->{$devname};
3679 if (defined($opts->{storage
})) {
3680 $storeid = $opts->{storage
} || 'local';
3681 } elsif (!$storeid) {
3684 $format = 'raw' if !$format;
3685 $devinfo->{$devname}->{devname
} = $devname;
3686 $devinfo->{$devname}->{virtdev
} = $virtdev;
3687 $devinfo->{$devname}->{format
} = $format;
3688 $devinfo->{$devname}->{storeid
} = $storeid;
3690 # check permission on storage
3691 my $pool = $opts->{pool
}; # todo: do we need that?
3692 if ($user ne 'root@pam') {
3693 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3696 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3700 foreach my $devname (keys %$devinfo) {
3701 die "found no device mapping information for device '$devname'\n"
3702 if !$devinfo->{$devname}->{virtdev
};
3706 my $cfg = cfs_read_file
('storage.cfg');
3707 foreach my $virtdev (sort keys %$virtdev_hash) {
3708 my $d = $virtdev_hash->{$virtdev};
3709 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3710 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3711 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3712 $d->{format
}, undef, $alloc_size);
3713 print STDERR
"new volume ID is '$volid'\n";
3714 $d->{volid
} = $volid;
3715 my $path = PVE
::Storage
::path
($cfg, $volid);
3717 my $write_zeros = 1;
3718 # fixme: what other storages types initialize volumes with zero?
3719 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs') {
3723 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3725 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3726 $map->{$virtdev} = $volid;
3729 $fh->seek(0, 0) || die "seek failed - $!\n";
3731 my $outfd = new IO
::File
($tmpfn, "w") ||
3732 die "unable to write config for VM $vmid\n";
3734 my $cookie = { netcount
=> 0 };
3735 while (defined(my $line = <$fh>)) {
3736 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3745 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3746 die "interrupted by signal\n";
3748 local $SIG{ALRM
} = sub { die "got timeout\n"; };
3750 $oldtimeout = alarm($timeout);
3757 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
3758 my ($dev_id, $size, $devname) = ($1, $2, $3);
3759 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
3760 } elsif ($line =~ m/^CTIME: /) {
3762 print $fifofh "done\n";
3763 my $tmp = $oldtimeout || 0;
3764 $oldtimeout = undef;
3770 print "restore vma archive: $cmd\n";
3771 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
3775 alarm($oldtimeout) if $oldtimeout;
3783 my $cfg = cfs_read_file
('storage.cfg');
3784 foreach my $devname (keys %$devinfo) {
3785 my $volid = $devinfo->{$devname}->{volid
};
3788 if ($volid =~ m
|^/|) {
3789 unlink $volid || die 'unlink failed\n';
3791 PVE
::Storage
::vdisk_free
($cfg, $volid);
3793 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3795 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3802 rename $tmpfn, $conffile ||
3803 die "unable to commit configuration file '$conffile'\n";
3805 eval { rescan
($vmid, 1); };
3809 sub restore_tar_archive
{
3810 my ($archive, $vmid, $user, $opts) = @_;
3812 if ($archive ne '-') {
3813 my $firstfile = archive_read_firstfile
($archive);
3814 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3815 if $firstfile ne 'qemu-server.conf';
3818 my $tocmd = "/usr/lib/qemu-server/qmextract";
3820 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
3821 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
3822 $tocmd .= ' --prealloc' if $opts->{prealloc
};
3823 $tocmd .= ' --info' if $opts->{info
};
3825 # tar option "xf" does not autodetect compression when read from STDIN,
3826 # so we pipe to zcat
3827 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
3828 PVE
::Tools
::shellquote
("--to-command=$tocmd");
3830 my $tmpdir = "/var/tmp/vzdumptmp$$";
3833 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
3834 local $ENV{VZDUMP_VMID
} = $vmid;
3835 local $ENV{VZDUMP_USER
} = $user;
3837 my $conffile = PVE
::QemuServer
::config_file
($vmid);
3838 my $tmpfn = "$conffile.$$.tmp";
3840 # disable interrupts (always do cleanups)
3841 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3842 print STDERR
"got interrupt - ignored\n";
3847 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3848 die "interrupted by signal\n";
3851 if ($archive eq '-') {
3852 print "extracting archive from STDIN\n";
3853 run_command
($cmd, input
=> "<&STDIN");
3855 print "extracting archive '$archive'\n";
3859 return if $opts->{info
};
3863 my $statfile = "$tmpdir/qmrestore.stat";
3864 if (my $fd = IO
::File-
>new($statfile, "r")) {
3865 while (defined (my $line = <$fd>)) {
3866 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3867 $map->{$1} = $2 if $1;
3869 print STDERR
"unable to parse line in statfile - $line\n";
3875 my $confsrc = "$tmpdir/qemu-server.conf";
3877 my $srcfd = new IO
::File
($confsrc, "r") ||
3878 die "unable to open file '$confsrc'\n";
3880 my $outfd = new IO
::File
($tmpfn, "w") ||
3881 die "unable to write config for VM $vmid\n";
3883 my $cookie = { netcount
=> 0 };
3884 while (defined (my $line = <$srcfd>)) {
3885 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3897 restore_cleanup
("$tmpdir/qmrestore.stat") if !$opts->{info
};
3904 rename $tmpfn, $conffile ||
3905 die "unable to commit configuration file '$conffile'\n";
3907 eval { rescan
($vmid, 1); };
3912 # Internal snapshots
3914 # NOTE: Snapshot create/delete involves several non-atomic
3915 # action, and can take a long time.
3916 # So we try to avoid locking the file and use 'lock' variable
3917 # inside the config file instead.
3919 my $snapshot_copy_config = sub {
3920 my ($source, $dest) = @_;
3922 foreach my $k (keys %$source) {
3923 next if $k eq 'snapshots';
3924 next if $k eq 'snapstate';
3925 next if $k eq 'snaptime';
3926 next if $k eq 'vmstate';
3927 next if $k eq 'lock';
3928 next if $k eq 'digest';
3929 next if $k eq 'description';
3930 next if $k =~ m/^unused\d+$/;
3932 $dest->{$k} = $source->{$k};
3936 my $snapshot_apply_config = sub {
3937 my ($conf, $snap) = @_;
3939 # copy snapshot list
3941 snapshots
=> $conf->{snapshots
},
3944 # keep description and list of unused disks
3945 foreach my $k (keys %$conf) {
3946 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
3947 $newconf->{$k} = $conf->{$k};
3950 &$snapshot_copy_config($snap, $newconf);
3955 sub foreach_writable_storage
{
3956 my ($conf, $func) = @_;
3960 foreach my $ds (keys %$conf) {
3961 next if !valid_drivename
($ds);
3963 my $drive = parse_drive
($ds, $conf->{$ds});
3965 next if drive_is_cdrom
($drive);
3967 my $volid = $drive->{file
};
3969 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3970 $sidhash->{$sid} = $sid if $sid;
3973 foreach my $sid (sort keys %$sidhash) {
3978 my $alloc_vmstate_volid = sub {
3979 my ($storecfg, $vmid, $conf, $snapname) = @_;
3981 # Note: we try to be smart when selecting a $target storage
3985 # search shared storage first
3986 foreach_writable_storage
($conf, sub {
3988 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
3989 return if !$scfg->{shared
};
3991 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
3995 # now search local storage
3996 foreach_writable_storage
($conf, sub {
3998 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
3999 return if $scfg->{shared
};
4001 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4005 $target = 'local' if !$target;
4007 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4008 # we abort live save after $conf->{memory}, so we need at max twice that space
4009 my $size = $conf->{memory
}*2 + $driver_state_size;
4011 my $name = "vm-$vmid-state-$snapname";
4012 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4013 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4014 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4019 my $snapshot_prepare = sub {
4020 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4024 my $updatefn = sub {
4026 my $conf = load_config
($vmid);
4030 $conf->{lock} = 'snapshot';
4032 die "snapshot name '$snapname' already used\n"
4033 if defined($conf->{snapshots
}->{$snapname});
4035 my $storecfg = PVE
::Storage
::config
();
4037 foreach_drive
($conf, sub {
4038 my ($ds, $drive) = @_;
4040 return if drive_is_cdrom
($drive);
4041 my $volid = $drive->{file
};
4043 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4045 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
4046 die "can't snapshot volume '$volid'\n"
4047 if !(($scfg->{path
} && $volname =~ m/\.qcow2$/) ||
4048 ($scfg->{type
} eq 'nexenta') ||
4049 ($scfg->{type
} eq 'rbd') ||
4050 ($scfg->{type
} eq 'sheepdog'));
4051 } elsif ($volid =~ m
|^(/.+)$| && -e
$volid) {
4052 die "snapshot device '$volid' is not possible\n";
4054 die "can't snapshot volume '$volid'\n";
4059 $snap = $conf->{snapshots
}->{$snapname} = {};
4061 if ($save_vmstate && check_running
($vmid)) {
4062 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4065 &$snapshot_copy_config($conf, $snap);
4067 $snap->{snapstate
} = "prepare";
4068 $snap->{snaptime
} = time();
4069 $snap->{description
} = $comment if $comment;
4071 update_config_nolock
($vmid, $conf, 1);
4074 lock_config
($vmid, $updatefn);
4079 my $snapshot_commit = sub {
4080 my ($vmid, $snapname) = @_;
4082 my $updatefn = sub {
4084 my $conf = load_config
($vmid);
4086 die "missing snapshot lock\n"
4087 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4089 my $snap = $conf->{snapshots
}->{$snapname};
4091 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4093 die "wrong snapshot state\n"
4094 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4096 delete $snap->{snapstate
};
4097 delete $conf->{lock};
4099 my $newconf = &$snapshot_apply_config($conf, $snap);
4101 $newconf->{parent
} = $snapname;
4103 update_config_nolock
($vmid, $newconf, 1);
4106 lock_config
($vmid, $updatefn);
4109 sub snapshot_rollback
{
4110 my ($vmid, $snapname) = @_;
4116 my $storecfg = PVE
::Storage
::config
();
4118 my $updatefn = sub {
4120 my $conf = load_config
($vmid);
4122 $snap = $conf->{snapshots
}->{$snapname};
4124 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4126 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4127 if $snap->{snapstate
};
4131 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4134 die "unable to rollback vm $vmid: vm is running\n"
4135 if check_running
($vmid);
4138 $conf->{lock} = 'rollback';
4140 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4141 delete $conf->{lock};
4145 # copy snapshot config to current config
4146 $conf = &$snapshot_apply_config($conf, $snap);
4147 $conf->{parent
} = $snapname;
4150 update_config_nolock
($vmid, $conf, 1);
4152 if (!$prepare && $snap->{vmstate
}) {
4153 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4154 vm_start
($storecfg, $vmid, $statefile);
4158 lock_config
($vmid, $updatefn);
4160 foreach_drive
($snap, sub {
4161 my ($ds, $drive) = @_;
4163 return if drive_is_cdrom
($drive);
4165 my $volid = $drive->{file
};
4166 my $device = "drive-$ds";
4168 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4172 lock_config
($vmid, $updatefn);
4175 my $savevm_wait = sub {
4179 my $stat = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "query-savevm");
4180 if (!$stat->{status
}) {
4181 die "savevm not active\n";
4182 } elsif ($stat->{status
} eq 'active') {
4185 } elsif ($stat->{status
} eq 'completed') {
4188 die "query-savevm returned status '$stat->{status}'\n";
4193 sub snapshot_create
{
4194 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4196 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4198 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4202 my $running = check_running
($vmid);
4205 # create internal snapshots of all drives
4207 my $storecfg = PVE
::Storage
::config
();
4210 if ($snap->{vmstate
}) {
4211 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4212 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4213 &$savevm_wait($vmid);
4215 vm_mon_cmd
($vmid, "savevm-start");
4219 qga_freezefs
($vmid) if $running && $freezefs;
4221 foreach_drive
($snap, sub {
4222 my ($ds, $drive) = @_;
4224 return if drive_is_cdrom
($drive);
4226 my $volid = $drive->{file
};
4227 my $device = "drive-$ds";
4229 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4230 $drivehash->{$ds} = 1;
4235 eval { gqa_unfreezefs
($vmid) if $running && $freezefs; };
4238 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4242 warn "snapshot create failed: starting cleanup\n";
4243 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4248 &$snapshot_commit($vmid, $snapname);
4251 # Note: $drivehash is only set when called from snapshot_create.
4252 sub snapshot_delete
{
4253 my ($vmid, $snapname, $force, $drivehash) = @_;
4260 my $unlink_parent = sub {
4261 my ($confref, $new_parent) = @_;
4263 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4265 $confref->{parent
} = $new_parent;
4267 delete $confref->{parent
};
4272 my $updatefn = sub {
4273 my ($remove_drive) = @_;
4275 my $conf = load_config
($vmid);
4277 check_lock
($conf) if !$drivehash;
4279 $snap = $conf->{snapshots
}->{$snapname};
4281 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4283 # remove parent refs
4284 &$unlink_parent($conf, $snap->{parent
});
4285 foreach my $sn (keys %{$conf->{snapshots
}}) {
4286 next if $sn eq $snapname;
4287 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4290 if ($remove_drive) {
4291 if ($remove_drive eq 'vmstate') {
4292 delete $snap->{$remove_drive};
4294 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4295 my $volid = $drive->{file
};
4296 delete $snap->{$remove_drive};
4297 add_unused_volume
($conf, $volid);
4302 $snap->{snapstate
} = 'delete';
4304 delete $conf->{snapshots
}->{$snapname};
4305 delete $conf->{lock} if $drivehash;
4306 foreach my $volid (@$unused) {
4307 add_unused_volume
($conf, $volid);
4311 update_config_nolock
($vmid, $conf, 1);
4314 lock_config
($vmid, $updatefn);
4316 # now remove vmstate file
4318 my $storecfg = PVE
::Storage
::config
();
4320 if ($snap->{vmstate
}) {
4321 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4323 die $err if !$force;
4326 # save changes (remove vmstate from snapshot)
4327 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4330 # now remove all internal snapshots
4331 foreach_drive
($snap, sub {
4332 my ($ds, $drive) = @_;
4334 return if drive_is_cdrom
($drive);
4336 my $volid = $drive->{file
};
4337 my $device = "drive-$ds";
4339 if (!$drivehash || $drivehash->{$ds}) {
4340 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4342 die $err if !$force;
4347 # save changes (remove drive fron snapshot)
4348 lock_config
($vmid, $updatefn, $ds) if !$force;
4349 push @$unused, $volid;
4352 # now cleanup config
4354 lock_config
($vmid, $updatefn);