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
=> "Allow hotplug for disk and network device",
175 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
181 description
=> "Lock/unlock the VM.",
182 enum
=> [qw(migrate backup snapshot rollback)],
187 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
194 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
202 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
209 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
215 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
223 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
224 enum
=> PVE
::Tools
::kvmkeymaplist
(),
229 type
=> 'string', format
=> 'dns-name',
230 description
=> "Set a name for the VM. Only used on the configuration web interface.",
235 description
=> "scsi controller model",
236 enum
=> [qw(lsi virtio-scsi-pci megasas)],
242 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
247 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
248 description
=> <<EODESC,
249 Used to enable special optimization/features for specific
252 other => unspecified OS
253 wxp => Microsoft Windows XP
254 w2k => Microsoft Windows 2000
255 w2k3 => Microsoft Windows 2003
256 w2k8 => Microsoft Windows 2008
257 wvista => Microsoft Windows Vista
258 win7 => Microsoft Windows 7
259 win8 => Microsoft Windows 8/2012
260 l24 => Linux 2.4 Kernel
261 l26 => Linux 2.6/3.X Kernel
263 other|l24|l26 ... no special behaviour
264 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
270 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
271 pattern
=> '[acdn]{1,4}',
276 type
=> 'string', format
=> 'pve-qm-bootdisk',
277 description
=> "Enable booting from specified disk.",
278 pattern
=> '(ide|sata|scsi|virtio)\d+',
283 description
=> "The number of CPUs. Please use option -sockets instead.",
290 description
=> "The number of CPU sockets.",
297 description
=> "The number of cores per socket.",
304 description
=> "Enable/disable ACPI.",
310 description
=> "Enable/disable Qemu GuestAgent.",
316 description
=> "Enable/disable KVM hardware virtualization.",
322 description
=> "Enable/disable time drift fix.",
328 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
333 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
338 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types",
339 enum
=> [qw(std cirrus vmware)],
343 type
=> 'string', format
=> 'pve-qm-watchdog',
344 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
345 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
350 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
351 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
352 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
357 type
=> 'string', format
=> 'pve-qm-startup',
358 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
359 description
=> "Startup and shutdown behavior. Order is a non-negative number defining the general startup order. Shutdown in done with reverse ordering. Additionally you can set the 'up' or 'down' delay in seconds, which specifies a delay to wait before the next VM is started or stopped.",
364 description
=> "Enable/disable Template.",
370 description
=> <<EODESCR,
371 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
373 args: -no-reboot -no-hpet
380 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. Else the mouse runs out of sync with normal vnc clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches.",
385 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
389 migrate_downtime
=> {
392 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
398 type
=> 'string', format
=> 'pve-qm-drive',
399 typetext
=> 'volume',
400 description
=> "This is an alias for option -ide2",
404 description
=> "Emulated CPU type.",
406 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
409 parent
=> get_standard_option
('pve-snapshot-name', {
411 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
415 description
=> "Timestamp for snapshots.",
421 type
=> 'string', format
=> 'pve-volume-id',
422 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
426 # what about other qemu settings ?
428 #machine => 'string',
441 ##soundhw => 'string',
443 while (my ($k, $v) = each %$confdesc) {
444 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
447 my $MAX_IDE_DISKS = 4;
448 my $MAX_SCSI_DISKS = 14;
449 my $MAX_VIRTIO_DISKS = 16;
450 my $MAX_SATA_DISKS = 6;
451 my $MAX_USB_DEVICES = 5;
453 my $MAX_UNUSED_DISKS = 8;
454 my $MAX_HOSTPCI_DEVICES = 2;
455 my $MAX_SERIAL_PORTS = 4;
456 my $MAX_PARALLEL_PORTS = 3;
458 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
459 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
460 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
464 type
=> 'string', format
=> 'pve-qm-net',
465 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
466 description
=> <<EODESCR,
467 Specify network devices.
469 MODEL is one of: $nic_model_list_txt
471 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
472 automatically generated if not specified.
474 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
476 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
478 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
484 The DHCP server assign addresses to the guest starting from 10.0.2.15.
488 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
490 for (my $i = 0; $i < $MAX_NETS; $i++) {
491 $confdesc->{"net$i"} = $netdesc;
498 type
=> 'string', format
=> 'pve-qm-drive',
499 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
500 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
502 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
506 type
=> 'string', format
=> 'pve-qm-drive',
507 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
508 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
510 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
516 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
524 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
530 type
=> 'string', format
=> 'pve-qm-usb-device',
531 typetext
=> 'host=HOSTUSBDEVICE',
532 description
=> <<EODESCR,
533 Configure an USB device (n is 0 to 4). This can be used to
534 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
536 'bus-port(.port)*' (decimal numbers) or
537 'vendor_id:product_id' (hexadeciaml numbers)
539 You can use the 'lsusb -t' command to list existing usb devices.
541 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
545 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
549 type
=> 'string', format
=> 'pve-qm-hostpci',
550 typetext
=> "HOSTPCIDEVICE",
551 description
=> <<EODESCR,
552 Map host pci devices. HOSTPCIDEVICE syntax is:
554 'bus:dev.func' (hexadecimal numbers)
556 You can us the 'lspci' command to list existing pci devices.
558 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
560 Experimental: user reported problems with this option.
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
568 pattern
=> '/dev/ttyS\d+',
569 description
=> <<EODESCR,
570 Map host serial devices (n is 0 to 3).
572 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
574 Experimental: user reported problems with this option.
581 pattern
=> '/dev/parport\d+',
582 description
=> <<EODESCR,
583 Map host parallel devices (n is 0 to 2).
585 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
587 Experimental: user reported problems with this option.
591 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
592 $confdesc->{"parallel$i"} = $paralleldesc;
595 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
596 $confdesc->{"serial$i"} = $serialdesc;
599 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
600 $confdesc->{"hostpci$i"} = $hostpcidesc;
603 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
604 $drivename_hash->{"ide$i"} = 1;
605 $confdesc->{"ide$i"} = $idedesc;
608 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
609 $drivename_hash->{"sata$i"} = 1;
610 $confdesc->{"sata$i"} = $satadesc;
613 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
614 $drivename_hash->{"scsi$i"} = 1;
615 $confdesc->{"scsi$i"} = $scsidesc ;
618 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
619 $drivename_hash->{"virtio$i"} = 1;
620 $confdesc->{"virtio$i"} = $virtiodesc;
623 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
624 $confdesc->{"usb$i"} = $usbdesc;
629 type
=> 'string', format
=> 'pve-volume-id',
630 description
=> "Reference to unused volumes.",
633 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
634 $confdesc->{"unused$i"} = $unuseddesc;
637 my $kvm_api_version = 0;
641 return $kvm_api_version if $kvm_api_version;
643 my $fh = IO
::File-
>new("</dev/kvm") ||
646 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
647 $kvm_api_version = $v;
652 return $kvm_api_version;
655 my $kvm_user_version;
657 sub kvm_user_version
{
659 return $kvm_user_version if $kvm_user_version;
661 $kvm_user_version = 'unknown';
663 my $tmp = `kvm -help 2>/dev/null`;
665 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
666 $kvm_user_version = $2;
669 return $kvm_user_version;
673 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
676 # order is important - used to autoselect boot disk
677 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
678 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
679 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
680 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
683 sub valid_drivename
{
686 return defined($drivename_hash->{$dev});
691 return defined($confdesc->{$key});
695 return $nic_model_list;
698 sub os_list_description
{
703 w2k
=> 'Windows 2000',
704 w2k3
=>, 'Windows 2003',
705 w2k8
=> 'Windows 2008',
706 wvista
=> 'Windows Vista',
708 win8
=> 'Windows 8/2012',
718 return $cdrom_path if $cdrom_path;
720 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
721 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
722 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
726 my ($storecfg, $vmid, $cdrom) = @_;
728 if ($cdrom eq 'cdrom') {
729 return get_cdrom_path
();
730 } elsif ($cdrom eq 'none') {
732 } elsif ($cdrom =~ m
|^/|) {
735 return PVE
::Storage
::path
($storecfg, $cdrom);
739 # try to convert old style file names to volume IDs
740 sub filename_to_volume_id
{
741 my ($vmid, $file, $media) = @_;
743 if (!($file eq 'none' || $file eq 'cdrom' ||
744 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
746 return undef if $file =~ m
|/|;
748 if ($media && $media eq 'cdrom') {
749 $file = "local:iso/$file";
751 $file = "local:$vmid/$file";
758 sub verify_media_type
{
759 my ($opt, $vtype, $media) = @_;
764 if ($media eq 'disk') {
766 } elsif ($media eq 'cdrom') {
769 die "internal error";
772 return if ($vtype eq $etype);
774 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
777 sub cleanup_drive_path
{
778 my ($opt, $storecfg, $drive) = @_;
780 # try to convert filesystem paths to volume IDs
782 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
783 ($drive->{file
} !~ m
|^/dev/.+|) &&
784 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
785 ($drive->{file
} !~ m/^\d+$/)) {
786 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
787 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
788 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
789 verify_media_type
($opt, $vtype, $drive->{media
});
790 $drive->{file
} = $volid;
793 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
796 sub create_conf_nolock
{
797 my ($vmid, $settings) = @_;
799 my $filename = config_file
($vmid);
801 die "configuration file '$filename' already exists\n" if -f
$filename;
803 my $defaults = load_defaults
();
805 $settings->{name
} = "vm$vmid" if !$settings->{name
};
806 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
809 foreach my $opt (keys %$settings) {
810 next if !$confdesc->{$opt};
812 my $value = $settings->{$opt};
815 $data .= "$opt: $value\n";
818 PVE
::Tools
::file_set_contents
($filename, $data);
821 my $parse_size = sub {
824 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
825 my ($size, $unit) = ($1, $3);
828 $size = $size * 1024;
829 } elsif ($unit eq 'M') {
830 $size = $size * 1024 * 1024;
831 } elsif ($unit eq 'G') {
832 $size = $size * 1024 * 1024 * 1024;
838 my $format_size = sub {
843 my $kb = int($size/1024);
844 return $size if $kb*1024 != $size;
846 my $mb = int($kb/1024);
847 return "${kb}K" if $mb*1024 != $kb;
849 my $gb = int($mb/1024);
850 return "${mb}M" if $gb*1024 != $mb;
855 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
856 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
857 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
858 # [,aio=native|threads]
861 my ($key, $data) = @_;
865 # $key may be undefined - used to verify JSON parameters
866 if (!defined($key)) {
867 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
869 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
870 $res->{interface
} = $1;
876 foreach my $p (split (/,/, $data)) {
877 next if $p =~ m/^\s*$/;
879 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|bps_rd|mbps_rd|bps_wr|mbps_wr|iops|iops_rd|iops_wr|size)=(.+)$/) {
880 my ($k, $v) = ($1, $2);
882 $k = 'file' if $k eq 'volume';
884 return undef if defined $res->{$k};
886 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
887 return undef if !$v || $v !~ m/^\d+/;
889 $v = sprintf("%.3f", $v / (1024*1024));
893 if (!$res->{file
} && $p !~ m/=/) {
901 return undef if !$res->{file
};
903 return undef if $res->{cache
} &&
904 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
905 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
906 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
907 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
908 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
909 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
910 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
911 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
912 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
913 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
914 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
915 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
918 return undef if $res->{mbps_rd
} && $res->{mbps
};
919 return undef if $res->{mbps_wr
} && $res->{mbps
};
921 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
922 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
923 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
925 return undef if $res->{iops_rd
} && $res->{iops
};
926 return undef if $res->{iops_wr
} && $res->{iops
};
927 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
928 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
929 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
933 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
936 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
937 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
938 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
939 return undef if $res->{interface
} eq 'virtio';
942 # rerror does not work with scsi drives
943 if ($res->{rerror
}) {
944 return undef if $res->{interface
} eq 'scsi';
950 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
953 my ($vmid, $drive) = @_;
956 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
957 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
960 if ($drive->{size
}) {
961 $opts .= ",size=" . &$format_size($drive->{size
});
964 return "$drive->{file}$opts";
968 my($fh, $noerr) = @_;
971 my $SG_GET_VERSION_NUM = 0x2282;
973 my $versionbuf = "\x00" x
8;
974 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
976 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
979 my $version = unpack("I", $versionbuf);
980 if ($version < 30000) {
981 die "scsi generic interface too old\n" if !$noerr;
985 my $buf = "\x00" x
36;
986 my $sensebuf = "\x00" x
8;
987 my $cmd = pack("C x3 C x11", 0x12, 36);
989 # see /usr/include/scsi/sg.h
990 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";
992 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
993 length($sensebuf), 0, length($buf), $buf,
994 $cmd, $sensebuf, 6000);
996 $ret = ioctl($fh, $SG_IO, $packet);
998 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1002 my @res = unpack($sg_io_hdr_t, $packet);
1003 if ($res[17] || $res[18]) {
1004 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1009 ($res->{device
}, $res->{removable
}, $res->{venodor
},
1010 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1018 my $fh = IO
::File-
>new("+<$path") || return undef;
1019 my $res = scsi_inquiry
($fh, 1);
1025 sub print_drivedevice_full
{
1026 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1031 if ($drive->{interface
} eq 'virtio') {
1032 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1033 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1034 } elsif ($drive->{interface
} eq 'scsi') {
1035 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1036 my $controller = int($drive->{index} / $maxdev);
1037 my $unit = $drive->{index} % $maxdev;
1038 my $devicetype = 'hd';
1040 if (drive_is_cdrom
($drive)) {
1043 if ($drive->{file
} =~ m
|^/|) {
1044 $path = $drive->{file
};
1046 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1049 if($path =~ m/^iscsi\:\/\
//){
1050 $devicetype = 'generic';
1053 $devicetype = 'block' if path_is_scsi
($path);
1057 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1058 $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';
1060 $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}";
1063 } elsif ($drive->{interface
} eq 'ide'){
1065 my $controller = int($drive->{index} / $maxdev);
1066 my $unit = $drive->{index} % $maxdev;
1067 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1069 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1070 } elsif ($drive->{interface
} eq 'sata'){
1071 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1072 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1073 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1074 } elsif ($drive->{interface
} eq 'usb') {
1076 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1078 die "unsupported interface type";
1081 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1086 sub print_drive_full
{
1087 my ($storecfg, $vmid, $drive) = @_;
1090 foreach my $o (@qemu_drive_options) {
1091 next if $o eq 'bootindex';
1092 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1095 foreach my $o (qw(bps bps_rd bps_wr)) {
1096 my $v = $drive->{"m$o"};
1097 $opts .= ",$o=" . int($v*1024*1024) if $v;
1100 # use linux-aio by default (qemu default is threads)
1101 $opts .= ",aio=native" if !$drive->{aio
};
1104 my $volid = $drive->{file
};
1105 if (drive_is_cdrom
($drive)) {
1106 $path = get_iso_path
($storecfg, $vmid, $volid);
1108 if ($volid =~ m
|^/|) {
1111 $path = PVE
::Storage
::path
($storecfg, $volid);
1115 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1117 my $pathinfo = $path ?
"file=$path," : '';
1119 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1122 sub print_netdevice_full
{
1123 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1125 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1127 my $device = $net->{model
};
1128 if ($net->{model
} eq 'virtio') {
1129 $device = 'virtio-net-pci';
1132 # qemu > 0.15 always try to boot from network - we disable that by
1133 # not loading the pxe rom file
1134 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1135 my $pciaddr = print_pci_addr
("$netid", $bridges);
1136 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1137 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1141 sub print_netdev_full
{
1142 my ($vmid, $conf, $net, $netid) = @_;
1145 if ($netid =~ m/^net(\d+)$/) {
1149 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1151 my $ifname = "tap${vmid}i$i";
1153 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1154 die "interface name '$ifname' is too long (max 15 character)\n"
1155 if length($ifname) >= 16;
1157 my $vhostparam = '';
1158 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1160 my $vmname = $conf->{name
} || "vm$vmid";
1162 if ($net->{bridge
}) {
1163 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1165 return "type=user,id=$netid,hostname=$vmname";
1169 sub drive_is_cdrom
{
1172 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1179 return undef if !$value;
1183 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1184 $res->{pciid
} = $value;
1192 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1198 foreach my $kvp (split(/,/, $data)) {
1200 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1202 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1203 $res->{model
} = $model;
1204 $res->{macaddr
} = $mac;
1205 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1206 $res->{bridge
} = $1;
1207 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1209 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1217 return undef if !$res->{model
};
1225 my $res = "$net->{model}";
1226 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1227 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1228 $res .= ",rate=$net->{rate}" if $net->{rate
};
1229 $res .= ",tag=$net->{tag}" if $net->{tag
};
1234 sub add_random_macs
{
1235 my ($settings) = @_;
1237 foreach my $opt (keys %$settings) {
1238 next if $opt !~ m/^net(\d+)$/;
1239 my $net = parse_net
($settings->{$opt});
1241 $settings->{$opt} = print_net
($net);
1245 sub add_unused_volume
{
1246 my ($config, $volid) = @_;
1249 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1250 my $test = "unused$ind";
1251 if (my $vid = $config->{$test}) {
1252 return if $vid eq $volid; # do not add duplicates
1258 die "To many unused volume - please delete them first.\n" if !$key;
1260 $config->{$key} = $volid;
1265 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1266 sub verify_bootdisk
{
1267 my ($value, $noerr) = @_;
1269 return $value if valid_drivename
($value);
1271 return undef if $noerr;
1273 die "invalid boot disk '$value'\n";
1276 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1278 my ($value, $noerr) = @_;
1280 return $value if parse_net
($value);
1282 return undef if $noerr;
1284 die "unable to parse network options\n";
1287 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1289 my ($value, $noerr) = @_;
1291 return $value if parse_drive
(undef, $value);
1293 return undef if $noerr;
1295 die "unable to parse drive options\n";
1298 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1299 sub verify_hostpci
{
1300 my ($value, $noerr) = @_;
1302 return $value if parse_hostpci
($value);
1304 return undef if $noerr;
1306 die "unable to parse pci id\n";
1309 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1310 sub verify_watchdog
{
1311 my ($value, $noerr) = @_;
1313 return $value if parse_watchdog
($value);
1315 return undef if $noerr;
1317 die "unable to parse watchdog options\n";
1320 sub parse_watchdog
{
1323 return undef if !$value;
1327 foreach my $p (split(/,/, $value)) {
1328 next if $p =~ m/^\s*$/;
1330 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1332 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1333 $res->{action
} = $2;
1342 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1343 sub verify_startup
{
1344 my ($value, $noerr) = @_;
1346 return $value if parse_startup
($value);
1348 return undef if $noerr;
1350 die "unable to parse startup options\n";
1356 return undef if !$value;
1360 foreach my $p (split(/,/, $value)) {
1361 next if $p =~ m/^\s*$/;
1363 if ($p =~ m/^(order=)?(\d+)$/) {
1365 } elsif ($p =~ m/^up=(\d+)$/) {
1367 } elsif ($p =~ m/^down=(\d+)$/) {
1377 sub parse_usb_device
{
1380 return undef if !$value;
1382 my @dl = split(/,/, $value);
1386 foreach my $v (@dl) {
1387 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1389 $res->{vendorid
} = $2;
1390 $res->{productid
} = $4;
1391 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1393 $res->{hostbus
} = $1;
1394 $res->{hostport
} = $2;
1399 return undef if !$found;
1404 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1405 sub verify_usb_device
{
1406 my ($value, $noerr) = @_;
1408 return $value if parse_usb_device
($value);
1410 return undef if $noerr;
1412 die "unable to parse usb device\n";
1415 # add JSON properties for create and set function
1416 sub json_config_properties
{
1419 foreach my $opt (keys %$confdesc) {
1420 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1421 $prop->{$opt} = $confdesc->{$opt};
1428 my ($key, $value) = @_;
1430 die "unknown setting '$key'\n" if !$confdesc->{$key};
1432 my $type = $confdesc->{$key}->{type
};
1434 if (!defined($value)) {
1435 die "got undefined value\n";
1438 if ($value =~ m/[\n\r]/) {
1439 die "property contains a line feed\n";
1442 if ($type eq 'boolean') {
1443 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1444 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1445 die "type check ('boolean') failed - got '$value'\n";
1446 } elsif ($type eq 'integer') {
1447 return int($1) if $value =~ m/^(\d+)$/;
1448 die "type check ('integer') failed - got '$value'\n";
1449 } elsif ($type eq 'number') {
1450 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1451 die "type check ('number') failed - got '$value'\n";
1452 } elsif ($type eq 'string') {
1453 if (my $fmt = $confdesc->{$key}->{format
}) {
1454 if ($fmt eq 'pve-qm-drive') {
1455 # special case - we need to pass $key to parse_drive()
1456 my $drive = parse_drive
($key, $value);
1457 return $value if $drive;
1458 die "unable to parse drive options\n";
1460 PVE
::JSONSchema
::check_format
($fmt, $value);
1463 $value =~ s/^\"(.*)\"$/$1/;
1466 die "internal error"
1470 sub lock_config_full
{
1471 my ($vmid, $timeout, $code, @param) = @_;
1473 my $filename = config_file_lock
($vmid);
1475 my $res = lock_file
($filename, $timeout, $code, @param);
1483 my ($vmid, $code, @param) = @_;
1485 return lock_config_full
($vmid, 10, $code, @param);
1488 sub cfs_config_path
{
1489 my ($vmid, $node) = @_;
1491 $node = $nodename if !$node;
1492 return "nodes/$node/qemu-server/$vmid.conf";
1495 sub check_iommu_support
{
1496 #fixme : need to check IOMMU support
1497 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1505 my ($vmid, $node) = @_;
1507 my $cfspath = cfs_config_path
($vmid, $node);
1508 return "/etc/pve/$cfspath";
1511 sub config_file_lock
{
1514 return "$lock_dir/lock-$vmid.conf";
1520 my $conf = config_file
($vmid);
1521 utime undef, undef, $conf;
1525 my ($storecfg, $vmid, $keep_empty_config) = @_;
1527 my $conffile = config_file
($vmid);
1529 my $conf = load_config
($vmid);
1533 # only remove disks owned by this VM
1534 foreach_drive
($conf, sub {
1535 my ($ds, $drive) = @_;
1537 return if drive_is_cdrom
($drive);
1539 my $volid = $drive->{file
};
1541 return if !$volid || $volid =~ m
|^/|;
1543 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1544 return if !$path || !$owner || ($owner != $vmid);
1546 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1549 if ($keep_empty_config) {
1550 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1555 # also remove unused disk
1557 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1560 PVE
::Storage
::foreach_volid
($dl, sub {
1561 my ($volid, $sid, $volname, $d) = @_;
1562 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1572 my ($vmid, $node) = @_;
1574 my $cfspath = cfs_config_path
($vmid, $node);
1576 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1578 die "no such VM ('$vmid')\n" if !defined($conf);
1583 sub parse_vm_config
{
1584 my ($filename, $raw) = @_;
1586 return undef if !defined($raw);
1589 digest
=> Digest
::SHA
::sha1_hex
($raw),
1593 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1594 || die "got strange filename '$filename'";
1601 my @lines = split(/\n/, $raw);
1602 foreach my $line (@lines) {
1603 next if $line =~ m/^\s*$/;
1605 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1607 $conf->{description
} = $descr if $descr;
1609 $conf = $res->{snapshots
}->{$snapname} = {};
1613 if ($line =~ m/^\#(.*)\s*$/) {
1614 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1618 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1619 $descr .= PVE
::Tools
::decode_text
($2);
1620 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1621 $conf->{snapstate
} = $1;
1622 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1625 $conf->{$key} = $value;
1626 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1629 eval { $value = check_type
($key, $value); };
1631 warn "vm $vmid - unable to parse value of '$key' - $@";
1633 my $fmt = $confdesc->{$key}->{format
};
1634 if ($fmt && $fmt eq 'pve-qm-drive') {
1635 my $v = parse_drive
($key, $value);
1636 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1637 $v->{file
} = $volid;
1638 $value = print_drive
($vmid, $v);
1640 warn "vm $vmid - unable to parse value of '$key'\n";
1645 if ($key eq 'cdrom') {
1646 $conf->{ide2
} = $value;
1648 $conf->{$key} = $value;
1654 $conf->{description
} = $descr if $descr;
1656 delete $res->{snapstate
}; # just to be sure
1661 sub write_vm_config
{
1662 my ($filename, $conf) = @_;
1664 delete $conf->{snapstate
}; # just to be sure
1666 if ($conf->{cdrom
}) {
1667 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1668 $conf->{ide2
} = $conf->{cdrom
};
1669 delete $conf->{cdrom
};
1672 # we do not use 'smp' any longer
1673 if ($conf->{sockets
}) {
1674 delete $conf->{smp
};
1675 } elsif ($conf->{smp
}) {
1676 $conf->{sockets
} = $conf->{smp
};
1677 delete $conf->{cores
};
1678 delete $conf->{smp
};
1681 my $used_volids = {};
1683 my $cleanup_config = sub {
1686 foreach my $key (keys %$cref) {
1687 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1688 $key eq 'snapstate';
1689 my $value = $cref->{$key};
1690 eval { $value = check_type
($key, $value); };
1691 die "unable to parse value of '$key' - $@" if $@;
1693 $cref->{$key} = $value;
1695 if (valid_drivename
($key)) {
1696 my $drive = parse_drive
($key, $value);
1697 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1702 &$cleanup_config($conf);
1703 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1704 &$cleanup_config($conf->{snapshots
}->{$snapname});
1707 # remove 'unusedX' settings if we re-add a volume
1708 foreach my $key (keys %$conf) {
1709 my $value = $conf->{$key};
1710 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1711 delete $conf->{$key};
1715 my $generate_raw_config = sub {
1720 # add description as comment to top of file
1721 my $descr = $conf->{description
} || '';
1722 foreach my $cl (split(/\n/, $descr)) {
1723 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1726 foreach my $key (sort keys %$conf) {
1727 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1728 $raw .= "$key: $conf->{$key}\n";
1733 my $raw = &$generate_raw_config($conf);
1734 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1735 $raw .= "\n[$snapname]\n";
1736 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1742 sub update_config_nolock
{
1743 my ($vmid, $conf, $skiplock) = @_;
1745 check_lock
($conf) if !$skiplock;
1747 my $cfspath = cfs_config_path
($vmid);
1749 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1753 my ($vmid, $conf, $skiplock) = @_;
1755 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1762 # we use static defaults from our JSON schema configuration
1763 foreach my $key (keys %$confdesc) {
1764 if (defined(my $default = $confdesc->{$key}->{default})) {
1765 $res->{$key} = $default;
1769 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1770 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1776 my $vmlist = PVE
::Cluster
::get_vmlist
();
1778 return $res if !$vmlist || !$vmlist->{ids
};
1779 my $ids = $vmlist->{ids
};
1781 foreach my $vmid (keys %$ids) {
1782 my $d = $ids->{$vmid};
1783 next if !$d->{node
} || $d->{node
} ne $nodename;
1784 next if !$d->{type
} || $d->{type
} ne 'qemu';
1785 $res->{$vmid}->{exists} = 1;
1790 # test if VM uses local resources (to prevent migration)
1791 sub check_local_resources
{
1792 my ($conf, $noerr) = @_;
1796 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1797 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1799 foreach my $k (keys %$conf) {
1800 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1803 die "VM uses local resources\n" if $loc_res && !$noerr;
1808 # check is used storages are available on all nodes (use by migrate)
1809 sub check_storage_availability
{
1810 my ($storecfg, $conf, $node) = @_;
1812 foreach_drive
($conf, sub {
1813 my ($ds, $drive) = @_;
1815 my $volid = $drive->{file
};
1818 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1821 # check if storage is available on both nodes
1822 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1823 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1830 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1834 my ($pidfile, $pid) = @_;
1836 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1840 return undef if !$line;
1841 my @param = split(/\0/, $line);
1843 my $cmd = $param[0];
1844 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1846 for (my $i = 0; $i < scalar (@param); $i++) {
1849 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1850 my $p = $param[$i+1];
1851 return 1 if $p && ($p eq $pidfile);
1860 my ($vmid, $nocheck, $node) = @_;
1862 my $filename = config_file
($vmid, $node);
1864 die "unable to find configuration file for VM $vmid - no such machine\n"
1865 if !$nocheck && ! -f
$filename;
1867 my $pidfile = pidfile_name
($vmid);
1869 if (my $fd = IO
::File-
>new("<$pidfile")) {
1874 my $mtime = $st->mtime;
1875 if ($mtime > time()) {
1876 warn "file '$filename' modified in future\n";
1879 if ($line =~ m/^(\d+)$/) {
1881 if (check_cmdline
($pidfile, $pid)) {
1882 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1894 my $vzlist = config_list
();
1896 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1898 while (defined(my $de = $fd->read)) {
1899 next if $de !~ m/^(\d+)\.pid$/;
1901 next if !defined($vzlist->{$vmid});
1902 if (my $pid = check_running
($vmid)) {
1903 $vzlist->{$vmid}->{pid
} = $pid;
1911 my ($storecfg, $conf) = @_;
1913 my $bootdisk = $conf->{bootdisk
};
1914 return undef if !$bootdisk;
1915 return undef if !valid_drivename
($bootdisk);
1917 return undef if !$conf->{$bootdisk};
1919 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1920 return undef if !defined($drive);
1922 return undef if drive_is_cdrom
($drive);
1924 my $volid = $drive->{file
};
1925 return undef if !$volid;
1927 return $drive->{size
};
1930 my $last_proc_pid_stat;
1932 # get VM status information
1933 # This must be fast and should not block ($full == false)
1934 # We only query KVM using QMP if $full == true (this can be slow)
1936 my ($opt_vmid, $full) = @_;
1940 my $storecfg = PVE
::Storage
::config
();
1942 my $list = vzlist
();
1943 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
1945 my $cpucount = $cpuinfo->{cpus
} || 1;
1947 foreach my $vmid (keys %$list) {
1948 next if $opt_vmid && ($vmid ne $opt_vmid);
1950 my $cfspath = cfs_config_path
($vmid);
1951 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
1954 $d->{pid
} = $list->{$vmid}->{pid
};
1956 # fixme: better status?
1957 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
1959 my $size = disksize
($storecfg, $conf);
1960 if (defined($size)) {
1961 $d->{disk
} = 0; # no info available
1962 $d->{maxdisk
} = $size;
1968 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
1969 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
1971 $d->{name
} = $conf->{name
} || "VM $vmid";
1972 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
1974 if ($conf->{balloon
}) {
1975 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
1976 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
1987 $d->{diskwrite
} = 0;
1989 $d->{template
} = is_template
($conf);
1994 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
1995 foreach my $dev (keys %$netdev) {
1996 next if $dev !~ m/^tap([1-9]\d*)i/;
1998 my $d = $res->{$vmid};
2001 $d->{netout
} += $netdev->{$dev}->{receive
};
2002 $d->{netin
} += $netdev->{$dev}->{transmit
};
2005 my $ctime = gettimeofday
;
2007 foreach my $vmid (keys %$list) {
2009 my $d = $res->{$vmid};
2010 my $pid = $d->{pid
};
2013 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2014 next if !$pstat; # not running
2016 my $used = $pstat->{utime} + $pstat->{stime
};
2018 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2020 if ($pstat->{vsize
}) {
2021 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2024 my $old = $last_proc_pid_stat->{$pid};
2026 $last_proc_pid_stat->{$pid} = {
2034 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2036 if ($dtime > 1000) {
2037 my $dutime = $used - $old->{used
};
2039 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2040 $last_proc_pid_stat->{$pid} = {
2046 $d->{cpu
} = $old->{cpu
};
2050 return $res if !$full;
2052 my $qmpclient = PVE
::QMPClient-
>new();
2054 my $ballooncb = sub {
2055 my ($vmid, $resp) = @_;
2057 my $info = $resp->{'return'};
2058 return if !$info->{max_mem
};
2060 my $d = $res->{$vmid};
2062 # use memory assigned to VM
2063 $d->{maxmem
} = $info->{max_mem
};
2064 $d->{balloon
} = $info->{actual
};
2066 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2067 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2068 $d->{freemem
} = $info->{free_mem
};
2073 my $blockstatscb = sub {
2074 my ($vmid, $resp) = @_;
2075 my $data = $resp->{'return'} || [];
2076 my $totalrdbytes = 0;
2077 my $totalwrbytes = 0;
2078 for my $blockstat (@$data) {
2079 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2080 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2082 $res->{$vmid}->{diskread
} = $totalrdbytes;
2083 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2086 my $statuscb = sub {
2087 my ($vmid, $resp) = @_;
2089 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2090 # this fails if ballon driver is not loaded, so this must be
2091 # the last commnand (following command are aborted if this fails).
2092 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2094 my $status = 'unknown';
2095 if (!defined($status = $resp->{'return'}->{status
})) {
2096 warn "unable to get VM status\n";
2100 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2103 foreach my $vmid (keys %$list) {
2104 next if $opt_vmid && ($vmid ne $opt_vmid);
2105 next if !$res->{$vmid}->{pid
}; # not running
2106 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2109 $qmpclient->queue_execute();
2111 foreach my $vmid (keys %$list) {
2112 next if $opt_vmid && ($vmid ne $opt_vmid);
2113 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2120 my ($conf, $func) = @_;
2122 foreach my $ds (keys %$conf) {
2123 next if !valid_drivename
($ds);
2125 my $drive = parse_drive
($ds, $conf->{$ds});
2128 &$func($ds, $drive);
2133 my ($conf, $func) = @_;
2137 my $test_volid = sub {
2138 my ($volid, $is_cdrom) = @_;
2142 $volhash->{$volid} = $is_cdrom || 0;
2145 foreach_drive
($conf, sub {
2146 my ($ds, $drive) = @_;
2147 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2150 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2151 my $snap = $conf->{snapshots
}->{$snapname};
2152 &$test_volid($snap->{vmstate
}, 0);
2153 foreach_drive
($snap, sub {
2154 my ($ds, $drive) = @_;
2155 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2159 foreach my $volid (keys %$volhash) {
2160 &$func($volid, $volhash->{$volid});
2164 sub config_to_command
{
2165 my ($storecfg, $vmid, $conf, $defaults) = @_;
2168 my $globalFlags = [];
2169 my $machineFlags = [];
2174 my $kvmver = kvm_user_version
();
2175 my $vernum = 0; # unknown
2176 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2177 $vernum = $1*1000000+$2*1000;
2178 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2179 $vernum = $1*1000000+$2*1000+$3;
2182 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2184 my $have_ovz = -f
'/proc/vz/vestat';
2186 push @$cmd, '/usr/bin/kvm';
2188 push @$cmd, '-id', $vmid;
2192 my $qmpsocket = qmp_socket
($vmid);
2193 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2194 push @$cmd, '-mon', "chardev=qmp,mode=control";
2196 my $socket = vnc_socket
($vmid);
2197 push @$cmd, '-vnc', "unix:$socket,x509,password";
2199 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2201 push @$cmd, '-daemonize';
2203 $pciaddr = print_pci_addr
("piix3", $bridges);
2204 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2207 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2208 next if !$conf->{"usb$i"};
2211 # include usb device config
2212 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2214 # enable absolute mouse coordinates (needed by vnc)
2215 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2216 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2219 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2220 my $d = parse_hostpci
($conf->{"hostpci$i"});
2222 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2223 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2227 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2228 my $d = parse_usb_device
($conf->{"usb$i"});
2230 if ($d->{vendorid
} && $d->{productid
}) {
2231 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2232 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2233 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2238 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2239 if (my $path = $conf->{"serial$i"}) {
2240 die "no such serial device\n" if ! -c
$path;
2241 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2242 push @$devices, '-device', "isa-serial,chardev=serial$i";
2247 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2248 if (my $path = $conf->{"parallel$i"}) {
2249 die "no such parallel device\n" if ! -c
$path;
2250 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2251 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2255 my $vmname = $conf->{name
} || "vm$vmid";
2257 push @$cmd, '-name', $vmname;
2260 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2261 $sockets = $conf->{sockets
} if $conf->{sockets
};
2263 my $cores = $conf->{cores
} || 1;
2265 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2267 push @$cmd, '-cpu', $conf->{cpu
} if $conf->{cpu
};
2269 push @$cmd, '-nodefaults';
2271 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2273 my $bootindex_hash = {};
2275 foreach my $o (split(//, $bootorder)) {
2276 $bootindex_hash->{$o} = $i*100;
2280 push @$cmd, '-boot', "menu=on";
2282 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2284 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2286 my $vga = $conf->{vga
};
2288 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' || $conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2295 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2298 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2300 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2301 my $useLocaltime = $conf->{localtime};
2303 if (my $ost = $conf->{ostype
}) {
2304 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2306 if ($ost =~ m/^w/) { # windows
2307 $useLocaltime = 1 if !defined($conf->{localtime});
2309 # use time drift fix when acpi is enabled
2310 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2311 $tdf = 1 if !defined($conf->{tdf
});
2315 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2317 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2318 push @$cmd, '-no-hpet';
2322 push @$rtcFlags, 'driftfix=slew' if $tdf;
2325 push @$machineFlags, 'accel=tcg';
2327 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2330 if ($conf->{startdate
}) {
2331 push @$rtcFlags, "base=$conf->{startdate}";
2332 } elsif ($useLocaltime) {
2333 push @$rtcFlags, 'base=localtime';
2336 push @$cmd, '-S' if $conf->{freeze
};
2338 # set keyboard layout
2339 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2340 push @$cmd, '-k', $kb if $kb;
2343 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2344 #push @$cmd, '-soundhw', 'es1370';
2345 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2347 if($conf->{agent
}) {
2348 my $qgasocket = qga_socket
($vmid);
2349 my $pciaddr = print_pci_addr
("qga0", $bridges);
2350 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2351 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2352 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2355 # enable balloon by default, unless explicitly disabled
2356 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2357 $pciaddr = print_pci_addr
("balloon0", $bridges);
2358 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2361 if ($conf->{watchdog
}) {
2362 my $wdopts = parse_watchdog
($conf->{watchdog
});
2363 $pciaddr = print_pci_addr
("watchdog", $bridges);
2364 my $watchdog = $wdopts->{model
} || 'i6300esb';
2365 push @$devices, '-device', "$watchdog$pciaddr";
2366 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2370 my $scsicontroller = {};
2371 my $ahcicontroller = {};
2372 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2374 foreach_drive
($conf, sub {
2375 my ($ds, $drive) = @_;
2377 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2378 push @$vollist, $drive->{file
};
2381 $use_virtio = 1 if $ds =~ m/^virtio/;
2383 if (drive_is_cdrom
($drive)) {
2384 if ($bootindex_hash->{d
}) {
2385 $drive->{bootindex
} = $bootindex_hash->{d
};
2386 $bootindex_hash->{d
} += 1;
2389 if ($bootindex_hash->{c
}) {
2390 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2391 $bootindex_hash->{c
} += 1;
2395 if ($drive->{interface
} eq 'scsi') {
2397 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2398 my $controller = int($drive->{index} / $maxdev);
2399 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2400 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2401 $scsicontroller->{$controller}=1;
2404 if ($drive->{interface
} eq 'sata') {
2405 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2406 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2407 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2408 $ahcicontroller->{$controller}=1;
2411 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2412 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2415 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2417 for (my $i = 0; $i < $MAX_NETS; $i++) {
2418 next if !$conf->{"net$i"};
2419 my $d = parse_net
($conf->{"net$i"});
2422 $use_virtio = 1 if $d->{model
} eq 'virtio';
2424 if ($bootindex_hash->{n
}) {
2425 $d->{bootindex
} = $bootindex_hash->{n
};
2426 $bootindex_hash->{n
} += 1;
2429 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2430 push @$devices, '-netdev', $netdevfull;
2432 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2433 push @$devices, '-device', $netdevicefull;
2437 while (my ($k, $v) = each %$bridges) {
2438 $pciaddr = print_pci_addr
("pci.$k");
2439 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2443 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2444 # when the VM uses virtio devices.
2445 if (!$use_virtio && $have_ovz) {
2447 my $cpuunits = defined($conf->{cpuunits
}) ?
2448 $conf->{cpuunits
} : $defaults->{cpuunits
};
2450 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2452 # fixme: cpulimit is currently ignored
2453 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2457 if ($conf->{args
}) {
2458 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2462 push @$cmd, @$devices;
2463 push @$cmd, '-rtc', join(',', @$rtcFlags)
2464 if scalar(@$rtcFlags);
2465 push @$cmd, '-machine', join(',', @$machineFlags)
2466 if scalar(@$machineFlags);
2467 push @$cmd, '-global', join(',', @$globalFlags)
2468 if scalar(@$globalFlags);
2470 return wantarray ?
($cmd, $vollist) : $cmd;
2475 return "${var_run_tmpdir}/$vmid.vnc";
2480 return "${var_run_tmpdir}/$vmid.qmp";
2485 return "${var_run_tmpdir}/$vmid.qga";
2490 return "${var_run_tmpdir}/$vmid.pid";
2493 sub next_migrate_port
{
2495 for (my $p = 60000; $p < 60010; $p++) {
2497 my $sock = IO
::Socket
::INET-
>new(Listen
=> 5,
2498 LocalAddr
=> 'localhost',
2509 die "unable to find free migration port";
2512 sub vm_devices_list
{
2515 my $res = vm_mon_cmd
($vmid, 'query-pci');
2518 foreach my $pcibus (@$res) {
2519 foreach my $device (@{$pcibus->{devices
}}) {
2520 next if !$device->{'qdev_id'};
2521 $devices->{$device->{'qdev_id'}} = $device;
2529 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2531 return 1 if !check_running
($vmid);
2533 if ($deviceid eq 'tablet') {
2534 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2535 qemu_deviceadd
($vmid, $devicefull);
2539 return 1 if !$conf->{hotplug
};
2541 my $devices_list = vm_devices_list
($vmid);
2542 return 1 if defined($devices_list->{$deviceid});
2544 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2546 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2547 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2548 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2549 qemu_deviceadd
($vmid, $devicefull);
2550 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2551 qemu_drivedel
($vmid, $deviceid);
2556 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2557 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2558 my $pciaddr = print_pci_addr
($deviceid);
2559 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2560 qemu_deviceadd
($vmid, $devicefull);
2561 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2564 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2565 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2566 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2567 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2568 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2569 if(!qemu_deviceadd
($vmid, $devicefull)) {
2570 qemu_drivedel
($vmid, $deviceid);
2575 if ($deviceid =~ m/^(net)(\d+)$/) {
2576 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2577 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2578 qemu_deviceadd
($vmid, $netdevicefull);
2579 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2580 qemu_netdevdel
($vmid, $deviceid);
2585 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2587 my $pciaddr = print_pci_addr
($deviceid);
2588 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2589 qemu_deviceadd
($vmid, $devicefull);
2590 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2596 sub vm_deviceunplug
{
2597 my ($vmid, $conf, $deviceid) = @_;
2599 return 1 if !check_running
($vmid);
2601 if ($deviceid eq 'tablet') {
2602 qemu_devicedel
($vmid, $deviceid);
2606 return 1 if !$conf->{hotplug
};
2608 my $devices_list = vm_devices_list
($vmid);
2609 return 1 if !defined($devices_list->{$deviceid});
2611 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2613 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2614 qemu_devicedel
($vmid, $deviceid);
2615 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2616 return undef if !qemu_drivedel
($vmid, $deviceid);
2619 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2620 return undef if !qemu_devicedel
($vmid, $deviceid);
2623 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2624 return undef if !qemu_devicedel
($vmid, $deviceid);
2625 return undef if !qemu_drivedel
($vmid, $deviceid);
2628 if ($deviceid =~ m/^(net)(\d+)$/) {
2629 qemu_devicedel
($vmid, $deviceid);
2630 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2631 return undef if !qemu_netdevdel
($vmid, $deviceid);
2637 sub qemu_deviceadd
{
2638 my ($vmid, $devicefull) = @_;
2640 $devicefull = "driver=".$devicefull;
2641 my %options = split(/[=,]/, $devicefull);
2643 vm_mon_cmd
($vmid, "device_add" , %options);
2647 sub qemu_devicedel
{
2648 my($vmid, $deviceid) = @_;
2649 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2654 my($storecfg, $vmid, $device) = @_;
2656 my $drive = print_drive_full
($storecfg, $vmid, $device);
2657 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2658 # If the command succeeds qemu prints: "OK"
2659 if ($ret !~ m/OK/s) {
2660 syslog
("err", "adding drive failed: $ret");
2667 my($vmid, $deviceid) = @_;
2669 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2671 if ($ret =~ m/Device \'.*?\' not found/s) {
2672 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2674 elsif ($ret ne "") {
2675 syslog
("err", "deleting drive $deviceid failed : $ret");
2681 sub qemu_deviceaddverify
{
2682 my ($vmid,$deviceid) = @_;
2684 for (my $i = 0; $i <= 5; $i++) {
2685 my $devices_list = vm_devices_list
($vmid);
2686 return 1 if defined($devices_list->{$deviceid});
2689 syslog
("err", "error on hotplug device $deviceid");
2694 sub qemu_devicedelverify
{
2695 my ($vmid,$deviceid) = @_;
2697 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2698 for (my $i = 0; $i <= 5; $i++) {
2699 my $devices_list = vm_devices_list
($vmid);
2700 return 1 if !defined($devices_list->{$deviceid});
2703 syslog
("err", "error on hot-unplugging device $deviceid");
2707 sub qemu_findorcreatescsihw
{
2708 my ($storecfg, $conf, $vmid, $device) = @_;
2710 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2711 my $controller = int($device->{index} / $maxdev);
2712 my $scsihwid="scsihw$controller";
2713 my $devices_list = vm_devices_list
($vmid);
2715 if(!defined($devices_list->{$scsihwid})) {
2716 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2721 sub qemu_bridgeadd
{
2722 my ($storecfg, $conf, $vmid, $device) = @_;
2725 my $bridgeid = undef;
2726 print_pci_addr
($device, $bridges);
2728 while (my ($k, $v) = each %$bridges) {
2731 return if $bridgeid < 1;
2732 my $bridge = "pci.$bridgeid";
2733 my $devices_list = vm_devices_list
($vmid);
2735 if(!defined($devices_list->{$bridge})) {
2736 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2741 sub qemu_netdevadd
{
2742 my ($vmid, $conf, $device, $deviceid) = @_;
2744 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2745 my %options = split(/[=,]/, $netdev);
2747 vm_mon_cmd
($vmid, "netdev_add", %options);
2751 sub qemu_netdevdel
{
2752 my ($vmid, $deviceid) = @_;
2754 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2758 sub qemu_block_set_io_throttle
{
2759 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2761 return if !check_running
($vmid) ;
2764 $bps_rd = 0 if !$bps_rd;
2765 $bps_wr = 0 if !$bps_wr;
2766 $iops = 0 if !$iops;
2767 $iops_rd = 0 if !$iops_rd;
2768 $iops_wr = 0 if !$iops_wr;
2770 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));
2774 # old code, only used to shutdown old VM after update
2776 my ($fh, $timeout) = @_;
2778 my $sel = new IO
::Select
;
2785 while (scalar (@ready = $sel->can_read($timeout))) {
2787 if ($count = $fh->sysread($buf, 8192)) {
2788 if ($buf =~ /^(.*)\(qemu\) $/s) {
2795 if (!defined($count)) {
2802 die "monitor read timeout\n" if !scalar(@ready);
2807 # old code, only used to shutdown old VM after update
2808 sub vm_monitor_command
{
2809 my ($vmid, $cmdstr, $nocheck) = @_;
2814 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2816 my $sname = "${var_run_tmpdir}/$vmid.mon";
2818 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2819 die "unable to connect to VM $vmid socket - $!\n";
2823 # hack: migrate sometime blocks the monitor (when migrate_downtime
2825 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2826 $timeout = 60*60; # 1 hour
2830 my $data = __read_avail
($sock, $timeout);
2832 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2833 die "got unexpected qemu monitor banner\n";
2836 my $sel = new IO
::Select
;
2839 if (!scalar(my @ready = $sel->can_write($timeout))) {
2840 die "monitor write error - timeout";
2843 my $fullcmd = "$cmdstr\r";
2845 # syslog('info', "VM $vmid monitor command: $cmdstr");
2848 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2849 die "monitor write error - $!";
2852 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2856 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2857 $timeout = 60*60; # 1 hour
2858 } elsif ($cmdstr =~ m/^(eject|change)/) {
2859 $timeout = 60; # note: cdrom mount command is slow
2861 if ($res = __read_avail
($sock, $timeout)) {
2863 my @lines = split("\r?\n", $res);
2865 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2867 $res = join("\n", @lines);
2875 syslog
("err", "VM $vmid monitor command failed - $err");
2882 sub qemu_block_resize
{
2883 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2885 my $running = check_running
($vmid);
2887 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2889 return if !$running;
2891 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2895 sub qemu_volume_snapshot
{
2896 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2898 my $running = check_running
($vmid);
2900 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2902 return if !$running;
2904 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2908 sub qemu_volume_snapshot_delete
{
2909 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2911 my $running = check_running
($vmid);
2913 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2915 return if !$running;
2917 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
2923 #need to impplement call to qemu-ga
2926 sub qga_unfreezefs
{
2929 #need to impplement call to qemu-ga
2933 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused) = @_;
2935 lock_config
($vmid, sub {
2936 my $conf = load_config
($vmid, $migratedfrom);
2938 die "you can't start a vm if it's a template\n" if is_template
($conf);
2940 check_lock
($conf) if !$skiplock;
2942 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
2944 my $defaults = load_defaults
();
2946 # set environment variable useful inside network script
2947 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
2949 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults);
2951 my $migrate_port = 0;
2954 if ($statefile eq 'tcp') {
2955 $migrate_port = next_migrate_port
();
2956 my $migrate_uri = "tcp:localhost:${migrate_port}";
2957 push @$cmd, '-incoming', $migrate_uri;
2960 push @$cmd, '-loadstate', $statefile;
2967 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2968 my $d = parse_hostpci
($conf->{"hostpci$i"});
2970 my $info = pci_device_info
("0000:$d->{pciid}");
2971 die "IOMMU not present\n" if !check_iommu_support
();
2972 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2973 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
2974 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
2977 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
2979 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
2982 die "start failed: $err" if $err;
2984 print "migration listens on port $migrate_port\n" if $migrate_port;
2986 if ($statefile && $statefile ne 'tcp') {
2987 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
2992 my $capabilities = {};
2993 $capabilities->{capability
} = "xbzrle";
2994 $capabilities->{state} = JSON
::true
;
2995 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
2999 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3000 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3001 if $conf->{balloon
};
3002 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3003 path
=> "machine/peripheral/balloon0",
3004 property
=> "guest-stats-polling-interval",
3012 my ($vmid, $execute, %params) = @_;
3014 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3015 vm_qmp_command
($vmid, $cmd);
3018 sub vm_mon_cmd_nocheck
{
3019 my ($vmid, $execute, %params) = @_;
3021 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3022 vm_qmp_command
($vmid, $cmd, 1);
3025 sub vm_qmp_command
{
3026 my ($vmid, $cmd, $nocheck) = @_;
3031 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3032 $timeout = $cmd->{arguments
}->{timeout
};
3033 delete $cmd->{arguments
}->{timeout
};
3037 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3038 my $sname = qmp_socket
($vmid);
3040 my $qmpclient = PVE
::QMPClient-
>new();
3042 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3043 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3044 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3045 if scalar(%{$cmd->{arguments
}});
3046 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3048 die "unable to open monitor socket\n";
3052 syslog
("err", "VM $vmid qmp command failed - $err");
3059 sub vm_human_monitor_command
{
3060 my ($vmid, $cmdline) = @_;
3065 execute
=> 'human-monitor-command',
3066 arguments
=> { 'command-line' => $cmdline},
3069 return vm_qmp_command
($vmid, $cmd);
3072 sub vm_commandline
{
3073 my ($storecfg, $vmid) = @_;
3075 my $conf = load_config
($vmid);
3077 my $defaults = load_defaults
();
3079 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3081 return join(' ', @$cmd);
3085 my ($vmid, $skiplock) = @_;
3087 lock_config
($vmid, sub {
3089 my $conf = load_config
($vmid);
3091 check_lock
($conf) if !$skiplock;
3093 vm_mon_cmd
($vmid, "system_reset");
3097 sub get_vm_volumes
{
3101 foreach_volid
($conf, sub {
3102 my ($volid, $is_cdrom) = @_;
3104 return if $volid =~ m
|^/|;
3106 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3109 push @$vollist, $volid;
3115 sub vm_stop_cleanup
{
3116 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3119 fairsched_rmnod
($vmid); # try to destroy group
3122 my $vollist = get_vm_volumes
($conf);
3123 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3126 foreach my $ext (qw(mon qmp pid vnc qga)) {
3127 unlink "/var/run/qemu-server/${vmid}.$ext";
3130 warn $@ if $@; # avoid errors - just warn
3133 # Note: use $nockeck to skip tests if VM configuration file exists.
3134 # We need that when migration VMs to other nodes (files already moved)
3135 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3137 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3139 $force = 1 if !defined($force) && !$shutdown;
3142 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3143 kill 15, $pid if $pid;
3144 my $conf = load_config
($vmid, $migratedfrom);
3145 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3149 lock_config
($vmid, sub {
3151 my $pid = check_running
($vmid, $nocheck);
3156 $conf = load_config
($vmid);
3157 check_lock
($conf) if !$skiplock;
3158 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3159 my $opts = parse_startup
($conf->{startup
});
3160 $timeout = $opts->{down
} if $opts->{down
};
3164 $timeout = 60 if !defined($timeout);
3168 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3171 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3178 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3183 if ($count >= $timeout) {
3185 warn "VM still running - terminating now with SIGTERM\n";
3188 die "VM quit/powerdown failed - got timeout\n";
3191 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3196 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3199 die "VM quit/powerdown failed\n";
3207 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3212 if ($count >= $timeout) {
3213 warn "VM still running - terminating now with SIGKILL\n";
3218 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3223 my ($vmid, $skiplock) = @_;
3225 lock_config
($vmid, sub {
3227 my $conf = load_config
($vmid);
3229 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3231 vm_mon_cmd
($vmid, "stop");
3236 my ($vmid, $skiplock) = @_;
3238 lock_config
($vmid, sub {
3240 my $conf = load_config
($vmid);
3242 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3244 vm_mon_cmd
($vmid, "cont");
3249 my ($vmid, $skiplock, $key) = @_;
3251 lock_config
($vmid, sub {
3253 my $conf = load_config
($vmid);
3255 # there is no qmp command, so we use the human monitor command
3256 vm_human_monitor_command
($vmid, "sendkey $key");
3261 my ($storecfg, $vmid, $skiplock) = @_;
3263 lock_config
($vmid, sub {
3265 my $conf = load_config
($vmid);
3267 check_lock
($conf) if !$skiplock;
3269 if (!check_running
($vmid)) {
3270 fairsched_rmnod
($vmid); # try to destroy group
3271 destroy_vm
($storecfg, $vmid);
3273 die "VM $vmid is running - destroy failed\n";
3281 my ($filename, $buf) = @_;
3283 my $fh = IO
::File-
>new($filename, "w");
3284 return undef if !$fh;
3286 my $res = print $fh $buf;
3293 sub pci_device_info
{
3298 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3299 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3301 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3302 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3304 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3305 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3307 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3308 return undef if !defined($product) || $product !~ s/^0x//;
3313 product
=> $product,
3319 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3328 my $name = $dev->{name
};
3330 my $fn = "$pcisysfs/devices/$name/reset";
3332 return file_write
($fn, "1");
3335 sub pci_dev_bind_to_stub
{
3338 my $name = $dev->{name
};
3340 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3341 return 1 if -d
$testdir;
3343 my $data = "$dev->{vendor} $dev->{product}";
3344 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3346 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3347 if (!file_write
($fn, $name)) {
3348 return undef if -f
$fn;
3351 $fn = "$pcisysfs/drivers/pci-stub/bind";
3352 if (! -d
$testdir) {
3353 return undef if !file_write
($fn, $name);
3359 sub print_pci_addr
{
3360 my ($id, $bridges) = @_;
3364 piix3
=> { bus
=> 0, addr
=> 1 },
3365 #addr2 : first videocard
3366 balloon0
=> { bus
=> 0, addr
=> 3 },
3367 watchdog
=> { bus
=> 0, addr
=> 4 },
3368 scsihw0
=> { bus
=> 0, addr
=> 5 },
3369 scsihw1
=> { bus
=> 0, addr
=> 6 },
3370 ahci0
=> { bus
=> 0, addr
=> 7 },
3371 qga0
=> { bus
=> 0, addr
=> 8 },
3372 virtio0
=> { bus
=> 0, addr
=> 10 },
3373 virtio1
=> { bus
=> 0, addr
=> 11 },
3374 virtio2
=> { bus
=> 0, addr
=> 12 },
3375 virtio3
=> { bus
=> 0, addr
=> 13 },
3376 virtio4
=> { bus
=> 0, addr
=> 14 },
3377 virtio5
=> { bus
=> 0, addr
=> 15 },
3378 hostpci0
=> { bus
=> 0, addr
=> 16 },
3379 hostpci1
=> { bus
=> 0, addr
=> 17 },
3380 net0
=> { bus
=> 0, addr
=> 18 },
3381 net1
=> { bus
=> 0, addr
=> 19 },
3382 net2
=> { bus
=> 0, addr
=> 20 },
3383 net3
=> { bus
=> 0, addr
=> 21 },
3384 net4
=> { bus
=> 0, addr
=> 22 },
3385 net5
=> { bus
=> 0, addr
=> 23 },
3386 #addr29 : usb-host (pve-usb.cfg)
3387 'pci.1' => { bus
=> 0, addr
=> 30 },
3388 'pci.2' => { bus
=> 0, addr
=> 31 },
3389 'net6' => { bus
=> 1, addr
=> 1 },
3390 'net7' => { bus
=> 1, addr
=> 2 },
3391 'net8' => { bus
=> 1, addr
=> 3 },
3392 'net9' => { bus
=> 1, addr
=> 4 },
3393 'net10' => { bus
=> 1, addr
=> 5 },
3394 'net11' => { bus
=> 1, addr
=> 6 },
3395 'net12' => { bus
=> 1, addr
=> 7 },
3396 'net13' => { bus
=> 1, addr
=> 8 },
3397 'net14' => { bus
=> 1, addr
=> 9 },
3398 'net15' => { bus
=> 1, addr
=> 10 },
3399 'net16' => { bus
=> 1, addr
=> 11 },
3400 'net17' => { bus
=> 1, addr
=> 12 },
3401 'net18' => { bus
=> 1, addr
=> 13 },
3402 'net19' => { bus
=> 1, addr
=> 14 },
3403 'net20' => { bus
=> 1, addr
=> 15 },
3404 'net21' => { bus
=> 1, addr
=> 16 },
3405 'net22' => { bus
=> 1, addr
=> 17 },
3406 'net23' => { bus
=> 1, addr
=> 18 },
3407 'net24' => { bus
=> 1, addr
=> 19 },
3408 'net25' => { bus
=> 1, addr
=> 20 },
3409 'net26' => { bus
=> 1, addr
=> 21 },
3410 'net27' => { bus
=> 1, addr
=> 22 },
3411 'net28' => { bus
=> 1, addr
=> 23 },
3412 'net29' => { bus
=> 1, addr
=> 24 },
3413 'net30' => { bus
=> 1, addr
=> 25 },
3414 'net31' => { bus
=> 1, addr
=> 26 },
3415 'virtio6' => { bus
=> 2, addr
=> 1 },
3416 'virtio7' => { bus
=> 2, addr
=> 2 },
3417 'virtio8' => { bus
=> 2, addr
=> 3 },
3418 'virtio9' => { bus
=> 2, addr
=> 4 },
3419 'virtio10' => { bus
=> 2, addr
=> 5 },
3420 'virtio11' => { bus
=> 2, addr
=> 6 },
3421 'virtio12' => { bus
=> 2, addr
=> 7 },
3422 'virtio13' => { bus
=> 2, addr
=> 8 },
3423 'virtio14' => { bus
=> 2, addr
=> 9 },
3424 'virtio15' => { bus
=> 2, addr
=> 10 },
3427 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3428 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3429 my $bus = $devices->{$id}->{bus
};
3430 $res = ",bus=pci.$bus,addr=$addr";
3431 $bridges->{$bus} = 1 if $bridges;
3437 # vzdump restore implementaion
3439 sub tar_archive_read_firstfile
{
3440 my $archive = shift;
3442 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3444 # try to detect archive type first
3445 my $pid = open (TMP
, "tar tf '$archive'|") ||
3446 die "unable to open file '$archive'\n";
3447 my $firstfile = <TMP
>;
3451 die "ERROR: archive contaions no data\n" if !$firstfile;
3457 sub tar_restore_cleanup
{
3458 my ($storecfg, $statfile) = @_;
3460 print STDERR
"starting cleanup\n";
3462 if (my $fd = IO
::File-
>new($statfile, "r")) {
3463 while (defined(my $line = <$fd>)) {
3464 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3467 if ($volid =~ m
|^/|) {
3468 unlink $volid || die 'unlink failed\n';
3470 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3472 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3474 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3476 print STDERR
"unable to parse line in statfile - $line";
3483 sub restore_archive
{
3484 my ($archive, $vmid, $user, $opts) = @_;
3486 my $format = $opts->{format
};
3489 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3490 $format = 'tar' if !$format;
3492 } elsif ($archive =~ m/\.tar$/) {
3493 $format = 'tar' if !$format;
3494 } elsif ($archive =~ m/.tar.lzo$/) {
3495 $format = 'tar' if !$format;
3497 } elsif ($archive =~ m/\.vma$/) {
3498 $format = 'vma' if !$format;
3499 } elsif ($archive =~ m/\.vma\.gz$/) {
3500 $format = 'vma' if !$format;
3502 } elsif ($archive =~ m/\.vma\.lzo$/) {
3503 $format = 'vma' if !$format;
3506 $format = 'vma' if !$format; # default
3509 # try to detect archive format
3510 if ($format eq 'tar') {
3511 return restore_tar_archive
($archive, $vmid, $user, $opts);
3513 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3517 sub restore_update_config_line
{
3518 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3520 return if $line =~ m/^\#qmdump\#/;
3521 return if $line =~ m/^\#vzdump\#/;
3522 return if $line =~ m/^lock:/;
3523 return if $line =~ m/^unused\d+:/;
3524 return if $line =~ m/^parent:/;
3526 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3527 # try to convert old 1.X settings
3528 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3529 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3530 my ($model, $macaddr) = split(/\=/, $devconfig);
3531 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3534 bridge
=> "vmbr$ind",
3535 macaddr
=> $macaddr,
3537 my $netstr = print_net
($net);
3539 print $outfd "net$cookie->{netcount}: $netstr\n";
3540 $cookie->{netcount
}++;
3542 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3543 my ($id, $netstr) = ($1, $2);
3544 my $net = parse_net
($netstr);
3545 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3546 $netstr = print_net
($net);
3547 print $outfd "$id: $netstr\n";
3548 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3551 if ($line =~ m/backup=no/) {
3552 print $outfd "#$line";
3553 } elsif ($virtdev && $map->{$virtdev}) {
3554 my $di = parse_drive
($virtdev, $value);
3555 $di->{file
} = $map->{$virtdev};
3556 $value = print_drive
($vmid, $di);
3557 print $outfd "$virtdev: $value\n";
3567 my ($cfg, $vmid) = @_;
3569 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3571 my $volid_hash = {};
3572 foreach my $storeid (keys %$info) {
3573 foreach my $item (@{$info->{$storeid}}) {
3574 next if !($item->{volid
} && $item->{size
});
3575 $volid_hash->{$item->{volid
}} = $item;
3582 sub update_disksize
{
3583 my ($vmid, $conf, $volid_hash) = @_;
3590 foreach my $opt (keys %$conf) {
3591 if (valid_drivename
($opt)) {
3592 my $drive = parse_drive
($opt, $conf->{$opt});
3593 my $volid = $drive->{file
};
3596 $used->{$volid} = 1;
3598 next if drive_is_cdrom
($drive);
3599 next if !$volid_hash->{$volid};
3601 $drive->{size
} = $volid_hash->{$volid}->{size
};
3603 $conf->{$opt} = print_drive
($vmid, $drive);
3607 foreach my $volid (sort keys %$volid_hash) {
3608 next if $volid =~ m/vm-$vmid-state-/;
3609 next if $used->{$volid};
3611 add_unused_volume
($conf, $volid);
3618 my ($vmid, $nolock) = @_;
3620 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3622 my $volid_hash = scan_volids
($cfg, $vmid);
3624 my $updatefn = sub {
3627 my $conf = load_config
($vmid);
3632 foreach my $volid (keys %$volid_hash) {
3633 my $info = $volid_hash->{$volid};
3634 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3637 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3639 update_config_nolock
($vmid, $conf, 1) if $changes;
3642 if (defined($vmid)) {
3646 lock_config
($vmid, $updatefn, $vmid);
3649 my $vmlist = config_list
();
3650 foreach my $vmid (keys %$vmlist) {
3654 lock_config
($vmid, $updatefn, $vmid);
3660 sub restore_vma_archive
{
3661 my ($archive, $vmid, $user, $opts, $comp) = @_;
3663 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3664 my $readfrom = $archive;
3669 my $qarchive = PVE
::Tools
::shellquote
($archive);
3670 if ($comp eq 'gzip') {
3671 $uncomp = "zcat $qarchive|";
3672 } elsif ($comp eq 'lzop') {
3673 $uncomp = "lzop -d -c $qarchive|";
3675 die "unknown compression method '$comp'\n";
3680 my $tmpdir = "/var/tmp/vzdumptmp$$";
3683 # disable interrupts (always do cleanups)
3684 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3685 warn "got interrupt - ignored\n";
3688 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3689 POSIX
::mkfifo
($mapfifo, 0600);
3692 my $openfifo = sub {
3693 open($fifofh, '>', $mapfifo) || die $!;
3696 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3703 my $rpcenv = PVE
::RPCEnvironment
::get
();
3705 my $conffile = config_file
($vmid);
3706 my $tmpfn = "$conffile.$$.tmp";
3708 # Note: $oldconf is undef if VM does not exists
3709 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3711 my $print_devmap = sub {
3712 my $virtdev_hash = {};
3714 my $cfgfn = "$tmpdir/qemu-server.conf";
3716 # we can read the config - that is already extracted
3717 my $fh = IO
::File-
>new($cfgfn, "r") ||
3718 "unable to read qemu-server.conf - $!\n";
3720 while (defined(my $line = <$fh>)) {
3721 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3722 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3723 die "archive does not contain data for drive '$virtdev'\n"
3724 if !$devinfo->{$devname};
3725 if (defined($opts->{storage
})) {
3726 $storeid = $opts->{storage
} || 'local';
3727 } elsif (!$storeid) {
3730 $format = 'raw' if !$format;
3731 $devinfo->{$devname}->{devname
} = $devname;
3732 $devinfo->{$devname}->{virtdev
} = $virtdev;
3733 $devinfo->{$devname}->{format
} = $format;
3734 $devinfo->{$devname}->{storeid
} = $storeid;
3736 # check permission on storage
3737 my $pool = $opts->{pool
}; # todo: do we need that?
3738 if ($user ne 'root@pam') {
3739 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3742 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3746 foreach my $devname (keys %$devinfo) {
3747 die "found no device mapping information for device '$devname'\n"
3748 if !$devinfo->{$devname}->{virtdev
};
3751 my $cfg = cfs_read_file
('storage.cfg');
3753 # create empty/temp config
3755 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3756 foreach_drive
($oldconf, sub {
3757 my ($ds, $drive) = @_;
3759 return if drive_is_cdrom
($drive);
3761 my $volid = $drive->{file
};
3763 return if !$volid || $volid =~ m
|^/|;
3765 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3766 return if !$path || !$owner || ($owner != $vmid);
3768 # Note: only delete disk we want to restore
3769 # other volumes will become unused
3770 if ($virtdev_hash->{$ds}) {
3771 PVE
::Storage
::vdisk_free
($cfg, $volid);
3777 foreach my $virtdev (sort keys %$virtdev_hash) {
3778 my $d = $virtdev_hash->{$virtdev};
3779 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3780 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3781 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3782 $d->{format
}, undef, $alloc_size);
3783 print STDERR
"new volume ID is '$volid'\n";
3784 $d->{volid
} = $volid;
3785 my $path = PVE
::Storage
::path
($cfg, $volid);
3787 my $write_zeros = 1;
3788 # fixme: what other storages types initialize volumes with zero?
3789 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' ||
3790 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
3794 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3796 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3797 $map->{$virtdev} = $volid;
3800 $fh->seek(0, 0) || die "seek failed - $!\n";
3802 my $outfd = new IO
::File
($tmpfn, "w") ||
3803 die "unable to write config for VM $vmid\n";
3805 my $cookie = { netcount
=> 0 };
3806 while (defined(my $line = <$fh>)) {
3807 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3816 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3817 die "interrupted by signal\n";
3819 local $SIG{ALRM
} = sub { die "got timeout\n"; };
3821 $oldtimeout = alarm($timeout);
3828 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
3829 my ($dev_id, $size, $devname) = ($1, $2, $3);
3830 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
3831 } elsif ($line =~ m/^CTIME: /) {
3833 print $fifofh "done\n";
3834 my $tmp = $oldtimeout || 0;
3835 $oldtimeout = undef;
3841 print "restore vma archive: $cmd\n";
3842 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
3846 alarm($oldtimeout) if $oldtimeout;
3854 my $cfg = cfs_read_file
('storage.cfg');
3855 foreach my $devname (keys %$devinfo) {
3856 my $volid = $devinfo->{$devname}->{volid
};
3859 if ($volid =~ m
|^/|) {
3860 unlink $volid || die 'unlink failed\n';
3862 PVE
::Storage
::vdisk_free
($cfg, $volid);
3864 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3866 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3873 rename($tmpfn, $conffile) ||
3874 die "unable to commit configuration file '$conffile'\n";
3876 PVE
::Cluster
::cfs_update
(); # make sure we read new file
3878 eval { rescan
($vmid, 1); };
3882 sub restore_tar_archive
{
3883 my ($archive, $vmid, $user, $opts) = @_;
3885 if ($archive ne '-') {
3886 my $firstfile = tar_archive_read_firstfile
($archive);
3887 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3888 if $firstfile ne 'qemu-server.conf';
3891 my $storecfg = cfs_read_file
('storage.cfg');
3893 # destroy existing data - keep empty config
3894 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
3895 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
3897 my $tocmd = "/usr/lib/qemu-server/qmextract";
3899 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
3900 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
3901 $tocmd .= ' --prealloc' if $opts->{prealloc
};
3902 $tocmd .= ' --info' if $opts->{info
};
3904 # tar option "xf" does not autodetect compression when read from STDIN,
3905 # so we pipe to zcat
3906 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
3907 PVE
::Tools
::shellquote
("--to-command=$tocmd");
3909 my $tmpdir = "/var/tmp/vzdumptmp$$";
3912 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
3913 local $ENV{VZDUMP_VMID
} = $vmid;
3914 local $ENV{VZDUMP_USER
} = $user;
3916 my $conffile = config_file
($vmid);
3917 my $tmpfn = "$conffile.$$.tmp";
3919 # disable interrupts (always do cleanups)
3920 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3921 print STDERR
"got interrupt - ignored\n";
3926 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3927 die "interrupted by signal\n";
3930 if ($archive eq '-') {
3931 print "extracting archive from STDIN\n";
3932 run_command
($cmd, input
=> "<&STDIN");
3934 print "extracting archive '$archive'\n";
3938 return if $opts->{info
};
3942 my $statfile = "$tmpdir/qmrestore.stat";
3943 if (my $fd = IO
::File-
>new($statfile, "r")) {
3944 while (defined (my $line = <$fd>)) {
3945 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3946 $map->{$1} = $2 if $1;
3948 print STDERR
"unable to parse line in statfile - $line\n";
3954 my $confsrc = "$tmpdir/qemu-server.conf";
3956 my $srcfd = new IO
::File
($confsrc, "r") ||
3957 die "unable to open file '$confsrc'\n";
3959 my $outfd = new IO
::File
($tmpfn, "w") ||
3960 die "unable to write config for VM $vmid\n";
3962 my $cookie = { netcount
=> 0 };
3963 while (defined (my $line = <$srcfd>)) {
3964 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3976 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
3983 rename $tmpfn, $conffile ||
3984 die "unable to commit configuration file '$conffile'\n";
3986 PVE
::Cluster
::cfs_update
(); # make sure we read new file
3988 eval { rescan
($vmid, 1); };
3993 # Internal snapshots
3995 # NOTE: Snapshot create/delete involves several non-atomic
3996 # action, and can take a long time.
3997 # So we try to avoid locking the file and use 'lock' variable
3998 # inside the config file instead.
4000 my $snapshot_copy_config = sub {
4001 my ($source, $dest) = @_;
4003 foreach my $k (keys %$source) {
4004 next if $k eq 'snapshots';
4005 next if $k eq 'snapstate';
4006 next if $k eq 'snaptime';
4007 next if $k eq 'vmstate';
4008 next if $k eq 'lock';
4009 next if $k eq 'digest';
4010 next if $k eq 'description';
4011 next if $k =~ m/^unused\d+$/;
4013 $dest->{$k} = $source->{$k};
4017 my $snapshot_apply_config = sub {
4018 my ($conf, $snap) = @_;
4020 # copy snapshot list
4022 snapshots
=> $conf->{snapshots
},
4025 # keep description and list of unused disks
4026 foreach my $k (keys %$conf) {
4027 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4028 $newconf->{$k} = $conf->{$k};
4031 &$snapshot_copy_config($snap, $newconf);
4036 sub foreach_writable_storage
{
4037 my ($conf, $func) = @_;
4041 foreach my $ds (keys %$conf) {
4042 next if !valid_drivename
($ds);
4044 my $drive = parse_drive
($ds, $conf->{$ds});
4046 next if drive_is_cdrom
($drive);
4048 my $volid = $drive->{file
};
4050 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4051 $sidhash->{$sid} = $sid if $sid;
4054 foreach my $sid (sort keys %$sidhash) {
4059 my $alloc_vmstate_volid = sub {
4060 my ($storecfg, $vmid, $conf, $snapname) = @_;
4062 # Note: we try to be smart when selecting a $target storage
4066 # search shared storage first
4067 foreach_writable_storage
($conf, sub {
4069 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4070 return if !$scfg->{shared
};
4072 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4076 # now search local storage
4077 foreach_writable_storage
($conf, sub {
4079 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4080 return if $scfg->{shared
};
4082 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4086 $target = 'local' if !$target;
4088 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4089 # we abort live save after $conf->{memory}, so we need at max twice that space
4090 my $size = $conf->{memory
}*2 + $driver_state_size;
4092 my $name = "vm-$vmid-state-$snapname";
4093 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4094 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4095 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4100 my $snapshot_prepare = sub {
4101 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4105 my $updatefn = sub {
4107 my $conf = load_config
($vmid);
4109 die "you can't take a snapshot if it's a template\n"
4110 if is_template
($conf);
4114 $conf->{lock} = 'snapshot';
4116 die "snapshot name '$snapname' already used\n"
4117 if defined($conf->{snapshots
}->{$snapname});
4119 my $storecfg = PVE
::Storage
::config
();
4120 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4122 $snap = $conf->{snapshots
}->{$snapname} = {};
4124 if ($save_vmstate && check_running
($vmid)) {
4125 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4128 &$snapshot_copy_config($conf, $snap);
4130 $snap->{snapstate
} = "prepare";
4131 $snap->{snaptime
} = time();
4132 $snap->{description
} = $comment if $comment;
4134 update_config_nolock
($vmid, $conf, 1);
4137 lock_config
($vmid, $updatefn);
4142 my $snapshot_commit = sub {
4143 my ($vmid, $snapname) = @_;
4145 my $updatefn = sub {
4147 my $conf = load_config
($vmid);
4149 die "missing snapshot lock\n"
4150 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4152 my $snap = $conf->{snapshots
}->{$snapname};
4154 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4156 die "wrong snapshot state\n"
4157 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4159 delete $snap->{snapstate
};
4160 delete $conf->{lock};
4162 my $newconf = &$snapshot_apply_config($conf, $snap);
4164 $newconf->{parent
} = $snapname;
4166 update_config_nolock
($vmid, $newconf, 1);
4169 lock_config
($vmid, $updatefn);
4172 sub snapshot_rollback
{
4173 my ($vmid, $snapname) = @_;
4179 my $storecfg = PVE
::Storage
::config
();
4181 my $updatefn = sub {
4183 my $conf = load_config
($vmid);
4185 die "you can't rollback if vm is a template\n" if is_template
($conf);
4187 $snap = $conf->{snapshots
}->{$snapname};
4189 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4191 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4192 if $snap->{snapstate
};
4196 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4199 die "unable to rollback vm $vmid: vm is running\n"
4200 if check_running
($vmid);
4203 $conf->{lock} = 'rollback';
4205 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4206 delete $conf->{lock};
4210 # copy snapshot config to current config
4211 $conf = &$snapshot_apply_config($conf, $snap);
4212 $conf->{parent
} = $snapname;
4215 update_config_nolock
($vmid, $conf, 1);
4217 if (!$prepare && $snap->{vmstate
}) {
4218 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4219 vm_start
($storecfg, $vmid, $statefile);
4223 lock_config
($vmid, $updatefn);
4225 foreach_drive
($snap, sub {
4226 my ($ds, $drive) = @_;
4228 return if drive_is_cdrom
($drive);
4230 my $volid = $drive->{file
};
4231 my $device = "drive-$ds";
4233 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4237 lock_config
($vmid, $updatefn);
4240 my $savevm_wait = sub {
4244 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4245 if (!$stat->{status
}) {
4246 die "savevm not active\n";
4247 } elsif ($stat->{status
} eq 'active') {
4250 } elsif ($stat->{status
} eq 'completed') {
4253 die "query-savevm returned status '$stat->{status}'\n";
4258 sub snapshot_create
{
4259 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4261 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4263 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4267 my $running = check_running
($vmid);
4270 # create internal snapshots of all drives
4272 my $storecfg = PVE
::Storage
::config
();
4275 if ($snap->{vmstate
}) {
4276 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4277 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4278 &$savevm_wait($vmid);
4280 vm_mon_cmd
($vmid, "savevm-start");
4284 qga_freezefs
($vmid) if $running && $freezefs;
4286 foreach_drive
($snap, sub {
4287 my ($ds, $drive) = @_;
4289 return if drive_is_cdrom
($drive);
4291 my $volid = $drive->{file
};
4292 my $device = "drive-$ds";
4294 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4295 $drivehash->{$ds} = 1;
4300 eval { gqa_unfreezefs
($vmid) if $running && $freezefs; };
4303 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4307 warn "snapshot create failed: starting cleanup\n";
4308 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4313 &$snapshot_commit($vmid, $snapname);
4316 # Note: $drivehash is only set when called from snapshot_create.
4317 sub snapshot_delete
{
4318 my ($vmid, $snapname, $force, $drivehash) = @_;
4325 my $unlink_parent = sub {
4326 my ($confref, $new_parent) = @_;
4328 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4330 $confref->{parent
} = $new_parent;
4332 delete $confref->{parent
};
4337 my $updatefn = sub {
4338 my ($remove_drive) = @_;
4340 my $conf = load_config
($vmid);
4344 die "you can't delete a snapshot if vm is a template\n"
4345 if is_template
($conf);
4348 $snap = $conf->{snapshots
}->{$snapname};
4350 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4352 # remove parent refs
4353 &$unlink_parent($conf, $snap->{parent
});
4354 foreach my $sn (keys %{$conf->{snapshots
}}) {
4355 next if $sn eq $snapname;
4356 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4359 if ($remove_drive) {
4360 if ($remove_drive eq 'vmstate') {
4361 delete $snap->{$remove_drive};
4363 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4364 my $volid = $drive->{file
};
4365 delete $snap->{$remove_drive};
4366 add_unused_volume
($conf, $volid);
4371 $snap->{snapstate
} = 'delete';
4373 delete $conf->{snapshots
}->{$snapname};
4374 delete $conf->{lock} if $drivehash;
4375 foreach my $volid (@$unused) {
4376 add_unused_volume
($conf, $volid);
4380 update_config_nolock
($vmid, $conf, 1);
4383 lock_config
($vmid, $updatefn);
4385 # now remove vmstate file
4387 my $storecfg = PVE
::Storage
::config
();
4389 if ($snap->{vmstate
}) {
4390 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4392 die $err if !$force;
4395 # save changes (remove vmstate from snapshot)
4396 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4399 # now remove all internal snapshots
4400 foreach_drive
($snap, sub {
4401 my ($ds, $drive) = @_;
4403 return if drive_is_cdrom
($drive);
4405 my $volid = $drive->{file
};
4406 my $device = "drive-$ds";
4408 if (!$drivehash || $drivehash->{$ds}) {
4409 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4411 die $err if !$force;
4416 # save changes (remove drive fron snapshot)
4417 lock_config
($vmid, $updatefn, $ds) if !$force;
4418 push @$unused, $volid;
4421 # now cleanup config
4423 lock_config
($vmid, $updatefn);
4427 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4430 foreach_drive
($conf, sub {
4431 my ($ds, $drive) = @_;
4433 return if drive_is_cdrom
($drive);
4434 my $volid = $drive->{file
};
4435 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4441 sub template_create
{
4442 my ($vmid, $conf, $disk) = @_;
4444 my $running = check_running
($vmid);
4445 die "you can't convert a vm to template if vm is running vm\n" if $running;
4447 my $storecfg = PVE
::Storage
::config
();
4450 foreach_drive
($conf, sub {
4451 my ($ds, $drive) = @_;
4453 return if drive_is_cdrom
($drive);
4454 return if $disk && $ds ne $disk;
4456 my $volid = $drive->{file
};
4457 die "volume '$volid' does not support template/clone\n"
4458 if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4461 foreach_drive
($conf, sub {
4462 my ($ds, $drive) = @_;
4464 return if drive_is_cdrom
($drive);
4465 return if $disk && $ds ne $disk;
4467 my $volid = $drive->{file
};
4468 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4469 $drive->{file
} = $voliddst;
4470 $conf->{$ds} = PVE
::QemuServer
::print_drive
($vmid, $drive);
4471 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1);
4474 if($conf->{snapshots
}){
4475 delete $conf->{parent
};
4476 delete $conf->{snapshots
};
4477 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1);
4478 #fixme : do we need to delete disks snapshots ?
4485 return 1 if defined $conf->{template
} && $conf->{template
} == 1;