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 Time
::HiRes
qw(gettimeofday);
32 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
34 # Note about locking: we use flock on the config file protect
35 # against concurent actions.
36 # Aditionaly, we have a 'lock' setting in the config file. This
37 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
38 # allowed when such lock is set. But you can ignore this kind of
39 # lock with the --skiplock flag.
41 cfs_register_file
('/qemu-server/',
45 PVE
::JSONSchema
::register_standard_option
('skiplock', {
46 description
=> "Ignore locks - only root is allowed to use this option.",
51 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
52 description
=> "Some command save/restore state from this location.",
58 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
59 description
=> "The name of the snapshot.",
60 type
=> 'string', format
=> 'pve-configid',
64 #no warnings 'redefine';
66 unless(defined(&_VZSYSCALLS_H_
)) {
67 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
68 require 'sys/syscall.ph';
69 if(defined(&__x86_64__
)) {
70 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
71 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
72 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
73 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
74 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
75 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
76 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
77 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
79 elsif(defined( &__i386__
) ) {
80 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
81 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
82 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
83 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
84 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
85 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
86 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
87 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
89 die("no fairsched syscall for this arch");
91 require 'asm/ioctl.ph';
92 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
96 my ($parent, $weight, $desired) = @_;
98 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
101 sub fairsched_rmnod
{
104 return syscall(&__NR_fairsched_rmnod
, int($id));
108 my ($pid, $newid) = @_;
110 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
113 sub fairsched_vcpus
{
114 my ($id, $vcpus) = @_;
116 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
120 my ($id, $op, $rate) = @_;
122 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
125 use constant FAIRSCHED_SET_RATE
=> 0;
126 use constant FAIRSCHED_DROP_RATE
=> 1;
127 use constant FAIRSCHED_GET_RATE
=> 2;
129 sub fairsched_cpulimit
{
130 my ($id, $limit) = @_;
132 my $cpulim1024 = int($limit * 1024 / 100);
133 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
135 return fairsched_rate
($id, $op, $cpulim1024);
138 my $nodename = PVE
::INotify
::nodename
();
140 mkdir "/etc/pve/nodes/$nodename";
141 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
144 my $var_run_tmpdir = "/var/run/qemu-server";
145 mkdir $var_run_tmpdir;
147 my $lock_dir = "/var/lock/qemu-server";
150 my $pcisysfs = "/sys/bus/pci";
156 description
=> "Specifies whether a VM will be started during system bootup.",
162 description
=> "Automatic restart after crash (currently ignored).",
168 description
=> "Activate hotplug for disk and network device",
174 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
180 description
=> "Lock/unlock the VM.",
181 enum
=> [qw(migrate backup snapshot rollback)],
186 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.",
193 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.",
201 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
208 description
=> "Amount of target RAM for the VM in MB.",
214 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
215 enum
=> PVE
::Tools
::kvmkeymaplist
(),
220 type
=> 'string', format
=> 'dns-name',
221 description
=> "Set a name for the VM. Only used on the configuration web interface.",
226 description
=> "scsi controller model",
227 enum
=> [qw(lsi virtio-scsi-pci megasas)],
233 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
238 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26)],
239 description
=> <<EODESC,
240 Used to enable special optimization/features for specific
243 other => unspecified OS
244 wxp => Microsoft Windows XP
245 w2k => Microsoft Windows 2000
246 w2k3 => Microsoft Windows 2003
247 w2k8 => Microsoft Windows 2008
248 wvista => Microsoft Windows Vista
249 win7 => Microsoft Windows 7
250 l24 => Linux 2.4 Kernel
251 l26 => Linux 2.6/3.X Kernel
253 other|l24|l26 ... no special behaviour
254 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
260 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
261 pattern
=> '[acdn]{1,4}',
266 type
=> 'string', format
=> 'pve-qm-bootdisk',
267 description
=> "Enable booting from specified disk.",
268 pattern
=> '(ide|sata|scsi|virtio)\d+',
273 description
=> "The number of CPUs. Please use option -sockets instead.",
280 description
=> "The number of CPU sockets.",
287 description
=> "The number of cores per socket.",
294 description
=> "Enable/disable ACPI.",
300 description
=> "Enable/disable Qemu GuestAgent.",
306 description
=> "Enable/disable KVM hardware virtualization.",
312 description
=> "Enable/disable time drift fix. This is ignored for kvm versions newer that 1.0 (not needed anymore).",
318 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
323 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
328 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 win7/w2k8, and 'cirrur' for other OS types",
329 enum
=> [qw(std cirrus vmware)],
333 type
=> 'string', format
=> 'pve-qm-watchdog',
334 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
335 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)",
340 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
341 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'.",
342 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
347 type
=> 'string', format
=> 'pve-qm-startup',
348 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
349 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.",
354 description
=> <<EODESCR,
355 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
357 args: -no-reboot -no-hpet
364 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.",
369 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
373 migrate_downtime
=> {
376 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
382 type
=> 'string', format
=> 'pve-qm-drive',
383 typetext
=> 'volume',
384 description
=> "This is an alias for option -ide2",
388 description
=> "Emulated CPU type.",
390 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom cpu64-rhel6 cpu64-rhel5 Conroe Penryn Nehalem Westmere Opteron_G1 Opteron_G2 Opteron_G3 host) ],
393 parent
=> get_standard_option
('pve-snapshot-name', {
395 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
399 # what about other qemu settings ?
401 #machine => 'string',
414 ##soundhw => 'string',
416 while (my ($k, $v) = each %$confdesc) {
417 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
420 my $MAX_IDE_DISKS = 4;
421 my $MAX_SCSI_DISKS = 14;
422 my $MAX_VIRTIO_DISKS = 16;
423 my $MAX_SATA_DISKS = 6;
424 my $MAX_USB_DEVICES = 5;
426 my $MAX_UNUSED_DISKS = 8;
427 my $MAX_HOSTPCI_DEVICES = 2;
428 my $MAX_SERIAL_PORTS = 4;
429 my $MAX_PARALLEL_PORTS = 3;
431 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
432 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
433 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
438 type
=> 'string', format
=> 'pve-qm-net',
439 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
440 description
=> <<EODESCR,
441 Specify network devices.
443 MODEL is one of: $nic_model_list_txt
445 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
446 automatically generated if not specified.
448 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
450 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'.
452 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
458 The DHCP server assign addresses to the guest starting from 10.0.2.15.
462 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
464 for (my $i = 0; $i < $MAX_NETS; $i++) {
465 $confdesc->{"net$i"} = $netdesc;
472 type
=> 'string', format
=> 'pve-qm-drive',
473 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]',
474 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
476 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
480 type
=> 'string', format
=> 'pve-qm-drive',
481 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]',
482 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
484 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
488 type
=> 'string', format
=> 'pve-qm-drive',
489 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]',
490 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
492 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
496 type
=> 'string', format
=> 'pve-qm-drive',
497 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]',
498 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
500 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
504 type
=> 'string', format
=> 'pve-qm-usb-device',
505 typetext
=> 'host=HOSTUSBDEVICE',
506 description
=> <<EODESCR,
507 Configure an USB device (n is 0 to 4). This can be used to
508 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
510 'bus-port(.port)*' (decimal numbers) or
511 'vendor_id:product_id' (hexadeciaml numbers)
513 You can use the 'lsusb -t' command to list existing usb devices.
515 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
519 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
523 type
=> 'string', format
=> 'pve-qm-hostpci',
524 typetext
=> "HOSTPCIDEVICE",
525 description
=> <<EODESCR,
526 Map host pci devices. HOSTPCIDEVICE syntax is:
528 'bus:dev.func' (hexadecimal numbers)
530 You can us the 'lspci' command to list existing pci devices.
532 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
534 Experimental: user reported problems with this option.
537 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
542 pattern
=> '/dev/ttyS\d+',
543 description
=> <<EODESCR,
544 Map host serial devices (n is 0 to 3).
546 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
548 Experimental: user reported problems with this option.
555 pattern
=> '/dev/parport\d+',
556 description
=> <<EODESCR,
557 Map host parallel devices (n is 0 to 2).
559 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
561 Experimental: user reported problems with this option.
565 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
566 $confdesc->{"parallel$i"} = $paralleldesc;
569 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
570 $confdesc->{"serial$i"} = $serialdesc;
573 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
574 $confdesc->{"hostpci$i"} = $hostpcidesc;
577 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
578 $drivename_hash->{"ide$i"} = 1;
579 $confdesc->{"ide$i"} = $idedesc;
582 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
583 $drivename_hash->{"sata$i"} = 1;
584 $confdesc->{"sata$i"} = $satadesc;
587 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
588 $drivename_hash->{"scsi$i"} = 1;
589 $confdesc->{"scsi$i"} = $scsidesc ;
592 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
593 $drivename_hash->{"virtio$i"} = 1;
594 $confdesc->{"virtio$i"} = $virtiodesc;
597 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
598 $confdesc->{"usb$i"} = $usbdesc;
603 type
=> 'string', format
=> 'pve-volume-id',
604 description
=> "Reference to unused volumes.",
607 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
608 $confdesc->{"unused$i"} = $unuseddesc;
611 my $kvm_api_version = 0;
615 return $kvm_api_version if $kvm_api_version;
617 my $fh = IO
::File-
>new("</dev/kvm") ||
620 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
621 $kvm_api_version = $v;
626 return $kvm_api_version;
629 my $kvm_user_version;
631 sub kvm_user_version
{
633 return $kvm_user_version if $kvm_user_version;
635 $kvm_user_version = 'unknown';
637 my $tmp = `kvm -help 2>/dev/null`;
639 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) /) {
640 $kvm_user_version = $2;
643 return $kvm_user_version;
647 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
650 # order is important - used to autoselect boot disk
651 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
652 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
653 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
654 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
657 sub valid_drivename
{
660 return defined($drivename_hash->{$dev});
665 return defined($confdesc->{$key});
669 return $nic_model_list;
672 sub os_list_description
{
677 w2k
=> 'Windows 2000',
678 w2k3
=>, 'Windows 2003',
679 w2k8
=> 'Windows 2008',
680 wvista
=> 'Windows Vista',
691 return $cdrom_path if $cdrom_path;
693 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
694 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
695 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
699 my ($storecfg, $vmid, $cdrom) = @_;
701 if ($cdrom eq 'cdrom') {
702 return get_cdrom_path
();
703 } elsif ($cdrom eq 'none') {
705 } elsif ($cdrom =~ m
|^/|) {
708 return PVE
::Storage
::path
($storecfg, $cdrom);
712 # try to convert old style file names to volume IDs
713 sub filename_to_volume_id
{
714 my ($vmid, $file, $media) = @_;
716 if (!($file eq 'none' || $file eq 'cdrom' ||
717 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
719 return undef if $file =~ m
|/|;
721 if ($media && $media eq 'cdrom') {
722 $file = "local:iso/$file";
724 $file = "local:$vmid/$file";
731 sub verify_media_type
{
732 my ($opt, $vtype, $media) = @_;
737 if ($media eq 'disk') {
739 } elsif ($media eq 'cdrom') {
742 die "internal error";
745 return if ($vtype eq $etype);
747 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
750 sub cleanup_drive_path
{
751 my ($opt, $storecfg, $drive) = @_;
753 # try to convert filesystem paths to volume IDs
755 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
756 ($drive->{file
} !~ m
|^/dev/.+|) &&
757 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
758 ($drive->{file
} !~ m/^\d+$/)) {
759 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
760 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
761 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
762 verify_media_type
($opt, $vtype, $drive->{media
});
763 $drive->{file
} = $volid;
766 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
769 sub create_conf_nolock
{
770 my ($vmid, $settings) = @_;
772 my $filename = config_file
($vmid);
774 die "configuration file '$filename' already exists\n" if -f
$filename;
776 my $defaults = load_defaults
();
778 $settings->{name
} = "vm$vmid" if !$settings->{name
};
779 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
782 foreach my $opt (keys %$settings) {
783 next if !$confdesc->{$opt};
785 my $value = $settings->{$opt};
788 $data .= "$opt: $value\n";
791 PVE
::Tools
::file_set_contents
($filename, $data);
794 my $parse_size = sub {
797 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
798 my ($size, $unit) = ($1, $3);
801 $size = $size * 1024;
802 } elsif ($unit eq 'M') {
803 $size = $size * 1024 * 1024;
804 } elsif ($unit eq 'G') {
805 $size = $size * 1024 * 1024 * 1024;
811 my $format_size = sub {
816 my $kb = int($size/1024);
817 return $size if $kb*1024 != $size;
819 my $mb = int($kb/1024);
820 return "${kb}K" if $mb*1024 != $kb;
822 my $gb = int($mb/1024);
823 return "${mb}M" if $gb*1024 != $mb;
828 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
829 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
830 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
831 # [,aio=native|threads]
834 my ($key, $data) = @_;
838 # $key may be undefined - used to verify JSON parameters
839 if (!defined($key)) {
840 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
842 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
843 $res->{interface
} = $1;
849 foreach my $p (split (/,/, $data)) {
850 next if $p =~ m/^\s*$/;
852 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)=(.+)$/) {
853 my ($k, $v) = ($1, $2);
855 $k = 'file' if $k eq 'volume';
857 return undef if defined $res->{$k};
859 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
860 return undef if !$v || $v !~ m/^\d+/;
862 $v = sprintf("%.3f", $v / (1024*1024));
866 if (!$res->{file
} && $p !~ m/=/) {
874 return undef if !$res->{file
};
876 return undef if $res->{cache
} &&
877 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
878 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
879 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
880 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
881 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
882 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
883 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
884 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
885 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
886 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
887 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
888 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
891 return undef if $res->{mbps_rd
} && $res->{mbps
};
892 return undef if $res->{mbps_wr
} && $res->{mbps
};
894 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
895 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
896 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
898 return undef if $res->{iops_rd
} && $res->{iops
};
899 return undef if $res->{iops_wr
} && $res->{iops
};
900 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
901 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
902 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
906 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
909 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
910 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
911 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
912 return undef if $res->{interface
} eq 'virtio';
915 # rerror does not work with scsi drives
916 if ($res->{rerror
}) {
917 return undef if $res->{interface
} eq 'scsi';
923 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
926 my ($vmid, $drive) = @_;
929 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
930 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
933 if ($drive->{size
}) {
934 $opts .= ",size=" . &$format_size($drive->{size
});
937 return "$drive->{file}$opts";
941 my($fh, $noerr) = @_;
944 my $SG_GET_VERSION_NUM = 0x2282;
946 my $versionbuf = "\x00" x
8;
947 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
949 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
952 my $version = unpack("I", $versionbuf);
953 if ($version < 30000) {
954 die "scsi generic interface too old\n" if !$noerr;
958 my $buf = "\x00" x
36;
959 my $sensebuf = "\x00" x
8;
960 my $cmd = pack("C x3 C x11", 0x12, 36);
962 # see /usr/include/scsi/sg.h
963 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";
965 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
966 length($sensebuf), 0, length($buf), $buf,
967 $cmd, $sensebuf, 6000);
969 $ret = ioctl($fh, $SG_IO, $packet);
971 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
975 my @res = unpack($sg_io_hdr_t, $packet);
976 if ($res[17] || $res[18]) {
977 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
982 ($res->{device
}, $res->{removable
}, $res->{venodor
},
983 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
991 my $fh = IO
::File-
>new("+<$path") || return undef;
992 my $res = scsi_inquiry
($fh, 1);
998 sub print_drivedevice_full
{
999 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1004 if ($drive->{interface
} eq 'virtio') {
1005 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1006 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1007 } elsif ($drive->{interface
} eq 'scsi') {
1008 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1009 my $controller = int($drive->{index} / $maxdev);
1010 my $unit = $drive->{index} % $maxdev;
1011 my $devicetype = 'hd';
1013 if (drive_is_cdrom
($drive)) {
1016 if ($drive->{file
} =~ m
|^/|) {
1017 $path = $drive->{file
};
1019 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1022 if($path =~ m/^iscsi\:\/\
//){
1023 $devicetype = 'generic';
1026 $devicetype = 'block' if path_is_scsi
($path);
1030 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1031 $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';
1033 $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}";
1036 } elsif ($drive->{interface
} eq 'ide'){
1038 my $controller = int($drive->{index} / $maxdev);
1039 my $unit = $drive->{index} % $maxdev;
1040 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1042 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1043 } elsif ($drive->{interface
} eq 'sata'){
1044 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1045 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1046 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1047 } elsif ($drive->{interface
} eq 'usb') {
1049 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1051 die "unsupported interface type";
1054 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1059 sub print_drive_full
{
1060 my ($storecfg, $vmid, $drive) = @_;
1063 foreach my $o (@qemu_drive_options) {
1064 next if $o eq 'bootindex';
1065 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1068 foreach my $o (qw(bps bps_rd bps_wr)) {
1069 my $v = $drive->{"m$o"};
1070 $opts .= ",$o=" . int($v*1024*1024) if $v;
1073 # use linux-aio by default (qemu default is threads)
1074 $opts .= ",aio=native" if !$drive->{aio
};
1077 my $volid = $drive->{file
};
1078 if (drive_is_cdrom
($drive)) {
1079 $path = get_iso_path
($storecfg, $vmid, $volid);
1081 if ($volid =~ m
|^/|) {
1084 $path = PVE
::Storage
::path
($storecfg, $volid);
1086 if (!$drive->{cache
} && ($path =~ m
|^/dev/| || $path =~ m
|\
.raw
$|)) {
1087 $opts .= ",cache=none";
1091 my $pathinfo = $path ?
"file=$path," : '';
1093 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1096 sub print_netdevice_full
{
1097 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1099 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1101 my $device = $net->{model
};
1102 if ($net->{model
} eq 'virtio') {
1103 $device = 'virtio-net-pci';
1106 # qemu > 0.15 always try to boot from network - we disable that by
1107 # not loading the pxe rom file
1108 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1109 my $pciaddr = print_pci_addr
("$netid", $bridges);
1110 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1111 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1115 sub print_netdev_full
{
1116 my ($vmid, $conf, $net, $netid) = @_;
1119 if ($netid =~ m/^net(\d+)$/) {
1123 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1125 my $ifname = "tap${vmid}i$i";
1127 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1128 die "interface name '$ifname' is too long (max 15 character)\n"
1129 if length($ifname) >= 16;
1131 my $vhostparam = '';
1132 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1134 my $vmname = $conf->{name
} || "vm$vmid";
1136 if ($net->{bridge
}) {
1137 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1139 return "type=user,id=$netid,hostname=$vmname";
1143 sub drive_is_cdrom
{
1146 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1153 return undef if !$value;
1157 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1158 $res->{pciid
} = $value;
1166 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1172 foreach my $kvp (split(/,/, $data)) {
1174 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1176 my $mac = uc($3) || PVE
::Tools
::random_ether_addr
();
1177 $res->{model
} = $model;
1178 $res->{macaddr
} = $mac;
1179 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1180 $res->{bridge
} = $1;
1181 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1183 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1191 return undef if !$res->{model
};
1199 my $res = "$net->{model}";
1200 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1201 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1202 $res .= ",rate=$net->{rate}" if $net->{rate
};
1203 $res .= ",tag=$net->{tag}" if $net->{tag
};
1208 sub add_random_macs
{
1209 my ($settings) = @_;
1211 foreach my $opt (keys %$settings) {
1212 next if $opt !~ m/^net(\d+)$/;
1213 my $net = parse_net
($settings->{$opt});
1215 $settings->{$opt} = print_net
($net);
1219 sub add_unused_volume
{
1220 my ($config, $volid) = @_;
1223 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1224 my $test = "unused$ind";
1225 if (my $vid = $config->{$test}) {
1226 return if $vid eq $volid; # do not add duplicates
1232 die "To many unused volume - please delete them first.\n" if !$key;
1234 $config->{$key} = $volid;
1239 # fixme: remove all thos $noerr parameters?
1241 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1242 sub verify_bootdisk
{
1243 my ($value, $noerr) = @_;
1245 return $value if valid_drivename
($value);
1247 return undef if $noerr;
1249 die "invalid boot disk '$value'\n";
1252 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1254 my ($value, $noerr) = @_;
1256 return $value if parse_net
($value);
1258 return undef if $noerr;
1260 die "unable to parse network options\n";
1263 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1265 my ($value, $noerr) = @_;
1267 return $value if parse_drive
(undef, $value);
1269 return undef if $noerr;
1271 die "unable to parse drive options\n";
1274 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1275 sub verify_hostpci
{
1276 my ($value, $noerr) = @_;
1278 return $value if parse_hostpci
($value);
1280 return undef if $noerr;
1282 die "unable to parse pci id\n";
1285 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1286 sub verify_watchdog
{
1287 my ($value, $noerr) = @_;
1289 return $value if parse_watchdog
($value);
1291 return undef if $noerr;
1293 die "unable to parse watchdog options\n";
1296 sub parse_watchdog
{
1299 return undef if !$value;
1303 foreach my $p (split(/,/, $value)) {
1304 next if $p =~ m/^\s*$/;
1306 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1308 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1309 $res->{action
} = $2;
1318 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1319 sub verify_startup
{
1320 my ($value, $noerr) = @_;
1322 return $value if parse_startup
($value);
1324 return undef if $noerr;
1326 die "unable to parse startup options\n";
1332 return undef if !$value;
1336 foreach my $p (split(/,/, $value)) {
1337 next if $p =~ m/^\s*$/;
1339 if ($p =~ m/^(order=)?(\d+)$/) {
1341 } elsif ($p =~ m/^up=(\d+)$/) {
1343 } elsif ($p =~ m/^down=(\d+)$/) {
1353 sub parse_usb_device
{
1356 return undef if !$value;
1358 my @dl = split(/,/, $value);
1362 foreach my $v (@dl) {
1363 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1365 $res->{vendorid
} = $2;
1366 $res->{productid
} = $4;
1367 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1369 $res->{hostbus
} = $1;
1370 $res->{hostport
} = $2;
1375 return undef if !$found;
1380 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1381 sub verify_usb_device
{
1382 my ($value, $noerr) = @_;
1384 return $value if parse_usb_device
($value);
1386 return undef if $noerr;
1388 die "unable to parse usb device\n";
1391 # add JSON properties for create and set function
1392 sub json_config_properties
{
1395 foreach my $opt (keys %$confdesc) {
1396 $prop->{$opt} = $confdesc->{$opt};
1403 my ($key, $value) = @_;
1405 die "unknown setting '$key'\n" if !$confdesc->{$key};
1407 my $type = $confdesc->{$key}->{type
};
1409 if (!defined($value)) {
1410 die "got undefined value\n";
1413 if ($value =~ m/[\n\r]/) {
1414 die "property contains a line feed\n";
1417 if ($type eq 'boolean') {
1418 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1419 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1420 die "type check ('boolean') failed - got '$value'\n";
1421 } elsif ($type eq 'integer') {
1422 return int($1) if $value =~ m/^(\d+)$/;
1423 die "type check ('integer') failed - got '$value'\n";
1424 } elsif ($type eq 'string') {
1425 if (my $fmt = $confdesc->{$key}->{format
}) {
1426 if ($fmt eq 'pve-qm-drive') {
1427 # special case - we need to pass $key to parse_drive()
1428 my $drive = parse_drive
($key, $value);
1429 return $value if $drive;
1430 die "unable to parse drive options\n";
1432 PVE
::JSONSchema
::check_format
($fmt, $value);
1435 $value =~ s/^\"(.*)\"$/$1/;
1438 die "internal error"
1442 sub lock_config_full
{
1443 my ($vmid, $timeout, $code, @param) = @_;
1445 my $filename = config_file_lock
($vmid);
1447 my $res = lock_file
($filename, $timeout, $code, @param);
1455 my ($vmid, $code, @param) = @_;
1457 return lock_config_full
($vmid, 10, $code, @param);
1460 sub cfs_config_path
{
1461 my ($vmid, $node) = @_;
1463 $node = $nodename if !$node;
1464 return "nodes/$node/qemu-server/$vmid.conf";
1467 sub check_iommu_support
{
1468 #fixme : need to check IOMMU support
1469 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1477 my ($vmid, $node) = @_;
1479 my $cfspath = cfs_config_path
($vmid, $node);
1480 return "/etc/pve/$cfspath";
1483 sub config_file_lock
{
1486 return "$lock_dir/lock-$vmid.conf";
1492 my $conf = config_file
($vmid);
1493 utime undef, undef, $conf;
1497 my ($storecfg, $vmid, $keep_empty_config) = @_;
1499 my $conffile = config_file
($vmid);
1501 my $conf = load_config
($vmid);
1505 # only remove disks owned by this VM
1506 foreach_drive
($conf, sub {
1507 my ($ds, $drive) = @_;
1509 return if drive_is_cdrom
($drive);
1511 my $volid = $drive->{file
};
1512 return if !$volid || $volid =~ m
|^/|;
1514 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1515 return if !$path || !$owner || ($owner != $vmid);
1517 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1520 if ($keep_empty_config) {
1521 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1526 # also remove unused disk
1528 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1531 PVE
::Storage
::foreach_volid
($dl, sub {
1532 my ($volid, $sid, $volname, $d) = @_;
1533 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1543 my ($vmid, $node) = @_;
1545 my $cfspath = cfs_config_path
($vmid, $node);
1547 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1549 die "no such VM ('$vmid')\n" if !defined($conf);
1554 sub parse_vm_config
{
1555 my ($filename, $raw) = @_;
1557 return undef if !defined($raw);
1560 digest
=> Digest
::SHA
::sha1_hex
($raw),
1564 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1565 || die "got strange filename '$filename'";
1572 my @lines = split(/\n/, $raw);
1573 foreach my $line (@lines) {
1574 next if $line =~ m/^\s*$/;
1576 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1578 $conf->{description
} = $descr if $descr;
1580 $conf = $res->{snapshots
}->{$snapname} = {};
1584 if ($line =~ m/^\#(.*)\s*$/) {
1585 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1589 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1590 $descr .= PVE
::Tools
::decode_text
($2);
1591 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1592 $conf->{snapstate
} = $1;
1593 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1596 $conf->{$key} = $value;
1597 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1600 eval { $value = check_type
($key, $value); };
1602 warn "vm $vmid - unable to parse value of '$key' - $@";
1604 my $fmt = $confdesc->{$key}->{format
};
1605 if ($fmt && $fmt eq 'pve-qm-drive') {
1606 my $v = parse_drive
($key, $value);
1607 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1608 $v->{file
} = $volid;
1609 $value = print_drive
($vmid, $v);
1611 warn "vm $vmid - unable to parse value of '$key'\n";
1616 if ($key eq 'cdrom') {
1617 $conf->{ide2
} = $value;
1619 $conf->{$key} = $value;
1625 $conf->{description
} = $descr if $descr;
1627 delete $res->{snapstate
}; # just to be sure
1632 sub write_vm_config
{
1633 my ($filename, $conf) = @_;
1635 delete $conf->{snapstate
}; # just to be sure
1637 if ($conf->{cdrom
}) {
1638 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1639 $conf->{ide2
} = $conf->{cdrom
};
1640 delete $conf->{cdrom
};
1643 # we do not use 'smp' any longer
1644 if ($conf->{sockets
}) {
1645 delete $conf->{smp
};
1646 } elsif ($conf->{smp
}) {
1647 $conf->{sockets
} = $conf->{smp
};
1648 delete $conf->{cores
};
1649 delete $conf->{smp
};
1652 my $used_volids = {};
1654 my $cleanup_config = sub {
1657 foreach my $key (keys %$cref) {
1658 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1659 $key eq 'snapstate';
1660 my $value = $cref->{$key};
1661 eval { $value = check_type
($key, $value); };
1662 die "unable to parse value of '$key' - $@" if $@;
1664 $cref->{$key} = $value;
1666 if (valid_drivename
($key)) {
1667 my $drive = PVE
::QemuServer
::parse_drive
($key, $value);
1668 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1673 &$cleanup_config($conf);
1674 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1675 &$cleanup_config($conf->{snapshots
}->{$snapname});
1678 # remove 'unusedX' settings if we re-add a volume
1679 foreach my $key (keys %$conf) {
1680 my $value = $conf->{$key};
1681 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1682 delete $conf->{$key};
1686 my $generate_raw_config = sub {
1691 # add description as comment to top of file
1692 my $descr = $conf->{description
} || '';
1693 foreach my $cl (split(/\n/, $descr)) {
1694 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1697 foreach my $key (sort keys %$conf) {
1698 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1699 $raw .= "$key: $conf->{$key}\n";
1704 my $raw = &$generate_raw_config($conf);
1705 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1706 $raw .= "\n[$snapname]\n";
1707 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1713 sub update_config_nolock
{
1714 my ($vmid, $conf, $skiplock) = @_;
1716 check_lock
($conf) if !$skiplock;
1718 my $cfspath = cfs_config_path
($vmid);
1720 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1724 my ($vmid, $conf, $skiplock) = @_;
1726 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1733 # we use static defaults from our JSON schema configuration
1734 foreach my $key (keys %$confdesc) {
1735 if (defined(my $default = $confdesc->{$key}->{default})) {
1736 $res->{$key} = $default;
1740 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1741 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1747 my $vmlist = PVE
::Cluster
::get_vmlist
();
1749 return $res if !$vmlist || !$vmlist->{ids
};
1750 my $ids = $vmlist->{ids
};
1752 foreach my $vmid (keys %$ids) {
1753 my $d = $ids->{$vmid};
1754 next if !$d->{node
} || $d->{node
} ne $nodename;
1755 next if !$d->{type
} || $d->{type
} ne 'qemu';
1756 $res->{$vmid}->{exists} = 1;
1761 # test if VM uses local resources (to prevent migration)
1762 sub check_local_resources
{
1763 my ($conf, $noerr) = @_;
1767 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1768 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1770 foreach my $k (keys %$conf) {
1771 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1774 die "VM uses local resources\n" if $loc_res && !$noerr;
1779 # check is used storages are available on all nodes (use by migrate)
1780 sub check_storage_availability
{
1781 my ($storecfg, $conf, $node) = @_;
1783 foreach_drive
($conf, sub {
1784 my ($ds, $drive) = @_;
1786 my $volid = $drive->{file
};
1789 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1792 # check if storage is available on both nodes
1793 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1794 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1801 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1805 my ($pidfile, $pid) = @_;
1807 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1811 return undef if !$line;
1812 my @param = split(/\0/, $line);
1814 my $cmd = $param[0];
1815 return if !$cmd || ($cmd !~ m
|kvm
$|);
1817 for (my $i = 0; $i < scalar (@param); $i++) {
1820 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1821 my $p = $param[$i+1];
1822 return 1 if $p && ($p eq $pidfile);
1831 my ($vmid, $nocheck, $node) = @_;
1833 my $filename = config_file
($vmid, $node);
1835 die "unable to find configuration file for VM $vmid - no such machine\n"
1836 if !$nocheck && ! -f
$filename;
1838 my $pidfile = pidfile_name
($vmid);
1840 if (my $fd = IO
::File-
>new("<$pidfile")) {
1845 my $mtime = $st->mtime;
1846 if ($mtime > time()) {
1847 warn "file '$filename' modified in future\n";
1850 if ($line =~ m/^(\d+)$/) {
1852 if (check_cmdline
($pidfile, $pid)) {
1853 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1865 my $vzlist = config_list
();
1867 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1869 while (defined(my $de = $fd->read)) {
1870 next if $de !~ m/^(\d+)\.pid$/;
1872 next if !defined($vzlist->{$vmid});
1873 if (my $pid = check_running
($vmid)) {
1874 $vzlist->{$vmid}->{pid
} = $pid;
1882 my ($storecfg, $conf) = @_;
1884 my $bootdisk = $conf->{bootdisk
};
1885 return undef if !$bootdisk;
1886 return undef if !valid_drivename
($bootdisk);
1888 return undef if !$conf->{$bootdisk};
1890 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1891 return undef if !defined($drive);
1893 return undef if drive_is_cdrom
($drive);
1895 my $volid = $drive->{file
};
1896 return undef if !$volid;
1898 return $drive->{size
};
1901 my $last_proc_pid_stat;
1903 # get VM status information
1904 # This must be fast and should not block ($full == false)
1905 # We only query KVM using QMP if $full == true (this can be slow)
1907 my ($opt_vmid, $full) = @_;
1911 my $storecfg = PVE
::Storage
::config
();
1913 my $list = vzlist
();
1914 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
1916 my $cpucount = $cpuinfo->{cpus
} || 1;
1918 foreach my $vmid (keys %$list) {
1919 next if $opt_vmid && ($vmid ne $opt_vmid);
1921 my $cfspath = cfs_config_path
($vmid);
1922 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
1925 $d->{pid
} = $list->{$vmid}->{pid
};
1927 # fixme: better status?
1928 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
1930 my $size = disksize
($storecfg, $conf);
1931 if (defined($size)) {
1932 $d->{disk
} = 0; # no info available
1933 $d->{maxdisk
} = $size;
1939 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
1940 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
1942 $d->{name
} = $conf->{name
} || "VM $vmid";
1943 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
1953 $d->{diskwrite
} = 0;
1958 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
1959 foreach my $dev (keys %$netdev) {
1960 next if $dev !~ m/^tap([1-9]\d*)i/;
1962 my $d = $res->{$vmid};
1965 $d->{netout
} += $netdev->{$dev}->{receive
};
1966 $d->{netin
} += $netdev->{$dev}->{transmit
};
1969 my $ctime = gettimeofday
;
1971 foreach my $vmid (keys %$list) {
1973 my $d = $res->{$vmid};
1974 my $pid = $d->{pid
};
1977 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
1978 next if !$pstat; # not running
1980 my $used = $pstat->{utime} + $pstat->{stime
};
1982 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
1984 if ($pstat->{vsize
}) {
1985 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
1988 my $old = $last_proc_pid_stat->{$pid};
1990 $last_proc_pid_stat->{$pid} = {
1998 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2000 if ($dtime > 1000) {
2001 my $dutime = $used - $old->{used
};
2003 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2004 $last_proc_pid_stat->{$pid} = {
2010 $d->{cpu
} = $old->{cpu
};
2014 return $res if !$full;
2016 my $qmpclient = PVE
::QMPClient-
>new();
2018 my $blockstatscb = sub {
2019 my ($vmid, $resp) = @_;
2020 my $data = $resp->{'return'} || [];
2021 my $totalrdbytes = 0;
2022 my $totalwrbytes = 0;
2023 for my $blockstat (@$data) {
2024 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2025 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2027 $res->{$vmid}->{diskread
} = $totalrdbytes;
2028 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2031 my $statuscb = sub {
2032 my ($vmid, $resp) = @_;
2033 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2035 my $status = 'unknown';
2036 if (!defined($status = $resp->{'return'}->{status
})) {
2037 warn "unable to get VM status\n";
2041 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2044 foreach my $vmid (keys %$list) {
2045 next if $opt_vmid && ($vmid ne $opt_vmid);
2046 next if !$res->{$vmid}->{pid
}; # not running
2047 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2050 $qmpclient->queue_execute();
2052 foreach my $vmid (keys %$list) {
2053 next if $opt_vmid && ($vmid ne $opt_vmid);
2054 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2061 my ($conf, $func) = @_;
2063 foreach my $ds (keys %$conf) {
2064 next if !valid_drivename
($ds);
2066 my $drive = parse_drive
($ds, $conf->{$ds});
2069 &$func($ds, $drive);
2073 sub config_to_command
{
2074 my ($storecfg, $vmid, $conf, $defaults, $migrate_uri) = @_;
2080 my $kvmver = kvm_user_version
();
2081 my $vernum = 0; # unknown
2082 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2083 $vernum = $1*1000000+$2*1000;
2084 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2085 $vernum = $1*1000000+$2*1000+$3;
2088 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2090 my $have_ovz = -f
'/proc/vz/vestat';
2092 push @$cmd, '/usr/bin/kvm';
2094 push @$cmd, '-id', $vmid;
2098 my $qmpsocket = qmp_socket
($vmid);
2099 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2100 push @$cmd, '-mon', "chardev=qmp,mode=control";
2102 my $socket = vnc_socket
($vmid);
2103 push @$cmd, '-vnc', "unix:$socket,x509,password";
2105 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2107 push @$cmd, '-daemonize';
2109 push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
2111 push @$cmd, '-S' if $migrate_uri;
2114 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2115 next if !$conf->{"usb$i"};
2118 # include usb device config
2119 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2121 # enable absolute mouse coordinates (needed by vnc)
2122 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2125 push @$devices, '-device', 'usb-tablet,bus=ehci.0,port=6';
2127 push @$devices, '-usbdevice', 'tablet';
2132 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2133 my $d = parse_hostpci
($conf->{"hostpci$i"});
2135 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2136 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2140 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2141 my $d = parse_usb_device
($conf->{"usb$i"});
2143 if ($d->{vendorid
} && $d->{productid
}) {
2144 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2145 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2146 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2151 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2152 if (my $path = $conf->{"serial$i"}) {
2153 die "no such serial device\n" if ! -c
$path;
2154 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2155 push @$devices, '-device', "isa-serial,chardev=serial$i";
2160 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2161 if (my $path = $conf->{"parallel$i"}) {
2162 die "no such parallel device\n" if ! -c
$path;
2163 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2164 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2168 my $vmname = $conf->{name
} || "vm$vmid";
2170 push @$cmd, '-name', $vmname;
2173 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2174 $sockets = $conf->{sockets
} if $conf->{sockets
};
2176 my $cores = $conf->{cores
} || 1;
2178 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2180 push @$cmd, '-cpu', $conf->{cpu
} if $conf->{cpu
};
2182 push @$cmd, '-nodefaults';
2184 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2186 my $bootindex_hash = {};
2188 foreach my $o (split(//, $bootorder)) {
2189 $bootindex_hash->{$o} = $i*100;
2193 push @$cmd, '-boot', "menu=on";
2195 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2197 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2199 my $vga = $conf->{vga
};
2201 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2208 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2211 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2212 # ignore - no longer supported by newer kvm
2213 # push @$cmd, '-tdf' if $tdf;
2215 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2217 if (my $ost = $conf->{ostype
}) {
2218 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2220 if ($ost =~ m/^w/) { # windows
2221 push @$cmd, '-localtime' if !defined($conf->{localtime});
2223 # use rtc-td-hack when acpi is enabled
2224 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2225 push @$cmd, '-rtc-td-hack';
2229 if ($ost eq 'win7' || $ost eq 'w2k8' || $ost eq 'wvista') {
2230 push @$cmd, '-no-kvm-pit-reinjection';
2231 push @$cmd, '-no-hpet';
2241 push @$cmd, '-no-kvm';
2243 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2246 push @$cmd, '-localtime' if $conf->{localtime};
2248 push @$cmd, '-startdate', $conf->{startdate
} if $conf->{startdate
};
2250 push @$cmd, '-S' if $conf->{freeze
};
2252 # set keyboard layout
2253 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2254 push @$cmd, '-k', $kb if $kb;
2257 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2258 #push @$cmd, '-soundhw', 'es1370';
2259 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2261 if($conf->{agent
}) {
2262 my $qgasocket = qga_socket
($vmid);
2263 my $pciaddr = print_pci_addr
("qga0", $bridges);
2264 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2265 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2266 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2269 $pciaddr = print_pci_addr
("balloon0", $bridges);
2270 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon
};
2272 if ($conf->{watchdog
}) {
2273 my $wdopts = parse_watchdog
($conf->{watchdog
});
2274 $pciaddr = print_pci_addr
("watchdog", $bridges);
2275 my $watchdog = $wdopts->{model
} || 'i6300esb';
2276 push @$devices, '-device', "$watchdog$pciaddr";
2277 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2281 my $scsicontroller = {};
2282 my $ahcicontroller = {};
2283 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2285 foreach_drive
($conf, sub {
2286 my ($ds, $drive) = @_;
2288 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2289 push @$vollist, $drive->{file
};
2292 $use_virtio = 1 if $ds =~ m/^virtio/;
2294 if (drive_is_cdrom
($drive)) {
2295 if ($bootindex_hash->{d
}) {
2296 $drive->{bootindex
} = $bootindex_hash->{d
};
2297 $bootindex_hash->{d
} += 1;
2300 if ($bootindex_hash->{c
}) {
2301 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2302 $bootindex_hash->{c
} += 1;
2306 if ($drive->{interface
} eq 'scsi') {
2308 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2309 my $controller = int($drive->{index} / $maxdev);
2310 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2311 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2312 $scsicontroller->{$controller}=1;
2315 if ($drive->{interface
} eq 'sata') {
2316 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2317 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2318 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2319 $ahcicontroller->{$controller}=1;
2322 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2323 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2326 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2328 for (my $i = 0; $i < $MAX_NETS; $i++) {
2329 next if !$conf->{"net$i"};
2330 my $d = parse_net
($conf->{"net$i"});
2333 $use_virtio = 1 if $d->{model
} eq 'virtio';
2335 if ($bootindex_hash->{n
}) {
2336 $d->{bootindex
} = $bootindex_hash->{n
};
2337 $bootindex_hash->{n
} += 1;
2340 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2341 push @$devices, '-netdev', $netdevfull;
2343 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2344 push @$devices, '-device', $netdevicefull;
2348 while (my ($k, $v) = each %$bridges) {
2349 $pciaddr = print_pci_addr
("pci.$k");
2350 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2354 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2355 # when the VM uses virtio devices.
2356 if (!$use_virtio && $have_ovz) {
2358 my $cpuunits = defined($conf->{cpuunits
}) ?
2359 $conf->{cpuunits
} : $defaults->{cpuunits
};
2361 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2363 # fixme: cpulimit is currently ignored
2364 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2368 if ($conf->{args
}) {
2369 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2373 push @$cmd, @$devices;
2374 return wantarray ?
($cmd, $vollist) : $cmd;
2379 return "${var_run_tmpdir}/$vmid.vnc";
2384 return "${var_run_tmpdir}/$vmid.qmp";
2389 return "${var_run_tmpdir}/$vmid.qga";
2394 return "${var_run_tmpdir}/$vmid.pid";
2397 sub next_migrate_port
{
2399 for (my $p = 60000; $p < 60010; $p++) {
2401 my $sock = IO
::Socket
::INET-
>new(Listen
=> 5,
2402 LocalAddr
=> 'localhost',
2413 die "unable to find free migration port";
2416 sub vm_devices_list
{
2419 my $res = vm_mon_cmd
($vmid, 'query-pci');
2422 foreach my $pcibus (@$res) {
2423 foreach my $device (@{$pcibus->{devices
}}) {
2424 next if !$device->{'qdev_id'};
2425 $devices->{$device->{'qdev_id'}} = $device;
2433 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2435 return 1 if !check_running
($vmid) || !$conf->{hotplug
};
2437 my $devices_list = vm_devices_list
($vmid);
2438 return 1 if defined($devices_list->{$deviceid});
2440 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2442 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2443 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2444 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2445 qemu_deviceadd
($vmid, $devicefull);
2446 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2447 qemu_drivedel
($vmid, $deviceid);
2452 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2453 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2454 my $pciaddr = print_pci_addr
($deviceid);
2455 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2456 qemu_deviceadd
($vmid, $devicefull);
2457 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2460 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2461 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2462 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2463 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2464 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2465 if(!qemu_deviceadd
($vmid, $devicefull)) {
2466 qemu_drivedel
($vmid, $deviceid);
2471 if ($deviceid =~ m/^(net)(\d+)$/) {
2472 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2473 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2474 qemu_deviceadd
($vmid, $netdevicefull);
2475 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2476 qemu_netdevdel
($vmid, $deviceid);
2481 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2483 my $pciaddr = print_pci_addr
($deviceid);
2484 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2485 qemu_deviceadd
($vmid, $devicefull);
2486 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2492 sub vm_deviceunplug
{
2493 my ($vmid, $conf, $deviceid) = @_;
2495 return 1 if !check_running
($vmid) || !$conf->{hotplug
};
2497 my $devices_list = vm_devices_list
($vmid);
2498 return 1 if !defined($devices_list->{$deviceid});
2500 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2502 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2503 return undef if !qemu_drivedel
($vmid, $deviceid);
2504 qemu_devicedel
($vmid, $deviceid);
2505 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2508 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2509 return undef if !qemu_devicedel
($vmid, $deviceid);
2512 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2513 return undef if !qemu_devicedel
($vmid, $deviceid);
2514 return undef if !qemu_drivedel
($vmid, $deviceid);
2517 if ($deviceid =~ m/^(net)(\d+)$/) {
2518 return undef if !qemu_netdevdel
($vmid, $deviceid);
2519 qemu_devicedel
($vmid, $deviceid);
2520 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2526 sub qemu_deviceadd
{
2527 my ($vmid, $devicefull) = @_;
2529 my $ret = vm_human_monitor_command
($vmid, "device_add $devicefull");
2531 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2532 return 1 if $ret eq "";
2533 syslog
("err", "error on hotplug device : $ret");
2538 sub qemu_devicedel
{
2539 my($vmid, $deviceid) = @_;
2541 my $ret = vm_human_monitor_command
($vmid, "device_del $deviceid");
2543 return 1 if $ret eq "";
2544 syslog
("err", "detaching device $deviceid failed : $ret");
2549 my($storecfg, $vmid, $device) = @_;
2551 my $drive = print_drive_full
($storecfg, $vmid, $device);
2552 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2553 # If the command succeeds qemu prints: "OK"
2554 if ($ret !~ m/OK/s) {
2555 syslog
("err", "adding drive failed: $ret");
2562 my($vmid, $deviceid) = @_;
2564 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2566 if ($ret =~ m/Device \'.*?\' not found/s) {
2567 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2569 elsif ($ret ne "") {
2570 syslog
("err", "deleting drive $deviceid failed : $ret");
2576 sub qemu_deviceaddverify
{
2577 my ($vmid,$deviceid) = @_;
2579 for (my $i = 0; $i <= 5; $i++) {
2580 my $devices_list = vm_devices_list
($vmid);
2581 return 1 if defined($devices_list->{$deviceid});
2584 syslog
("err", "error on hotplug device $deviceid");
2589 sub qemu_devicedelverify
{
2590 my ($vmid,$deviceid) = @_;
2592 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2593 for (my $i = 0; $i <= 5; $i++) {
2594 my $devices_list = vm_devices_list
($vmid);
2595 return 1 if !defined($devices_list->{$deviceid});
2598 syslog
("err", "error on hot-unplugging device $deviceid");
2602 sub qemu_findorcreatescsihw
{
2603 my ($storecfg, $conf, $vmid, $device) = @_;
2605 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2606 my $controller = int($device->{index} / $maxdev);
2607 my $scsihwid="scsihw$controller";
2608 my $devices_list = vm_devices_list
($vmid);
2610 if(!defined($devices_list->{$scsihwid})) {
2611 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2616 sub qemu_bridgeadd
{
2617 my ($storecfg, $conf, $vmid, $device) = @_;
2620 my $bridgeid = undef;
2621 print_pci_addr
($device, $bridges);
2623 while (my ($k, $v) = each %$bridges) {
2626 return if $bridgeid < 1;
2627 my $bridge = "pci.$bridgeid";
2628 my $devices_list = vm_devices_list
($vmid);
2630 if(!defined($devices_list->{$bridge})) {
2631 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2636 sub qemu_netdevadd
{
2637 my ($vmid, $conf, $device, $deviceid) = @_;
2639 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2640 my $ret = vm_human_monitor_command
($vmid, "netdev_add $netdev");
2643 #if the command succeeds, no output is sent. So any non-empty string shows an error
2644 return 1 if $ret eq "";
2645 syslog
("err", "adding netdev failed: $ret");
2649 sub qemu_netdevdel
{
2650 my ($vmid, $deviceid) = @_;
2652 my $ret = vm_human_monitor_command
($vmid, "netdev_del $deviceid");
2654 #if the command succeeds, no output is sent. So any non-empty string shows an error
2655 return 1 if $ret eq "";
2656 syslog
("err", "deleting netdev failed: $ret");
2660 sub qemu_block_set_io_throttle
{
2661 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2663 return if !check_running
($vmid) ;
2666 $bps_rd = 0 if !$bps_rd;
2667 $bps_wr = 0 if !$bps_wr;
2668 $iops = 0 if !$iops;
2669 $iops_rd = 0 if !$iops_rd;
2670 $iops_wr = 0 if !$iops_wr;
2672 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));
2676 # old code, only used to shutdown old VM after update
2678 my ($fh, $timeout) = @_;
2680 my $sel = new IO
::Select
;
2687 while (scalar (@ready = $sel->can_read($timeout))) {
2689 if ($count = $fh->sysread($buf, 8192)) {
2690 if ($buf =~ /^(.*)\(qemu\) $/s) {
2697 if (!defined($count)) {
2704 die "monitor read timeout\n" if !scalar(@ready);
2709 # old code, only used to shutdown old VM after update
2710 sub vm_monitor_command
{
2711 my ($vmid, $cmdstr, $nocheck) = @_;
2716 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2718 my $sname = "${var_run_tmpdir}/$vmid.mon";
2720 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2721 die "unable to connect to VM $vmid socket - $!\n";
2725 # hack: migrate sometime blocks the monitor (when migrate_downtime
2727 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2728 $timeout = 60*60; # 1 hour
2732 my $data = __read_avail
($sock, $timeout);
2734 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2735 die "got unexpected qemu monitor banner\n";
2738 my $sel = new IO
::Select
;
2741 if (!scalar(my @ready = $sel->can_write($timeout))) {
2742 die "monitor write error - timeout";
2745 my $fullcmd = "$cmdstr\r";
2747 # syslog('info', "VM $vmid monitor command: $cmdstr");
2750 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2751 die "monitor write error - $!";
2754 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2758 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2759 $timeout = 60*60; # 1 hour
2760 } elsif ($cmdstr =~ m/^(eject|change)/) {
2761 $timeout = 60; # note: cdrom mount command is slow
2763 if ($res = __read_avail
($sock, $timeout)) {
2765 my @lines = split("\r?\n", $res);
2767 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2769 $res = join("\n", @lines);
2777 syslog
("err", "VM $vmid monitor command failed - $err");
2784 sub qemu_block_resize
{
2785 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2787 my $running = PVE
::QemuServer
::check_running
($vmid);
2789 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2791 return if !$running;
2793 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2797 sub qemu_volume_snapshot
{
2798 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2800 my $running = PVE
::QemuServer
::check_running
($vmid);
2802 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2804 return if !$running;
2806 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2810 sub qemu_volume_snapshot_delete
{
2811 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2813 #need to implement statefile location
2814 my $statefile="/tmp/$vmid-$snap";
2816 unlink $statefile if -e
$statefile;
2818 my $running = PVE
::QemuServer
::check_running
($vmid);
2820 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2822 return if !$running;
2824 #need to split delvm monitor command like savevm
2828 sub qemu_snapshot_start
{
2829 my ($vmid, $snap) = @_;
2831 #need to implement statefile location
2832 my $statefile="/tmp/$vmid-$snap";
2834 vm_mon_cmd
($vmid, "snapshot-start", statefile
=> $statefile);
2838 sub qemu_snapshot_end
{
2841 vm_mon_cmd
($vmid, "snapshot-end");
2848 #need to impplement call to qemu-ga
2851 sub qga_unfreezefs
{
2854 #need to impplement call to qemu-ga
2858 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom) = @_;
2860 lock_config
($vmid, sub {
2861 my $conf = load_config
($vmid, $migratedfrom);
2863 check_lock
($conf) if !$skiplock;
2865 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
2868 my $migrate_port = 0;
2871 if ($statefile eq 'tcp') {
2872 $migrate_port = next_migrate_port
();
2873 $migrate_uri = "tcp:localhost:${migrate_port}";
2875 if (-f
$statefile) {
2876 $migrate_uri = "exec:cat $statefile";
2878 warn "state file '$statefile' does not exist - doing normal startup\n";
2883 my $defaults = load_defaults
();
2885 # set environment variable useful inside network script
2886 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
2888 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults, $migrate_uri);
2890 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2891 my $d = parse_hostpci
($conf->{"hostpci$i"});
2893 my $info = pci_device_info
("0000:$d->{pciid}");
2894 die "IOMMU not present\n" if !check_iommu_support
();
2895 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2896 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
2897 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
2900 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
2902 eval { run_command
($cmd, timeout
=> $migrate_uri ?
undef : 30); };
2904 die "start failed: $err" if $err;
2908 if ($statefile eq 'tcp') {
2909 print "migration listens on port $migrate_port\n";
2912 # fixme: send resume - is that necessary ?
2913 eval { vm_mon_cmd
($vmid, "cont"); };
2917 # always set migrate speed (overwrite kvm default of 32m)
2918 # we set a very hight default of 8192m which is basically unlimited
2919 my $migrate_speed = $defaults->{migrate_speed
} || 8192;
2920 $migrate_speed = $conf->{migrate_speed
} || $migrate_speed;
2921 $migrate_speed = $migrate_speed * 1048576;
2923 vm_mon_cmd
($vmid, "migrate_set_speed", value
=> $migrate_speed);
2926 my $migrate_downtime = $defaults->{migrate_downtime
};
2927 $migrate_downtime = $conf->{migrate_downtime
} if defined($conf->{migrate_downtime
});
2928 if (defined($migrate_downtime)) {
2929 eval { vm_mon_cmd
($vmid, "migrate_set_downtime", value
=> $migrate_downtime); };
2933 my $capabilities = {};
2934 $capabilities->{capability
} = "xbzrle";
2935 $capabilities->{state} = JSON
::true
;
2936 eval { PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
2939 vm_balloonset
($vmid, $conf->{balloon
}) if $conf->{balloon
};
2945 my ($vmid, $execute, %params) = @_;
2947 my $cmd = { execute
=> $execute, arguments
=> \
%params };
2948 vm_qmp_command
($vmid, $cmd);
2951 sub vm_mon_cmd_nocheck
{
2952 my ($vmid, $execute, %params) = @_;
2954 my $cmd = { execute
=> $execute, arguments
=> \
%params };
2955 vm_qmp_command
($vmid, $cmd, 1);
2958 sub vm_qmp_command
{
2959 my ($vmid, $cmd, $nocheck) = @_;
2964 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
2965 $timeout = $cmd->{arguments
}->{timeout
};
2966 delete $cmd->{arguments
}->{timeout
};
2970 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2971 my $sname = PVE
::QemuServer
::qmp_socket
($vmid);
2973 my $qmpclient = PVE
::QMPClient-
>new();
2975 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
2976 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
2977 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
2978 if scalar(%{$cmd->{arguments
}});
2979 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
2981 die "unable to open monitor socket\n";
2985 syslog
("err", "VM $vmid qmp command failed - $err");
2992 sub vm_human_monitor_command
{
2993 my ($vmid, $cmdline) = @_;
2998 execute
=> 'human-monitor-command',
2999 arguments
=> { 'command-line' => $cmdline},
3002 return vm_qmp_command
($vmid, $cmd);
3005 sub vm_commandline
{
3006 my ($storecfg, $vmid) = @_;
3008 my $conf = load_config
($vmid);
3010 my $defaults = load_defaults
();
3012 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3014 return join(' ', @$cmd);
3018 my ($vmid, $skiplock) = @_;
3020 lock_config
($vmid, sub {
3022 my $conf = load_config
($vmid);
3024 check_lock
($conf) if !$skiplock;
3026 vm_mon_cmd
($vmid, "system_reset");
3030 sub get_vm_volumes
{
3034 foreach_drive
($conf, sub {
3035 my ($ds, $drive) = @_;
3037 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3040 my $volid = $drive->{file
};
3041 return if !$volid || $volid =~ m
|^/|;
3043 push @$vollist, $volid;
3049 sub vm_stop_cleanup
{
3050 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3053 fairsched_rmnod
($vmid); # try to destroy group
3056 my $vollist = get_vm_volumes
($conf);
3057 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3060 foreach my $ext (qw(mon qmp pid vnc qga)) {
3061 unlink "/var/run/qemu-server/${vmid}.$ext";
3064 warn $@ if $@; # avoid errors - just warn
3067 # Note: use $nockeck to skip tests if VM configuration file exists.
3068 # We need that when migration VMs to other nodes (files already moved)
3069 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3071 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3073 $force = 1 if !defined($force) && !$shutdown;
3076 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3077 kill 15, $pid if $pid;
3078 my $conf = load_config
($vmid, $migratedfrom);
3079 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3083 lock_config
($vmid, sub {
3085 my $pid = check_running
($vmid, $nocheck);
3090 $conf = load_config
($vmid);
3091 check_lock
($conf) if !$skiplock;
3092 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3093 my $opts = parse_startup
($conf->{startup
});
3094 $timeout = $opts->{down
} if $opts->{down
};
3098 $timeout = 60 if !defined($timeout);
3102 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3105 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3112 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3117 if ($count >= $timeout) {
3119 warn "VM still running - terminating now with SIGTERM\n";
3122 die "VM quit/powerdown failed - got timeout\n";
3125 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3130 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3133 die "VM quit/powerdown failed\n";
3141 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3146 if ($count >= $timeout) {
3147 warn "VM still running - terminating now with SIGKILL\n";
3152 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3157 my ($vmid, $skiplock) = @_;
3159 lock_config
($vmid, sub {
3161 my $conf = load_config
($vmid);
3163 check_lock
($conf) if !$skiplock;
3165 vm_mon_cmd
($vmid, "stop");
3170 my ($vmid, $skiplock) = @_;
3172 lock_config
($vmid, sub {
3174 my $conf = load_config
($vmid);
3176 check_lock
($conf) if !$skiplock;
3178 vm_mon_cmd
($vmid, "cont");
3183 my ($vmid, $skiplock, $key) = @_;
3185 lock_config
($vmid, sub {
3187 my $conf = load_config
($vmid);
3189 # there is no qmp command, so we use the human monitor command
3190 vm_human_monitor_command
($vmid, "sendkey $key");
3195 my ($storecfg, $vmid, $skiplock) = @_;
3197 lock_config
($vmid, sub {
3199 my $conf = load_config
($vmid);
3201 check_lock
($conf) if !$skiplock;
3203 if (!check_running
($vmid)) {
3204 fairsched_rmnod
($vmid); # try to destroy group
3205 destroy_vm
($storecfg, $vmid);
3207 die "VM $vmid is running - destroy failed\n";
3215 my ($filename, $buf) = @_;
3217 my $fh = IO
::File-
>new($filename, "w");
3218 return undef if !$fh;
3220 my $res = print $fh $buf;
3227 sub pci_device_info
{
3232 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3233 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3235 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3236 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3238 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3239 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3241 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3242 return undef if !defined($product) || $product !~ s/^0x//;
3247 product
=> $product,
3253 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3262 my $name = $dev->{name
};
3264 my $fn = "$pcisysfs/devices/$name/reset";
3266 return file_write
($fn, "1");
3269 sub pci_dev_bind_to_stub
{
3272 my $name = $dev->{name
};
3274 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3275 return 1 if -d
$testdir;
3277 my $data = "$dev->{vendor} $dev->{product}";
3278 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3280 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3281 if (!file_write
($fn, $name)) {
3282 return undef if -f
$fn;
3285 $fn = "$pcisysfs/drivers/pci-stub/bind";
3286 if (! -d
$testdir) {
3287 return undef if !file_write
($fn, $name);
3293 sub print_pci_addr
{
3294 my ($id, $bridges) = @_;
3298 #addr1 : ide,parallel,serial (motherboard)
3299 #addr2 : first videocard
3300 balloon0
=> { bus
=> 0, addr
=> 3 },
3301 watchdog
=> { bus
=> 0, addr
=> 4 },
3302 scsihw0
=> { bus
=> 0, addr
=> 5 },
3303 scsihw1
=> { bus
=> 0, addr
=> 6 },
3304 ahci0
=> { bus
=> 0, addr
=> 7 },
3305 qga0
=> { bus
=> 0, addr
=> 8 },
3306 virtio0
=> { bus
=> 0, addr
=> 10 },
3307 virtio1
=> { bus
=> 0, addr
=> 11 },
3308 virtio2
=> { bus
=> 0, addr
=> 12 },
3309 virtio3
=> { bus
=> 0, addr
=> 13 },
3310 virtio4
=> { bus
=> 0, addr
=> 14 },
3311 virtio5
=> { bus
=> 0, addr
=> 15 },
3312 hostpci0
=> { bus
=> 0, addr
=> 16 },
3313 hostpci1
=> { bus
=> 0, addr
=> 17 },
3314 net0
=> { bus
=> 0, addr
=> 18 },
3315 net1
=> { bus
=> 0, addr
=> 19 },
3316 net2
=> { bus
=> 0, addr
=> 20 },
3317 net3
=> { bus
=> 0, addr
=> 21 },
3318 net4
=> { bus
=> 0, addr
=> 22 },
3319 net5
=> { bus
=> 0, addr
=> 23 },
3320 #addr29 : usb-host (pve-usb.cfg)
3321 'pci.1' => { bus
=> 0, addr
=> 30 },
3322 'pci.2' => { bus
=> 0, addr
=> 31 },
3323 'net6' => { bus
=> 1, addr
=> 1 },
3324 'net7' => { bus
=> 1, addr
=> 2 },
3325 'net8' => { bus
=> 1, addr
=> 3 },
3326 'net9' => { bus
=> 1, addr
=> 4 },
3327 'net10' => { bus
=> 1, addr
=> 5 },
3328 'net11' => { bus
=> 1, addr
=> 6 },
3329 'net12' => { bus
=> 1, addr
=> 7 },
3330 'net13' => { bus
=> 1, addr
=> 8 },
3331 'net14' => { bus
=> 1, addr
=> 9 },
3332 'net15' => { bus
=> 1, addr
=> 10 },
3333 'net16' => { bus
=> 1, addr
=> 11 },
3334 'net17' => { bus
=> 1, addr
=> 12 },
3335 'net18' => { bus
=> 1, addr
=> 13 },
3336 'net19' => { bus
=> 1, addr
=> 14 },
3337 'net20' => { bus
=> 1, addr
=> 15 },
3338 'net21' => { bus
=> 1, addr
=> 16 },
3339 'net22' => { bus
=> 1, addr
=> 17 },
3340 'net23' => { bus
=> 1, addr
=> 18 },
3341 'net24' => { bus
=> 1, addr
=> 19 },
3342 'net25' => { bus
=> 1, addr
=> 20 },
3343 'net26' => { bus
=> 1, addr
=> 21 },
3344 'net27' => { bus
=> 1, addr
=> 22 },
3345 'net28' => { bus
=> 1, addr
=> 23 },
3346 'net29' => { bus
=> 1, addr
=> 24 },
3347 'net30' => { bus
=> 1, addr
=> 25 },
3348 'net31' => { bus
=> 1, addr
=> 26 },
3349 'virtio6' => { bus
=> 2, addr
=> 1 },
3350 'virtio7' => { bus
=> 2, addr
=> 2 },
3351 'virtio8' => { bus
=> 2, addr
=> 3 },
3352 'virtio9' => { bus
=> 2, addr
=> 4 },
3353 'virtio10' => { bus
=> 2, addr
=> 5 },
3354 'virtio11' => { bus
=> 2, addr
=> 6 },
3355 'virtio12' => { bus
=> 2, addr
=> 7 },
3356 'virtio13' => { bus
=> 2, addr
=> 8 },
3357 'virtio14' => { bus
=> 2, addr
=> 9 },
3358 'virtio15' => { bus
=> 2, addr
=> 10 },
3361 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3362 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3363 my $bus = $devices->{$id}->{bus
};
3364 $res = ",bus=pci.$bus,addr=$addr";
3365 $bridges->{$bus} = 1 if $bridges;
3372 my ($vmid, $value) = @_;
3374 vm_mon_cmd
($vmid, "balloon", value
=> $value);
3377 # vzdump restore implementaion
3379 sub archive_read_firstfile
{
3380 my $archive = shift;
3382 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3384 # try to detect archive type first
3385 my $pid = open (TMP
, "tar tf '$archive'|") ||
3386 die "unable to open file '$archive'\n";
3387 my $firstfile = <TMP
>;
3391 die "ERROR: archive contaions no data\n" if !$firstfile;
3397 sub restore_cleanup
{
3398 my $statfile = shift;
3400 print STDERR
"starting cleanup\n";
3402 if (my $fd = IO
::File-
>new($statfile, "r")) {
3403 while (defined(my $line = <$fd>)) {
3404 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3407 if ($volid =~ m
|^/|) {
3408 unlink $volid || die 'unlink failed\n';
3410 my $cfg = cfs_read_file
('storage.cfg');
3411 PVE
::Storage
::vdisk_free
($cfg, $volid);
3413 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3415 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3417 print STDERR
"unable to parse line in statfile - $line";
3424 sub restore_archive
{
3425 my ($archive, $vmid, $user, $opts) = @_;
3427 if ($archive ne '-') {
3428 my $firstfile = archive_read_firstfile
($archive);
3429 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3430 if $firstfile ne 'qemu-server.conf';
3433 my $tocmd = "/usr/lib/qemu-server/qmextract";
3435 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
3436 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
3437 $tocmd .= ' --prealloc' if $opts->{prealloc
};
3438 $tocmd .= ' --info' if $opts->{info
};
3440 # tar option "xf" does not autodetect compression when read from STDIN,
3441 # so we pipe to zcat
3442 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
3443 PVE
::Tools
::shellquote
("--to-command=$tocmd");
3445 my $tmpdir = "/var/tmp/vzdumptmp$$";
3448 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
3449 local $ENV{VZDUMP_VMID
} = $vmid;
3450 local $ENV{VZDUMP_USER
} = $user;
3452 my $conffile = PVE
::QemuServer
::config_file
($vmid);
3453 my $tmpfn = "$conffile.$$.tmp";
3455 # disable interrupts (always do cleanups)
3456 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3457 print STDERR
"got interrupt - ignored\n";
3462 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3463 die "interrupted by signal\n";
3466 if ($archive eq '-') {
3467 print "extracting archive from STDIN\n";
3468 run_command
($cmd, input
=> "<&STDIN");
3470 print "extracting archive '$archive'\n";
3474 return if $opts->{info
};
3478 my $statfile = "$tmpdir/qmrestore.stat";
3479 if (my $fd = IO
::File-
>new($statfile, "r")) {
3480 while (defined (my $line = <$fd>)) {
3481 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3482 $map->{$1} = $2 if $1;
3484 print STDERR
"unable to parse line in statfile - $line\n";
3490 my $confsrc = "$tmpdir/qemu-server.conf";
3492 my $srcfd = new IO
::File
($confsrc, "r") ||
3493 die "unable to open file '$confsrc'\n";
3495 my $outfd = new IO
::File
($tmpfn, "w") ||
3496 die "unable to write config for VM $vmid\n";
3500 while (defined (my $line = <$srcfd>)) {
3501 next if $line =~ m/^\#vzdump\#/;
3502 next if $line =~ m/^lock:/;
3503 next if $line =~ m/^unused\d+:/;
3505 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3506 # try to convert old 1.X settings
3507 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3508 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3509 my ($model, $macaddr) = split(/\=/, $devconfig);
3510 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $opts->{unique
};
3513 bridge
=> "vmbr$ind",
3514 macaddr
=> $macaddr,
3516 my $netstr = print_net
($net);
3517 print $outfd "net${netcount}: $netstr\n";
3520 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && ($opts->{unique
})) {
3521 my ($id, $netstr) = ($1, $2);
3522 my $net = parse_net
($netstr);
3523 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3524 $netstr = print_net
($net);
3525 print $outfd "$id: $netstr\n";
3526 } elsif ($line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/) {
3529 if ($line =~ m/backup=no/) {
3530 print $outfd "#$line";
3531 } elsif ($virtdev && $map->{$virtdev}) {
3532 my $di = PVE
::QemuServer
::parse_drive
($virtdev, $value);
3533 $di->{file
} = $map->{$virtdev};
3534 $value = PVE
::QemuServer
::print_drive
($vmid, $di);
3535 print $outfd "$virtdev: $value\n";
3553 restore_cleanup
("$tmpdir/qmrestore.stat") if !$opts->{info
};
3560 rename $tmpfn, $conffile ||
3561 die "unable to commit configuration file '$conffile'\n";
3565 # Internal snapshots
3567 # NOTE: Snapshot create/delete involves several non-atomic
3568 # action, and can take a long time.
3569 # So we try to avoid locking the file and use 'lock' variable
3570 # inside the config file instead.
3572 my $snapshot_copy_config = sub {
3573 my ($source, $dest) = @_;
3575 foreach my $k (keys %$source) {
3576 next if $k eq 'snapshots';
3577 next if $k eq 'lock';
3578 next if $k eq 'digest';
3579 next if $k =~ m/^unused\d+$/;
3581 $dest->{$k} = $source->{$k};
3585 my $snapshot_apply_config = sub {
3586 my ($conf, $snap) = @_;
3588 # copy snapshot list
3590 snapshots
=> $conf->{snapshots
},
3593 # keep list of unused disks
3594 foreach my $k (keys %$conf) {
3595 next if $k !~ m/^unused\d+$/;
3596 $newconf->{$k} = $conf->{$k};
3599 &$snapshot_copy_config($snap, $newconf);
3604 my $snapshot_prepare = sub {
3605 my ($vmid, $snapname) = @_;
3609 my $updatefn = sub {
3611 my $conf = load_config
($vmid);
3615 $conf->{lock} = 'snapshot';
3617 die "snapshot name '$snapname' already used\n"
3618 if defined($conf->{snapshots
}->{$snapname});
3620 my $storecfg = PVE
::Storage
::config
();
3622 PVE
::QemuServer
::foreach_drive
($conf, sub {
3623 my ($ds, $drive) = @_;
3625 return if drive_is_cdrom
($drive);
3626 my $volid = $drive->{file
};
3628 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3630 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
3631 die "can't snapshot volume '$volid'\n"
3632 if !(($scfg->{path
} && $volname =~ m/\.qcow2$/) ||
3633 ($scfg->{type
} eq 'rbd') ||
3634 ($scfg->{type
} eq 'sheepdog'));
3635 } elsif ($volid =~ m
|^(/.+)$| && -e
$volid) {
3636 die "snapshot device '$volid' is not possible\n";
3638 die "can't snapshot volume '$volid'\n";
3642 $snap = $conf->{snapshots
}->{$snapname} = {
3643 snapstate
=> "prepare",
3646 &$snapshot_copy_config($conf, $snap);
3648 update_config_nolock
($vmid, $conf, 1);
3651 lock_config
($vmid, $updatefn);
3656 my $snapshot_commit = sub {
3657 my ($vmid, $snapname) = @_;
3659 my $updatefn = sub {
3661 my $conf = load_config
($vmid);
3663 die "missing snapshot lock\n"
3664 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
3666 my $snap = $conf->{snapshots
}->{$snapname};
3668 die "snapshot '$snapname' does not exist\n" if !defined($snap);
3670 die "wrong snapshot state\n"
3671 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
3673 delete $snap->{snapstate
};
3674 delete $conf->{lock};
3676 my $newconf = &$snapshot_apply_config($conf, $snap);
3678 update_config_nolock
($vmid, $newconf, 1);
3681 lock_config
($vmid, $updatefn);
3684 sub snapshot_rollback
{
3685 my ($vmid, $snapname) = @_;
3691 my $updatefn = sub {
3693 my $conf = load_config
($vmid);
3695 check_lock
($conf) if $prepare;
3697 die "unable to rollback vm $vmid: vm is running\n"
3698 if check_running
($vmid);
3701 $conf->{lock} = 'rollback';
3703 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
3704 delete $conf->{lock};
3707 $snap = $conf->{snapshots
}->{$snapname};
3709 die "snapshot '$snapname' does not exist\n" if !defined($snap);
3711 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
3712 if $snap->{snapstate
};
3715 # copy snapshot config to current config
3716 $conf = &$snapshot_apply_config($conf, $snap);
3717 $conf->{parent
} = $snapname;
3720 update_config_nolock
($vmid, $conf, 1);
3723 lock_config
($vmid, $updatefn);
3725 my $storecfg = PVE
::Storage
::config
();
3727 foreach_drive
($snap, sub {
3728 my ($ds, $drive) = @_;
3730 return if drive_is_cdrom
($drive);
3732 my $volid = $drive->{file
};
3733 my $device = "drive-$ds";
3735 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
3739 lock_config
($vmid, $updatefn);
3742 sub snapshot_create
{
3743 my ($vmid, $snapname, $vmstate, $freezefs) = @_;
3745 my $snap = &$snapshot_prepare($vmid, $snapname);
3748 # create internal snapshots of all drives
3750 qemu_snapshot_start
($vmid, $snapname) if $vmstate;
3752 qga_freezefs
($vmid) if $freezefs;
3754 my $storecfg = PVE
::Storage
::config
();
3756 foreach_drive
($snap, sub {
3757 my ($ds, $drive) = @_;
3759 return if drive_is_cdrom
($drive);
3761 my $volid = $drive->{file
};
3762 my $device = "drive-$ds";
3764 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
3769 eval { gqa_unfreezefs
($vmid) if $freezefs; };
3772 eval { qemu_snapshot_end
($vmid) if $vmstate; };
3776 warn "snapshot create failed: starting cleanup\n";
3777 eval { snapshot_delete
($vmid, $snapname, 1); };
3782 &$snapshot_commit($vmid, $snapname);
3785 sub snapshot_delete
{
3786 my ($vmid, $snapname, $force) = @_;
3793 my $updatefn = sub {
3795 my $conf = load_config
($vmid);
3797 check_lock
($conf) if !$force;
3799 $snap = $conf->{snapshots
}->{$snapname};
3801 die "snapshot '$snapname' does not exist\n" if !defined($snap);
3803 # remove parent refs
3804 foreach my $sn (keys %{$conf->{snapshots
}}) {
3805 next if $sn eq $snapname;
3806 my $snapref = $conf->{snapshots
}->{$sn};
3807 if ($snapref->{parent
} && $snapref->{parent
} eq $snapname) {
3808 if ($snap->{parent
}) {
3809 $snapref->{parent
} = $snap->{parent
};
3811 delete $snapref->{parent
};
3817 $snap->{snapstate
} = 'delete';
3819 delete $conf->{parent
} if $conf->{parent
} && $conf->{parent
} eq $snapname;
3820 delete $conf->{snapshots
}->{$snapname};
3821 foreach my $volid (@$unused) {
3822 add_unused_volume
($conf, $volid);
3826 update_config_nolock
($vmid, $conf, 1);
3829 lock_config
($vmid, $updatefn);
3831 # now remove all internal snapshots
3833 my $storecfg = PVE
::Storage
::config
();
3835 PVE
::QemuServer
::foreach_drive
($snap, sub {
3836 my ($ds, $drive) = @_;
3838 return if drive_is_cdrom
($drive);
3839 my $volid = $drive->{file
};
3840 my $device = "drive-$ds";
3842 qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname);
3843 push @$unused, $volid;
3846 # now cleanup config
3848 lock_config
($vmid, $updatefn);