1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
34 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
36 # Note about locking: we use flock on the config file protect
37 # against concurent actions.
38 # Aditionaly, we have a 'lock' setting in the config file. This
39 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
40 # allowed when such lock is set. But you can ignore this kind of
41 # lock with the --skiplock flag.
43 cfs_register_file
('/qemu-server/',
47 PVE
::JSONSchema
::register_standard_option
('skiplock', {
48 description
=> "Ignore locks - only root is allowed to use this option.",
53 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
54 description
=> "Some command save/restore state from this location.",
60 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
61 description
=> "The name of the snapshot.",
62 type
=> 'string', format
=> 'pve-configid',
66 #no warnings 'redefine';
68 unless(defined(&_VZSYSCALLS_H_
)) {
69 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
70 require 'sys/syscall.ph';
71 if(defined(&__x86_64__
)) {
72 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
73 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
74 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
75 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
76 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
77 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
78 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
79 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
81 elsif(defined( &__i386__
) ) {
82 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
83 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
84 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
85 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
86 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
87 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
88 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
89 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
91 die("no fairsched syscall for this arch");
93 require 'asm/ioctl.ph';
94 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
98 my ($parent, $weight, $desired) = @_;
100 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
103 sub fairsched_rmnod
{
106 return syscall(&__NR_fairsched_rmnod
, int($id));
110 my ($pid, $newid) = @_;
112 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
115 sub fairsched_vcpus
{
116 my ($id, $vcpus) = @_;
118 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
122 my ($id, $op, $rate) = @_;
124 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
127 use constant FAIRSCHED_SET_RATE
=> 0;
128 use constant FAIRSCHED_DROP_RATE
=> 1;
129 use constant FAIRSCHED_GET_RATE
=> 2;
131 sub fairsched_cpulimit
{
132 my ($id, $limit) = @_;
134 my $cpulim1024 = int($limit * 1024 / 100);
135 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
137 return fairsched_rate
($id, $op, $cpulim1024);
140 my $nodename = PVE
::INotify
::nodename
();
142 mkdir "/etc/pve/nodes/$nodename";
143 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
146 my $var_run_tmpdir = "/var/run/qemu-server";
147 mkdir $var_run_tmpdir;
149 my $lock_dir = "/var/lock/qemu-server";
152 my $pcisysfs = "/sys/bus/pci";
158 description
=> "Specifies whether a VM will be started during system bootup.",
164 description
=> "Automatic restart after crash (currently ignored).",
170 description
=> "Allow hotplug for disk and network device",
176 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
182 description
=> "Lock/unlock the VM.",
183 enum
=> [qw(migrate backup snapshot rollback)],
188 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.",
195 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.",
203 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
210 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
216 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",
224 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
225 enum
=> PVE
::Tools
::kvmkeymaplist
(),
230 type
=> 'string', format
=> 'dns-name',
231 description
=> "Set a name for the VM. Only used on the configuration web interface.",
236 description
=> "scsi controller model",
237 enum
=> [qw(lsi virtio-scsi-pci megasas pvscsi)],
243 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
248 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
249 description
=> <<EODESC,
250 Used to enable special optimization/features for specific
253 other => unspecified OS
254 wxp => Microsoft Windows XP
255 w2k => Microsoft Windows 2000
256 w2k3 => Microsoft Windows 2003
257 w2k8 => Microsoft Windows 2008
258 wvista => Microsoft Windows Vista
259 win7 => Microsoft Windows 7
260 win8 => Microsoft Windows 8/2012
261 l24 => Linux 2.4 Kernel
262 l26 => Linux 2.6/3.X Kernel
263 solaris => solaris/opensolaris/openindiania kernel
265 other|l24|l26|solaris ... no special behaviour
266 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
272 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
273 pattern
=> '[acdn]{1,4}',
278 type
=> 'string', format
=> 'pve-qm-bootdisk',
279 description
=> "Enable booting from specified disk.",
280 pattern
=> '(ide|sata|scsi|virtio)\d+',
285 description
=> "The number of CPUs. Please use option -sockets instead.",
292 description
=> "The number of CPU sockets.",
299 description
=> "The number of cores per socket.",
306 description
=> "Enable/disable ACPI.",
312 description
=> "Enable/disable Qemu GuestAgent.",
318 description
=> "Enable/disable KVM hardware virtualization.",
324 description
=> "Enable/disable time drift fix.",
330 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
335 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
340 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. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
341 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
345 type
=> 'string', format
=> 'pve-qm-watchdog',
346 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
347 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)",
352 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
353 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'.",
354 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
359 type
=> 'string', format
=> 'pve-qm-startup',
360 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
361 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.",
366 description
=> "Enable/disable Template.",
372 description
=> <<EODESCR,
373 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
375 args: -no-reboot -no-hpet
382 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. 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. This is turned of by default if you use spice (vga=qxl).",
387 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
391 migrate_downtime
=> {
394 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
400 type
=> 'string', format
=> 'pve-qm-drive',
401 typetext
=> 'volume',
402 description
=> "This is an alias for option -ide2",
406 description
=> "Emulated CPU type.",
408 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) ],
411 parent
=> get_standard_option
('pve-snapshot-name', {
413 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
417 description
=> "Timestamp for snapshots.",
423 type
=> 'string', format
=> 'pve-volume-id',
424 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
427 description
=> "Specific the Qemu machine type.",
429 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
435 # what about other qemu settings ?
437 #machine => 'string',
450 ##soundhw => 'string',
452 while (my ($k, $v) = each %$confdesc) {
453 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
456 my $MAX_IDE_DISKS = 4;
457 my $MAX_SCSI_DISKS = 14;
458 my $MAX_VIRTIO_DISKS = 16;
459 my $MAX_SATA_DISKS = 6;
460 my $MAX_USB_DEVICES = 5;
462 my $MAX_UNUSED_DISKS = 8;
463 my $MAX_HOSTPCI_DEVICES = 2;
464 my $MAX_SERIAL_PORTS = 4;
465 my $MAX_PARALLEL_PORTS = 3;
467 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
468 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
469 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
473 type
=> 'string', format
=> 'pve-qm-net',
474 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
475 description
=> <<EODESCR,
476 Specify network devices.
478 MODEL is one of: $nic_model_list_txt
480 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
481 automatically generated if not specified.
483 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
485 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'.
487 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
493 The DHCP server assign addresses to the guest starting from 10.0.2.15.
497 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
499 for (my $i = 0; $i < $MAX_NETS; $i++) {
500 $confdesc->{"net$i"} = $netdesc;
507 type
=> 'string', format
=> 'pve-qm-drive',
508 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]',
509 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
511 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
515 type
=> 'string', format
=> 'pve-qm-drive',
516 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]',
517 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
519 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
523 type
=> 'string', format
=> 'pve-qm-drive',
524 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]',
525 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
527 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
531 type
=> 'string', format
=> 'pve-qm-drive',
532 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]',
533 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
535 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
539 type
=> 'string', format
=> 'pve-qm-usb-device',
540 typetext
=> 'host=HOSTUSBDEVICE|spice',
541 description
=> <<EODESCR,
542 Configure an USB device (n is 0 to 4). This can be used to
543 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
545 'bus-port(.port)*' (decimal numbers) or
546 'vendor_id:product_id' (hexadeciaml numbers)
548 You can use the 'lsusb -t' command to list existing usb devices.
550 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
552 The value 'spice' can be used to add a usb redirection devices for spice.
556 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
560 type
=> 'string', format
=> 'pve-qm-hostpci',
561 typetext
=> "HOSTPCIDEVICE",
562 description
=> <<EODESCR,
563 Map host pci devices. HOSTPCIDEVICE syntax is:
565 'bus:dev.func' (hexadecimal numbers)
567 You can us the 'lspci' command to list existing pci devices.
569 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
571 Experimental: user reported problems with this option.
574 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
579 pattern
=> '(/dev/ttyS\d+|socket)',
580 description
=> <<EODESCR,
581 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
583 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
585 Experimental: user reported problems with this option.
592 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
593 description
=> <<EODESCR,
594 Map host parallel devices (n is 0 to 2).
596 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
598 Experimental: user reported problems with this option.
602 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
603 $confdesc->{"parallel$i"} = $paralleldesc;
606 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
607 $confdesc->{"serial$i"} = $serialdesc;
610 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
611 $confdesc->{"hostpci$i"} = $hostpcidesc;
614 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
615 $drivename_hash->{"ide$i"} = 1;
616 $confdesc->{"ide$i"} = $idedesc;
619 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
620 $drivename_hash->{"sata$i"} = 1;
621 $confdesc->{"sata$i"} = $satadesc;
624 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
625 $drivename_hash->{"scsi$i"} = 1;
626 $confdesc->{"scsi$i"} = $scsidesc ;
629 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
630 $drivename_hash->{"virtio$i"} = 1;
631 $confdesc->{"virtio$i"} = $virtiodesc;
634 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
635 $confdesc->{"usb$i"} = $usbdesc;
640 type
=> 'string', format
=> 'pve-volume-id',
641 description
=> "Reference to unused volumes.",
644 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
645 $confdesc->{"unused$i"} = $unuseddesc;
648 my $kvm_api_version = 0;
652 return $kvm_api_version if $kvm_api_version;
654 my $fh = IO
::File-
>new("</dev/kvm") ||
657 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
658 $kvm_api_version = $v;
663 return $kvm_api_version;
666 my $kvm_user_version;
668 sub kvm_user_version
{
670 return $kvm_user_version if $kvm_user_version;
672 $kvm_user_version = 'unknown';
674 my $tmp = `kvm -help 2>/dev/null`;
676 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
677 $kvm_user_version = $2;
680 return $kvm_user_version;
684 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
687 # order is important - used to autoselect boot disk
688 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
689 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
690 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
691 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
694 sub valid_drivename
{
697 return defined($drivename_hash->{$dev});
702 return defined($confdesc->{$key});
706 return $nic_model_list;
709 sub os_list_description
{
714 w2k
=> 'Windows 2000',
715 w2k3
=>, 'Windows 2003',
716 w2k8
=> 'Windows 2008',
717 wvista
=> 'Windows Vista',
719 win8
=> 'Windows 8/2012',
729 return $cdrom_path if $cdrom_path;
731 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
732 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
733 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
737 my ($storecfg, $vmid, $cdrom) = @_;
739 if ($cdrom eq 'cdrom') {
740 return get_cdrom_path
();
741 } elsif ($cdrom eq 'none') {
743 } elsif ($cdrom =~ m
|^/|) {
746 return PVE
::Storage
::path
($storecfg, $cdrom);
750 # try to convert old style file names to volume IDs
751 sub filename_to_volume_id
{
752 my ($vmid, $file, $media) = @_;
754 if (!($file eq 'none' || $file eq 'cdrom' ||
755 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
757 return undef if $file =~ m
|/|;
759 if ($media && $media eq 'cdrom') {
760 $file = "local:iso/$file";
762 $file = "local:$vmid/$file";
769 sub verify_media_type
{
770 my ($opt, $vtype, $media) = @_;
775 if ($media eq 'disk') {
777 } elsif ($media eq 'cdrom') {
780 die "internal error";
783 return if ($vtype eq $etype);
785 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
788 sub cleanup_drive_path
{
789 my ($opt, $storecfg, $drive) = @_;
791 # try to convert filesystem paths to volume IDs
793 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
794 ($drive->{file
} !~ m
|^/dev/.+|) &&
795 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
796 ($drive->{file
} !~ m/^\d+$/)) {
797 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
798 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
799 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
800 verify_media_type
($opt, $vtype, $drive->{media
});
801 $drive->{file
} = $volid;
804 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
807 sub create_conf_nolock
{
808 my ($vmid, $settings) = @_;
810 my $filename = config_file
($vmid);
812 die "configuration file '$filename' already exists\n" if -f
$filename;
814 my $defaults = load_defaults
();
816 $settings->{name
} = "vm$vmid" if !$settings->{name
};
817 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
820 foreach my $opt (keys %$settings) {
821 next if !$confdesc->{$opt};
823 my $value = $settings->{$opt};
826 $data .= "$opt: $value\n";
829 PVE
::Tools
::file_set_contents
($filename, $data);
832 my $parse_size = sub {
835 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
836 my ($size, $unit) = ($1, $3);
839 $size = $size * 1024;
840 } elsif ($unit eq 'M') {
841 $size = $size * 1024 * 1024;
842 } elsif ($unit eq 'G') {
843 $size = $size * 1024 * 1024 * 1024;
849 my $format_size = sub {
854 my $kb = int($size/1024);
855 return $size if $kb*1024 != $size;
857 my $mb = int($kb/1024);
858 return "${kb}K" if $mb*1024 != $kb;
860 my $gb = int($mb/1024);
861 return "${mb}M" if $gb*1024 != $mb;
866 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
867 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
868 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
869 # [,aio=native|threads]
872 my ($key, $data) = @_;
876 # $key may be undefined - used to verify JSON parameters
877 if (!defined($key)) {
878 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
880 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
881 $res->{interface
} = $1;
887 foreach my $p (split (/,/, $data)) {
888 next if $p =~ m/^\s*$/;
890 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)=(.+)$/) {
891 my ($k, $v) = ($1, $2);
893 $k = 'file' if $k eq 'volume';
895 return undef if defined $res->{$k};
897 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
898 return undef if !$v || $v !~ m/^\d+/;
900 $v = sprintf("%.3f", $v / (1024*1024));
904 if (!$res->{file
} && $p !~ m/=/) {
912 return undef if !$res->{file
};
914 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
918 return undef if $res->{cache
} &&
919 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
920 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
921 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
922 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
923 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
924 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
925 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
926 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
927 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
928 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
929 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
930 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
933 return undef if $res->{mbps_rd
} && $res->{mbps
};
934 return undef if $res->{mbps_wr
} && $res->{mbps
};
936 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
937 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
938 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
940 return undef if $res->{iops_rd
} && $res->{iops
};
941 return undef if $res->{iops_wr
} && $res->{iops
};
942 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
943 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
944 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
948 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
951 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
952 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
953 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
954 return undef if $res->{interface
} eq 'virtio';
957 # rerror does not work with scsi drives
958 if ($res->{rerror
}) {
959 return undef if $res->{interface
} eq 'scsi';
965 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
968 my ($vmid, $drive) = @_;
971 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
972 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
975 if ($drive->{size
}) {
976 $opts .= ",size=" . &$format_size($drive->{size
});
979 return "$drive->{file}$opts";
983 my($fh, $noerr) = @_;
986 my $SG_GET_VERSION_NUM = 0x2282;
988 my $versionbuf = "\x00" x
8;
989 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
991 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
994 my $version = unpack("I", $versionbuf);
995 if ($version < 30000) {
996 die "scsi generic interface too old\n" if !$noerr;
1000 my $buf = "\x00" x
36;
1001 my $sensebuf = "\x00" x
8;
1002 my $cmd = pack("C x3 C x1", 0x12, 36);
1004 # see /usr/include/scsi/sg.h
1005 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";
1007 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1008 length($sensebuf), 0, length($buf), $buf,
1009 $cmd, $sensebuf, 6000);
1011 $ret = ioctl($fh, $SG_IO, $packet);
1013 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1017 my @res = unpack($sg_io_hdr_t, $packet);
1018 if ($res[17] || $res[18]) {
1019 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1024 (my $byte0, my $byte1, $res->{vendor
},
1025 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1027 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1028 $res->{type
} = $byte0 & 31;
1036 my $fh = IO
::File-
>new("+<$path") || return undef;
1037 my $res = scsi_inquiry
($fh, 1);
1043 sub print_drivedevice_full
{
1044 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1049 if ($drive->{interface
} eq 'virtio') {
1050 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1051 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1052 } elsif ($drive->{interface
} eq 'scsi') {
1053 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1054 my $controller = int($drive->{index} / $maxdev);
1055 my $unit = $drive->{index} % $maxdev;
1056 my $devicetype = 'hd';
1058 if (drive_is_cdrom
($drive)) {
1061 if ($drive->{file
} =~ m
|^/|) {
1062 $path = $drive->{file
};
1064 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1067 if($path =~ m/^iscsi\:\/\
//){
1068 $devicetype = 'generic';
1070 if (my $info = path_is_scsi
($path)) {
1071 if ($info->{type
} == 0) {
1072 $devicetype = 'block';
1073 } elsif ($info->{type
} == 1) { # tape
1074 $devicetype = 'generic';
1080 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1081 $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';
1083 $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}";
1086 } elsif ($drive->{interface
} eq 'ide'){
1088 my $controller = int($drive->{index} / $maxdev);
1089 my $unit = $drive->{index} % $maxdev;
1090 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1092 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1093 } elsif ($drive->{interface
} eq 'sata'){
1094 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1095 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1096 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1097 } elsif ($drive->{interface
} eq 'usb') {
1099 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1101 die "unsupported interface type";
1104 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1109 sub print_drive_full
{
1110 my ($storecfg, $vmid, $drive) = @_;
1113 foreach my $o (@qemu_drive_options) {
1114 next if $o eq 'bootindex';
1115 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1118 foreach my $o (qw(bps bps_rd bps_wr)) {
1119 my $v = $drive->{"m$o"};
1120 $opts .= ",$o=" . int($v*1024*1024) if $v;
1123 # use linux-aio by default (qemu default is threads)
1124 $opts .= ",aio=native" if !$drive->{aio
};
1127 my $volid = $drive->{file
};
1128 if (drive_is_cdrom
($drive)) {
1129 $path = get_iso_path
($storecfg, $vmid, $volid);
1131 if ($volid =~ m
|^/|) {
1134 $path = PVE
::Storage
::path
($storecfg, $volid);
1138 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1140 my $pathinfo = $path ?
"file=$path," : '';
1142 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1145 sub print_netdevice_full
{
1146 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1148 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1150 my $device = $net->{model
};
1151 if ($net->{model
} eq 'virtio') {
1152 $device = 'virtio-net-pci';
1155 # qemu > 0.15 always try to boot from network - we disable that by
1156 # not loading the pxe rom file
1157 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1158 my $pciaddr = print_pci_addr
("$netid", $bridges);
1159 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1160 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1164 sub print_netdev_full
{
1165 my ($vmid, $conf, $net, $netid) = @_;
1168 if ($netid =~ m/^net(\d+)$/) {
1172 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1174 my $ifname = "tap${vmid}i$i";
1176 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1177 die "interface name '$ifname' is too long (max 15 character)\n"
1178 if length($ifname) >= 16;
1180 my $vhostparam = '';
1181 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1183 my $vmname = $conf->{name
} || "vm$vmid";
1185 if ($net->{bridge
}) {
1186 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1188 return "type=user,id=$netid,hostname=$vmname";
1192 sub drive_is_cdrom
{
1195 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1202 return undef if !$value;
1206 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1207 $res->{pciid
} = $value;
1215 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1221 foreach my $kvp (split(/,/, $data)) {
1223 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1225 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1226 $res->{model
} = $model;
1227 $res->{macaddr
} = $mac;
1228 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1229 $res->{bridge
} = $1;
1230 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1232 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1240 return undef if !$res->{model
};
1248 my $res = "$net->{model}";
1249 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1250 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1251 $res .= ",rate=$net->{rate}" if $net->{rate
};
1252 $res .= ",tag=$net->{tag}" if $net->{tag
};
1257 sub add_random_macs
{
1258 my ($settings) = @_;
1260 foreach my $opt (keys %$settings) {
1261 next if $opt !~ m/^net(\d+)$/;
1262 my $net = parse_net
($settings->{$opt});
1264 $settings->{$opt} = print_net
($net);
1268 sub add_unused_volume
{
1269 my ($config, $volid) = @_;
1272 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1273 my $test = "unused$ind";
1274 if (my $vid = $config->{$test}) {
1275 return if $vid eq $volid; # do not add duplicates
1281 die "To many unused volume - please delete them first.\n" if !$key;
1283 $config->{$key} = $volid;
1288 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1289 sub verify_bootdisk
{
1290 my ($value, $noerr) = @_;
1292 return $value if valid_drivename
($value);
1294 return undef if $noerr;
1296 die "invalid boot disk '$value'\n";
1299 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1301 my ($value, $noerr) = @_;
1303 return $value if parse_net
($value);
1305 return undef if $noerr;
1307 die "unable to parse network options\n";
1310 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1312 my ($value, $noerr) = @_;
1314 return $value if parse_drive
(undef, $value);
1316 return undef if $noerr;
1318 die "unable to parse drive options\n";
1321 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1322 sub verify_hostpci
{
1323 my ($value, $noerr) = @_;
1325 return $value if parse_hostpci
($value);
1327 return undef if $noerr;
1329 die "unable to parse pci id\n";
1332 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1333 sub verify_watchdog
{
1334 my ($value, $noerr) = @_;
1336 return $value if parse_watchdog
($value);
1338 return undef if $noerr;
1340 die "unable to parse watchdog options\n";
1343 sub parse_watchdog
{
1346 return undef if !$value;
1350 foreach my $p (split(/,/, $value)) {
1351 next if $p =~ m/^\s*$/;
1353 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1355 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1356 $res->{action
} = $2;
1365 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1366 sub verify_startup
{
1367 my ($value, $noerr) = @_;
1369 return $value if parse_startup
($value);
1371 return undef if $noerr;
1373 die "unable to parse startup options\n";
1379 return undef if !$value;
1383 foreach my $p (split(/,/, $value)) {
1384 next if $p =~ m/^\s*$/;
1386 if ($p =~ m/^(order=)?(\d+)$/) {
1388 } elsif ($p =~ m/^up=(\d+)$/) {
1390 } elsif ($p =~ m/^down=(\d+)$/) {
1400 sub parse_usb_device
{
1403 return undef if !$value;
1405 my @dl = split(/,/, $value);
1409 foreach my $v (@dl) {
1410 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1412 $res->{vendorid
} = $2;
1413 $res->{productid
} = $4;
1414 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1416 $res->{hostbus
} = $1;
1417 $res->{hostport
} = $2;
1418 } elsif ($v =~ m/^spice$/) {
1425 return undef if !$found;
1430 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1431 sub verify_usb_device
{
1432 my ($value, $noerr) = @_;
1434 return $value if parse_usb_device
($value);
1436 return undef if $noerr;
1438 die "unable to parse usb device\n";
1441 # add JSON properties for create and set function
1442 sub json_config_properties
{
1445 foreach my $opt (keys %$confdesc) {
1446 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1447 $prop->{$opt} = $confdesc->{$opt};
1454 my ($key, $value) = @_;
1456 die "unknown setting '$key'\n" if !$confdesc->{$key};
1458 my $type = $confdesc->{$key}->{type
};
1460 if (!defined($value)) {
1461 die "got undefined value\n";
1464 if ($value =~ m/[\n\r]/) {
1465 die "property contains a line feed\n";
1468 if ($type eq 'boolean') {
1469 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1470 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1471 die "type check ('boolean') failed - got '$value'\n";
1472 } elsif ($type eq 'integer') {
1473 return int($1) if $value =~ m/^(\d+)$/;
1474 die "type check ('integer') failed - got '$value'\n";
1475 } elsif ($type eq 'number') {
1476 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1477 die "type check ('number') failed - got '$value'\n";
1478 } elsif ($type eq 'string') {
1479 if (my $fmt = $confdesc->{$key}->{format
}) {
1480 if ($fmt eq 'pve-qm-drive') {
1481 # special case - we need to pass $key to parse_drive()
1482 my $drive = parse_drive
($key, $value);
1483 return $value if $drive;
1484 die "unable to parse drive options\n";
1486 PVE
::JSONSchema
::check_format
($fmt, $value);
1489 $value =~ s/^\"(.*)\"$/$1/;
1492 die "internal error"
1496 sub lock_config_full
{
1497 my ($vmid, $timeout, $code, @param) = @_;
1499 my $filename = config_file_lock
($vmid);
1501 my $res = lock_file
($filename, $timeout, $code, @param);
1508 sub lock_config_mode
{
1509 my ($vmid, $timeout, $shared, $code, @param) = @_;
1511 my $filename = config_file_lock
($vmid);
1513 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1521 my ($vmid, $code, @param) = @_;
1523 return lock_config_full
($vmid, 10, $code, @param);
1526 sub cfs_config_path
{
1527 my ($vmid, $node) = @_;
1529 $node = $nodename if !$node;
1530 return "nodes/$node/qemu-server/$vmid.conf";
1533 sub check_iommu_support
{
1534 #fixme : need to check IOMMU support
1535 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1543 my ($vmid, $node) = @_;
1545 my $cfspath = cfs_config_path
($vmid, $node);
1546 return "/etc/pve/$cfspath";
1549 sub config_file_lock
{
1552 return "$lock_dir/lock-$vmid.conf";
1558 my $conf = config_file
($vmid);
1559 utime undef, undef, $conf;
1563 my ($storecfg, $vmid, $keep_empty_config) = @_;
1565 my $conffile = config_file
($vmid);
1567 my $conf = load_config
($vmid);
1571 # only remove disks owned by this VM
1572 foreach_drive
($conf, sub {
1573 my ($ds, $drive) = @_;
1575 return if drive_is_cdrom
($drive);
1577 my $volid = $drive->{file
};
1579 return if !$volid || $volid =~ m
|^/|;
1581 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1582 return if !$path || !$owner || ($owner != $vmid);
1584 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1587 if ($keep_empty_config) {
1588 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1593 # also remove unused disk
1595 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1598 PVE
::Storage
::foreach_volid
($dl, sub {
1599 my ($volid, $sid, $volname, $d) = @_;
1600 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1610 my ($vmid, $node) = @_;
1612 my $cfspath = cfs_config_path
($vmid, $node);
1614 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1616 die "no such VM ('$vmid')\n" if !defined($conf);
1621 sub parse_vm_config
{
1622 my ($filename, $raw) = @_;
1624 return undef if !defined($raw);
1627 digest
=> Digest
::SHA
::sha1_hex
($raw),
1631 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1632 || die "got strange filename '$filename'";
1639 my @lines = split(/\n/, $raw);
1640 foreach my $line (@lines) {
1641 next if $line =~ m/^\s*$/;
1643 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1645 $conf->{description
} = $descr if $descr;
1647 $conf = $res->{snapshots
}->{$snapname} = {};
1651 if ($line =~ m/^\#(.*)\s*$/) {
1652 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1656 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1657 $descr .= PVE
::Tools
::decode_text
($2);
1658 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1659 $conf->{snapstate
} = $1;
1660 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1663 $conf->{$key} = $value;
1664 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1667 eval { $value = check_type
($key, $value); };
1669 warn "vm $vmid - unable to parse value of '$key' - $@";
1671 my $fmt = $confdesc->{$key}->{format
};
1672 if ($fmt && $fmt eq 'pve-qm-drive') {
1673 my $v = parse_drive
($key, $value);
1674 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1675 $v->{file
} = $volid;
1676 $value = print_drive
($vmid, $v);
1678 warn "vm $vmid - unable to parse value of '$key'\n";
1683 if ($key eq 'cdrom') {
1684 $conf->{ide2
} = $value;
1686 $conf->{$key} = $value;
1692 $conf->{description
} = $descr if $descr;
1694 delete $res->{snapstate
}; # just to be sure
1699 sub write_vm_config
{
1700 my ($filename, $conf) = @_;
1702 delete $conf->{snapstate
}; # just to be sure
1704 if ($conf->{cdrom
}) {
1705 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1706 $conf->{ide2
} = $conf->{cdrom
};
1707 delete $conf->{cdrom
};
1710 # we do not use 'smp' any longer
1711 if ($conf->{sockets
}) {
1712 delete $conf->{smp
};
1713 } elsif ($conf->{smp
}) {
1714 $conf->{sockets
} = $conf->{smp
};
1715 delete $conf->{cores
};
1716 delete $conf->{smp
};
1719 my $used_volids = {};
1721 my $cleanup_config = sub {
1722 my ($cref, $snapname) = @_;
1724 foreach my $key (keys %$cref) {
1725 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1726 $key eq 'snapstate';
1727 my $value = $cref->{$key};
1728 eval { $value = check_type
($key, $value); };
1729 die "unable to parse value of '$key' - $@" if $@;
1731 $cref->{$key} = $value;
1733 if (!$snapname && valid_drivename
($key)) {
1734 my $drive = parse_drive
($key, $value);
1735 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1740 &$cleanup_config($conf);
1741 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1742 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1745 # remove 'unusedX' settings if we re-add a volume
1746 foreach my $key (keys %$conf) {
1747 my $value = $conf->{$key};
1748 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1749 delete $conf->{$key};
1753 my $generate_raw_config = sub {
1758 # add description as comment to top of file
1759 my $descr = $conf->{description
} || '';
1760 foreach my $cl (split(/\n/, $descr)) {
1761 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1764 foreach my $key (sort keys %$conf) {
1765 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1766 $raw .= "$key: $conf->{$key}\n";
1771 my $raw = &$generate_raw_config($conf);
1772 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1773 $raw .= "\n[$snapname]\n";
1774 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1780 sub update_config_nolock
{
1781 my ($vmid, $conf, $skiplock) = @_;
1783 check_lock
($conf) if !$skiplock;
1785 my $cfspath = cfs_config_path
($vmid);
1787 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1791 my ($vmid, $conf, $skiplock) = @_;
1793 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1800 # we use static defaults from our JSON schema configuration
1801 foreach my $key (keys %$confdesc) {
1802 if (defined(my $default = $confdesc->{$key}->{default})) {
1803 $res->{$key} = $default;
1807 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1808 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1814 my $vmlist = PVE
::Cluster
::get_vmlist
();
1816 return $res if !$vmlist || !$vmlist->{ids
};
1817 my $ids = $vmlist->{ids
};
1819 foreach my $vmid (keys %$ids) {
1820 my $d = $ids->{$vmid};
1821 next if !$d->{node
} || $d->{node
} ne $nodename;
1822 next if !$d->{type
} || $d->{type
} ne 'qemu';
1823 $res->{$vmid}->{exists} = 1;
1828 # test if VM uses local resources (to prevent migration)
1829 sub check_local_resources
{
1830 my ($conf, $noerr) = @_;
1834 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1835 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1837 foreach my $k (keys %$conf) {
1838 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1839 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1842 die "VM uses local resources\n" if $loc_res && !$noerr;
1847 # check if used storages are available on all nodes (use by migrate)
1848 sub check_storage_availability
{
1849 my ($storecfg, $conf, $node) = @_;
1851 foreach_drive
($conf, sub {
1852 my ($ds, $drive) = @_;
1854 my $volid = $drive->{file
};
1857 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1860 # check if storage is available on both nodes
1861 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1862 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1866 # list nodes where all VM images are available (used by has_feature API)
1868 my ($conf, $storecfg) = @_;
1870 my $nodelist = PVE
::Cluster
::get_nodelist
();
1871 my $nodehash = { map { $_ => 1 } @$nodelist };
1872 my $nodename = PVE
::INotify
::nodename
();
1874 foreach_drive
($conf, sub {
1875 my ($ds, $drive) = @_;
1877 my $volid = $drive->{file
};
1880 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1882 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1883 if ($scfg->{disable
}) {
1885 } elsif (my $avail = $scfg->{nodes
}) {
1886 foreach my $node (keys %$nodehash) {
1887 delete $nodehash->{$node} if !$avail->{$node};
1889 } elsif (!$scfg->{shared
}) {
1890 foreach my $node (keys %$nodehash) {
1891 delete $nodehash->{$node} if $node ne $nodename
1903 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1907 my ($pidfile, $pid) = @_;
1909 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1913 return undef if !$line;
1914 my @param = split(/\0/, $line);
1916 my $cmd = $param[0];
1917 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1919 for (my $i = 0; $i < scalar (@param); $i++) {
1922 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1923 my $p = $param[$i+1];
1924 return 1 if $p && ($p eq $pidfile);
1933 my ($vmid, $nocheck, $node) = @_;
1935 my $filename = config_file
($vmid, $node);
1937 die "unable to find configuration file for VM $vmid - no such machine\n"
1938 if !$nocheck && ! -f
$filename;
1940 my $pidfile = pidfile_name
($vmid);
1942 if (my $fd = IO
::File-
>new("<$pidfile")) {
1947 my $mtime = $st->mtime;
1948 if ($mtime > time()) {
1949 warn "file '$filename' modified in future\n";
1952 if ($line =~ m/^(\d+)$/) {
1954 if (check_cmdline
($pidfile, $pid)) {
1955 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1967 my $vzlist = config_list
();
1969 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1971 while (defined(my $de = $fd->read)) {
1972 next if $de !~ m/^(\d+)\.pid$/;
1974 next if !defined($vzlist->{$vmid});
1975 if (my $pid = check_running
($vmid)) {
1976 $vzlist->{$vmid}->{pid
} = $pid;
1984 my ($storecfg, $conf) = @_;
1986 my $bootdisk = $conf->{bootdisk
};
1987 return undef if !$bootdisk;
1988 return undef if !valid_drivename
($bootdisk);
1990 return undef if !$conf->{$bootdisk};
1992 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1993 return undef if !defined($drive);
1995 return undef if drive_is_cdrom
($drive);
1997 my $volid = $drive->{file
};
1998 return undef if !$volid;
2000 return $drive->{size
};
2003 my $last_proc_pid_stat;
2005 # get VM status information
2006 # This must be fast and should not block ($full == false)
2007 # We only query KVM using QMP if $full == true (this can be slow)
2009 my ($opt_vmid, $full) = @_;
2013 my $storecfg = PVE
::Storage
::config
();
2015 my $list = vzlist
();
2016 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2018 my $cpucount = $cpuinfo->{cpus
} || 1;
2020 foreach my $vmid (keys %$list) {
2021 next if $opt_vmid && ($vmid ne $opt_vmid);
2023 my $cfspath = cfs_config_path
($vmid);
2024 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2027 $d->{pid
} = $list->{$vmid}->{pid
};
2029 # fixme: better status?
2030 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2032 my $size = disksize
($storecfg, $conf);
2033 if (defined($size)) {
2034 $d->{disk
} = 0; # no info available
2035 $d->{maxdisk
} = $size;
2041 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2042 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2044 $d->{name
} = $conf->{name
} || "VM $vmid";
2045 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2047 if ($conf->{balloon
}) {
2048 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2049 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2060 $d->{diskwrite
} = 0;
2062 $d->{template
} = is_template
($conf);
2067 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2068 foreach my $dev (keys %$netdev) {
2069 next if $dev !~ m/^tap([1-9]\d*)i/;
2071 my $d = $res->{$vmid};
2074 $d->{netout
} += $netdev->{$dev}->{receive
};
2075 $d->{netin
} += $netdev->{$dev}->{transmit
};
2078 my $ctime = gettimeofday
;
2080 foreach my $vmid (keys %$list) {
2082 my $d = $res->{$vmid};
2083 my $pid = $d->{pid
};
2086 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2087 next if !$pstat; # not running
2089 my $used = $pstat->{utime} + $pstat->{stime
};
2091 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2093 if ($pstat->{vsize
}) {
2094 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2097 my $old = $last_proc_pid_stat->{$pid};
2099 $last_proc_pid_stat->{$pid} = {
2107 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2109 if ($dtime > 1000) {
2110 my $dutime = $used - $old->{used
};
2112 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2113 $last_proc_pid_stat->{$pid} = {
2119 $d->{cpu
} = $old->{cpu
};
2123 return $res if !$full;
2125 my $qmpclient = PVE
::QMPClient-
>new();
2127 my $ballooncb = sub {
2128 my ($vmid, $resp) = @_;
2130 my $info = $resp->{'return'};
2131 return if !$info->{max_mem
};
2133 my $d = $res->{$vmid};
2135 # use memory assigned to VM
2136 $d->{maxmem
} = $info->{max_mem
};
2137 $d->{balloon
} = $info->{actual
};
2139 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2140 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2141 $d->{freemem
} = $info->{free_mem
};
2146 my $blockstatscb = sub {
2147 my ($vmid, $resp) = @_;
2148 my $data = $resp->{'return'} || [];
2149 my $totalrdbytes = 0;
2150 my $totalwrbytes = 0;
2151 for my $blockstat (@$data) {
2152 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2153 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2155 $res->{$vmid}->{diskread
} = $totalrdbytes;
2156 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2159 my $statuscb = sub {
2160 my ($vmid, $resp) = @_;
2162 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2163 # this fails if ballon driver is not loaded, so this must be
2164 # the last commnand (following command are aborted if this fails).
2165 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2167 my $status = 'unknown';
2168 if (!defined($status = $resp->{'return'}->{status
})) {
2169 warn "unable to get VM status\n";
2173 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2176 foreach my $vmid (keys %$list) {
2177 next if $opt_vmid && ($vmid ne $opt_vmid);
2178 next if !$res->{$vmid}->{pid
}; # not running
2179 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2182 $qmpclient->queue_execute();
2184 foreach my $vmid (keys %$list) {
2185 next if $opt_vmid && ($vmid ne $opt_vmid);
2186 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2193 my ($conf, $func) = @_;
2195 foreach my $ds (keys %$conf) {
2196 next if !valid_drivename
($ds);
2198 my $drive = parse_drive
($ds, $conf->{$ds});
2201 &$func($ds, $drive);
2206 my ($conf, $func) = @_;
2210 my $test_volid = sub {
2211 my ($volid, $is_cdrom) = @_;
2215 $volhash->{$volid} = $is_cdrom || 0;
2218 foreach_drive
($conf, sub {
2219 my ($ds, $drive) = @_;
2220 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2223 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2224 my $snap = $conf->{snapshots
}->{$snapname};
2225 &$test_volid($snap->{vmstate
}, 0);
2226 foreach_drive
($snap, sub {
2227 my ($ds, $drive) = @_;
2228 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2232 foreach my $volid (keys %$volhash) {
2233 &$func($volid, $volhash->{$volid});
2237 sub vga_conf_has_spice
{
2240 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2245 sub config_to_command
{
2246 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2249 my $globalFlags = [];
2250 my $machineFlags = [];
2256 my $kvmver = kvm_user_version
();
2257 my $vernum = 0; # unknown
2258 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2259 $vernum = $1*1000000+$2*1000;
2260 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2261 $vernum = $1*1000000+$2*1000+$3;
2264 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2266 my $have_ovz = -f
'/proc/vz/vestat';
2268 push @$cmd, '/usr/bin/kvm';
2270 push @$cmd, '-id', $vmid;
2274 my $qmpsocket = qmp_socket
($vmid);
2275 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2276 push @$cmd, '-mon', "chardev=qmp,mode=control";
2278 my $socket = vnc_socket
($vmid);
2279 push @$cmd, '-vnc', "unix:$socket,x509,password";
2281 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2283 push @$cmd, '-daemonize';
2285 $pciaddr = print_pci_addr
("piix3", $bridges);
2286 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2289 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2290 next if !$conf->{"usb$i"};
2293 # include usb device config
2294 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2296 my $vga = $conf->{vga
};
2298 my $qxlnum = vga_conf_has_spice
($vga);
2299 $vga = 'qxl' if $qxlnum;
2302 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2303 $conf->{ostype
} eq 'win7' ||
2304 $conf->{ostype
} eq 'w2k8')) {
2311 # enable absolute mouse coordinates (needed by vnc)
2313 if (defined($conf->{tablet
})) {
2314 $tablet = $conf->{tablet
};
2316 $tablet = $defaults->{tablet
};
2317 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2318 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2321 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2324 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2325 my $d = parse_hostpci
($conf->{"hostpci$i"});
2327 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2328 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2332 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2333 my $d = parse_usb_device
($conf->{"usb$i"});
2335 if ($d->{vendorid
} && $d->{productid
}) {
2336 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2337 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2338 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2339 } elsif ($d->{spice
}) {
2340 # usb redir support for spice
2341 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2342 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2347 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2348 if (my $path = $conf->{"serial$i"}) {
2349 if ($path eq 'socket') {
2350 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2351 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2352 push @$devices, '-device', "isa-serial,chardev=serial$i";
2354 die "no such serial device\n" if ! -c
$path;
2355 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2356 push @$devices, '-device', "isa-serial,chardev=serial$i";
2362 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2363 if (my $path = $conf->{"parallel$i"}) {
2364 die "no such parallel device\n" if ! -c
$path;
2365 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2366 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2367 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2371 my $vmname = $conf->{name
} || "vm$vmid";
2373 push @$cmd, '-name', $vmname;
2376 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2377 $sockets = $conf->{sockets
} if $conf->{sockets
};
2379 my $cores = $conf->{cores
} || 1;
2380 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2382 push @$cmd, '-nodefaults';
2384 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2386 my $bootindex_hash = {};
2388 foreach my $o (split(//, $bootorder)) {
2389 $bootindex_hash->{$o} = $i*100;
2393 push @$cmd, '-boot', "menu=on";
2395 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2397 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2399 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2402 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2404 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2405 my $useLocaltime = $conf->{localtime};
2407 if (my $ost = $conf->{ostype
}) {
2408 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2410 if ($ost =~ m/^w/) { # windows
2411 $useLocaltime = 1 if !defined($conf->{localtime});
2413 # use time drift fix when acpi is enabled
2414 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2415 $tdf = 1 if !defined($conf->{tdf
});
2419 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2421 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2422 push @$cmd, '-no-hpet';
2423 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2424 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2427 if ($ost eq 'win7' || $ost eq 'win8') {
2428 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2432 push @$rtcFlags, 'driftfix=slew' if $tdf;
2435 push @$machineFlags, 'accel=tcg';
2437 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2440 my $machine_type = $forcemachine || $conf->{machine
};
2441 if ($machine_type) {
2442 push @$machineFlags, "type=${machine_type}";
2445 if ($conf->{startdate
}) {
2446 push @$rtcFlags, "base=$conf->{startdate}";
2447 } elsif ($useLocaltime) {
2448 push @$rtcFlags, 'base=localtime';
2451 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2452 $cpu = $conf->{cpu
} if $conf->{cpu
};
2454 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2456 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2458 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2460 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2462 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2464 push @$cmd, '-cpu', $cpu;
2466 push @$cmd, '-S' if $conf->{freeze
};
2468 # set keyboard layout
2469 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2470 push @$cmd, '-k', $kb if $kb;
2473 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2474 #push @$cmd, '-soundhw', 'es1370';
2475 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2477 if($conf->{agent
}) {
2478 my $qgasocket = qga_socket
($vmid);
2479 my $pciaddr = print_pci_addr
("qga0", $bridges);
2480 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2481 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2482 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2489 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2490 for(my $i = 1; $i < $qxlnum; $i++){
2491 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2492 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2495 # assume other OS works like Linux
2496 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2497 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2501 my $pciaddr = print_pci_addr
("spice", $bridges);
2503 $spice_port = PVE
::Tools
::next_unused_port
(61000, 61099);
2505 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2507 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2508 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2509 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2512 # enable balloon by default, unless explicitly disabled
2513 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2514 $pciaddr = print_pci_addr
("balloon0", $bridges);
2515 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2518 if ($conf->{watchdog
}) {
2519 my $wdopts = parse_watchdog
($conf->{watchdog
});
2520 $pciaddr = print_pci_addr
("watchdog", $bridges);
2521 my $watchdog = $wdopts->{model
} || 'i6300esb';
2522 push @$devices, '-device', "$watchdog$pciaddr";
2523 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2527 my $scsicontroller = {};
2528 my $ahcicontroller = {};
2529 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2531 foreach_drive
($conf, sub {
2532 my ($ds, $drive) = @_;
2534 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2535 push @$vollist, $drive->{file
};
2538 $use_virtio = 1 if $ds =~ m/^virtio/;
2540 if (drive_is_cdrom
($drive)) {
2541 if ($bootindex_hash->{d
}) {
2542 $drive->{bootindex
} = $bootindex_hash->{d
};
2543 $bootindex_hash->{d
} += 1;
2546 if ($bootindex_hash->{c
}) {
2547 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2548 $bootindex_hash->{c
} += 1;
2552 if ($drive->{interface
} eq 'scsi') {
2554 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2555 my $controller = int($drive->{index} / $maxdev);
2556 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2557 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2558 $scsicontroller->{$controller}=1;
2561 if ($drive->{interface
} eq 'sata') {
2562 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2563 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2564 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2565 $ahcicontroller->{$controller}=1;
2568 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2569 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2572 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2574 for (my $i = 0; $i < $MAX_NETS; $i++) {
2575 next if !$conf->{"net$i"};
2576 my $d = parse_net
($conf->{"net$i"});
2579 $use_virtio = 1 if $d->{model
} eq 'virtio';
2581 if ($bootindex_hash->{n
}) {
2582 $d->{bootindex
} = $bootindex_hash->{n
};
2583 $bootindex_hash->{n
} += 1;
2586 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2587 push @$devices, '-netdev', $netdevfull;
2589 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2590 push @$devices, '-device', $netdevicefull;
2594 while (my ($k, $v) = each %$bridges) {
2595 $pciaddr = print_pci_addr
("pci.$k");
2596 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2600 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2601 # when the VM uses virtio devices.
2602 if (!$use_virtio && $have_ovz) {
2604 my $cpuunits = defined($conf->{cpuunits
}) ?
2605 $conf->{cpuunits
} : $defaults->{cpuunits
};
2607 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2609 # fixme: cpulimit is currently ignored
2610 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2614 if ($conf->{args
}) {
2615 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2619 push @$cmd, @$devices;
2620 push @$cmd, '-rtc', join(',', @$rtcFlags)
2621 if scalar(@$rtcFlags);
2622 push @$cmd, '-machine', join(',', @$machineFlags)
2623 if scalar(@$machineFlags);
2624 push @$cmd, '-global', join(',', @$globalFlags)
2625 if scalar(@$globalFlags);
2627 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2632 return "${var_run_tmpdir}/$vmid.vnc";
2638 my $res = vm_mon_cmd
($vmid, 'query-spice');
2640 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2645 return "${var_run_tmpdir}/$vmid.qmp";
2650 return "${var_run_tmpdir}/$vmid.qga";
2655 return "${var_run_tmpdir}/$vmid.pid";
2658 sub vm_devices_list
{
2661 my $res = vm_mon_cmd
($vmid, 'query-pci');
2664 foreach my $pcibus (@$res) {
2665 foreach my $device (@{$pcibus->{devices
}}) {
2666 next if !$device->{'qdev_id'};
2667 $devices->{$device->{'qdev_id'}} = $device;
2675 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2677 return 1 if !check_running
($vmid);
2679 if ($deviceid eq 'tablet') {
2680 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2681 qemu_deviceadd
($vmid, $devicefull);
2685 return 1 if !$conf->{hotplug
};
2687 my $devices_list = vm_devices_list
($vmid);
2688 return 1 if defined($devices_list->{$deviceid});
2690 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2692 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2693 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2694 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2695 qemu_deviceadd
($vmid, $devicefull);
2696 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2697 qemu_drivedel
($vmid, $deviceid);
2702 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2703 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2704 my $pciaddr = print_pci_addr
($deviceid);
2705 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2706 qemu_deviceadd
($vmid, $devicefull);
2707 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2710 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2711 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2712 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2713 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2714 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2715 if(!qemu_deviceadd
($vmid, $devicefull)) {
2716 qemu_drivedel
($vmid, $deviceid);
2721 if ($deviceid =~ m/^(net)(\d+)$/) {
2722 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2723 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2724 qemu_deviceadd
($vmid, $netdevicefull);
2725 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2726 qemu_netdevdel
($vmid, $deviceid);
2731 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2733 my $pciaddr = print_pci_addr
($deviceid);
2734 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2735 qemu_deviceadd
($vmid, $devicefull);
2736 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2742 sub vm_deviceunplug
{
2743 my ($vmid, $conf, $deviceid) = @_;
2745 return 1 if !check_running
($vmid);
2747 if ($deviceid eq 'tablet') {
2748 qemu_devicedel
($vmid, $deviceid);
2752 return 1 if !$conf->{hotplug
};
2754 my $devices_list = vm_devices_list
($vmid);
2755 return 1 if !defined($devices_list->{$deviceid});
2757 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2759 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2760 qemu_devicedel
($vmid, $deviceid);
2761 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2762 return undef if !qemu_drivedel
($vmid, $deviceid);
2765 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2766 return undef if !qemu_devicedel
($vmid, $deviceid);
2769 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2770 return undef if !qemu_devicedel
($vmid, $deviceid);
2771 return undef if !qemu_drivedel
($vmid, $deviceid);
2774 if ($deviceid =~ m/^(net)(\d+)$/) {
2775 qemu_devicedel
($vmid, $deviceid);
2776 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2777 return undef if !qemu_netdevdel
($vmid, $deviceid);
2783 sub qemu_deviceadd
{
2784 my ($vmid, $devicefull) = @_;
2786 $devicefull = "driver=".$devicefull;
2787 my %options = split(/[=,]/, $devicefull);
2789 vm_mon_cmd
($vmid, "device_add" , %options);
2793 sub qemu_devicedel
{
2794 my($vmid, $deviceid) = @_;
2795 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2800 my($storecfg, $vmid, $device) = @_;
2802 my $drive = print_drive_full
($storecfg, $vmid, $device);
2803 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2804 # If the command succeeds qemu prints: "OK"
2805 if ($ret !~ m/OK/s) {
2806 syslog
("err", "adding drive failed: $ret");
2813 my($vmid, $deviceid) = @_;
2815 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2817 if ($ret =~ m/Device \'.*?\' not found/s) {
2818 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2820 elsif ($ret ne "") {
2821 syslog
("err", "deleting drive $deviceid failed : $ret");
2827 sub qemu_deviceaddverify
{
2828 my ($vmid,$deviceid) = @_;
2830 for (my $i = 0; $i <= 5; $i++) {
2831 my $devices_list = vm_devices_list
($vmid);
2832 return 1 if defined($devices_list->{$deviceid});
2835 syslog
("err", "error on hotplug device $deviceid");
2840 sub qemu_devicedelverify
{
2841 my ($vmid,$deviceid) = @_;
2843 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2844 for (my $i = 0; $i <= 5; $i++) {
2845 my $devices_list = vm_devices_list
($vmid);
2846 return 1 if !defined($devices_list->{$deviceid});
2849 syslog
("err", "error on hot-unplugging device $deviceid");
2853 sub qemu_findorcreatescsihw
{
2854 my ($storecfg, $conf, $vmid, $device) = @_;
2856 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2857 my $controller = int($device->{index} / $maxdev);
2858 my $scsihwid="scsihw$controller";
2859 my $devices_list = vm_devices_list
($vmid);
2861 if(!defined($devices_list->{$scsihwid})) {
2862 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2867 sub qemu_bridgeadd
{
2868 my ($storecfg, $conf, $vmid, $device) = @_;
2871 my $bridgeid = undef;
2872 print_pci_addr
($device, $bridges);
2874 while (my ($k, $v) = each %$bridges) {
2877 return if !$bridgeid || $bridgeid < 1;
2878 my $bridge = "pci.$bridgeid";
2879 my $devices_list = vm_devices_list
($vmid);
2881 if(!defined($devices_list->{$bridge})) {
2882 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2887 sub qemu_netdevadd
{
2888 my ($vmid, $conf, $device, $deviceid) = @_;
2890 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2891 my %options = split(/[=,]/, $netdev);
2893 vm_mon_cmd
($vmid, "netdev_add", %options);
2897 sub qemu_netdevdel
{
2898 my ($vmid, $deviceid) = @_;
2900 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2904 sub qemu_block_set_io_throttle
{
2905 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2907 return if !check_running
($vmid) ;
2909 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));
2913 # old code, only used to shutdown old VM after update
2915 my ($fh, $timeout) = @_;
2917 my $sel = new IO
::Select
;
2924 while (scalar (@ready = $sel->can_read($timeout))) {
2926 if ($count = $fh->sysread($buf, 8192)) {
2927 if ($buf =~ /^(.*)\(qemu\) $/s) {
2934 if (!defined($count)) {
2941 die "monitor read timeout\n" if !scalar(@ready);
2946 # old code, only used to shutdown old VM after update
2947 sub vm_monitor_command
{
2948 my ($vmid, $cmdstr, $nocheck) = @_;
2953 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2955 my $sname = "${var_run_tmpdir}/$vmid.mon";
2957 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2958 die "unable to connect to VM $vmid socket - $!\n";
2962 # hack: migrate sometime blocks the monitor (when migrate_downtime
2964 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2965 $timeout = 60*60; # 1 hour
2969 my $data = __read_avail
($sock, $timeout);
2971 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2972 die "got unexpected qemu monitor banner\n";
2975 my $sel = new IO
::Select
;
2978 if (!scalar(my @ready = $sel->can_write($timeout))) {
2979 die "monitor write error - timeout";
2982 my $fullcmd = "$cmdstr\r";
2984 # syslog('info', "VM $vmid monitor command: $cmdstr");
2987 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2988 die "monitor write error - $!";
2991 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2995 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2996 $timeout = 60*60; # 1 hour
2997 } elsif ($cmdstr =~ m/^(eject|change)/) {
2998 $timeout = 60; # note: cdrom mount command is slow
3000 if ($res = __read_avail
($sock, $timeout)) {
3002 my @lines = split("\r?\n", $res);
3004 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3006 $res = join("\n", @lines);
3014 syslog
("err", "VM $vmid monitor command failed - $err");
3021 sub qemu_block_resize
{
3022 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3024 my $running = check_running
($vmid);
3026 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3028 return if !$running;
3030 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3034 sub qemu_volume_snapshot
{
3035 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3037 my $running = check_running
($vmid);
3039 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3041 return if !$running;
3043 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3047 sub qemu_volume_snapshot_delete
{
3048 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3050 my $running = check_running
($vmid);
3052 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3054 return if !$running;
3056 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3062 #need to impplement call to qemu-ga
3065 sub qga_unfreezefs
{
3068 #need to impplement call to qemu-ga
3072 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3074 lock_config
($vmid, sub {
3075 my $conf = load_config
($vmid, $migratedfrom);
3077 die "you can't start a vm if it's a template\n" if is_template
($conf);
3079 check_lock
($conf) if !$skiplock;
3081 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3083 my $defaults = load_defaults
();
3085 # set environment variable useful inside network script
3086 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3088 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3090 my $migrate_port = 0;
3093 if ($statefile eq 'tcp') {
3094 my $localip = "localhost";
3095 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3096 if ($datacenterconf->{migration_unsecure
}) {
3097 my $nodename = PVE
::INotify
::nodename
();
3098 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3100 $migrate_port = PVE
::Tools
::next_migrate_port
();
3101 $migrate_uri = "tcp:${localip}:${migrate_port}";
3102 push @$cmd, '-incoming', $migrate_uri;
3105 push @$cmd, '-loadstate', $statefile;
3112 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3113 my $d = parse_hostpci
($conf->{"hostpci$i"});
3115 my $info = pci_device_info
("0000:$d->{pciid}");
3116 die "IOMMU not present\n" if !check_iommu_support
();
3117 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3118 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3119 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3122 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3124 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3127 die "start failed: $err" if $err;
3129 print "migration listens on $migrate_uri\n" if $migrate_uri;
3131 if ($statefile && $statefile ne 'tcp') {
3132 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3136 if ($migratedfrom) {
3137 my $capabilities = {};
3138 $capabilities->{capability
} = "xbzrle";
3139 $capabilities->{state} = JSON
::true
;
3140 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
3144 print "spice listens on port $spice_port\n";
3145 if ($spice_ticket) {
3146 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3147 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3153 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3154 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3155 if $conf->{balloon
};
3156 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3157 path
=> "machine/peripheral/balloon0",
3158 property
=> "guest-stats-polling-interval",
3166 my ($vmid, $execute, %params) = @_;
3168 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3169 vm_qmp_command
($vmid, $cmd);
3172 sub vm_mon_cmd_nocheck
{
3173 my ($vmid, $execute, %params) = @_;
3175 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3176 vm_qmp_command
($vmid, $cmd, 1);
3179 sub vm_qmp_command
{
3180 my ($vmid, $cmd, $nocheck) = @_;
3185 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3186 $timeout = $cmd->{arguments
}->{timeout
};
3187 delete $cmd->{arguments
}->{timeout
};
3191 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3192 my $sname = qmp_socket
($vmid);
3194 my $qmpclient = PVE
::QMPClient-
>new();
3196 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3197 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3198 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3199 if scalar(%{$cmd->{arguments
}});
3200 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3202 die "unable to open monitor socket\n";
3206 syslog
("err", "VM $vmid qmp command failed - $err");
3213 sub vm_human_monitor_command
{
3214 my ($vmid, $cmdline) = @_;
3219 execute
=> 'human-monitor-command',
3220 arguments
=> { 'command-line' => $cmdline},
3223 return vm_qmp_command
($vmid, $cmd);
3226 sub vm_commandline
{
3227 my ($storecfg, $vmid) = @_;
3229 my $conf = load_config
($vmid);
3231 my $defaults = load_defaults
();
3233 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3235 return join(' ', @$cmd);
3239 my ($vmid, $skiplock) = @_;
3241 lock_config
($vmid, sub {
3243 my $conf = load_config
($vmid);
3245 check_lock
($conf) if !$skiplock;
3247 vm_mon_cmd
($vmid, "system_reset");
3251 sub get_vm_volumes
{
3255 foreach_volid
($conf, sub {
3256 my ($volid, $is_cdrom) = @_;
3258 return if $volid =~ m
|^/|;
3260 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3263 push @$vollist, $volid;
3269 sub vm_stop_cleanup
{
3270 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3273 fairsched_rmnod
($vmid); # try to destroy group
3276 my $vollist = get_vm_volumes
($conf);
3277 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3280 foreach my $ext (qw(mon qmp pid vnc qga)) {
3281 unlink "/var/run/qemu-server/${vmid}.$ext";
3284 warn $@ if $@; # avoid errors - just warn
3287 # Note: use $nockeck to skip tests if VM configuration file exists.
3288 # We need that when migration VMs to other nodes (files already moved)
3289 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3291 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3293 $force = 1 if !defined($force) && !$shutdown;
3296 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3297 kill 15, $pid if $pid;
3298 my $conf = load_config
($vmid, $migratedfrom);
3299 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3303 lock_config
($vmid, sub {
3305 my $pid = check_running
($vmid, $nocheck);
3310 $conf = load_config
($vmid);
3311 check_lock
($conf) if !$skiplock;
3312 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3313 my $opts = parse_startup
($conf->{startup
});
3314 $timeout = $opts->{down
} if $opts->{down
};
3318 $timeout = 60 if !defined($timeout);
3322 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3325 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3332 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3337 if ($count >= $timeout) {
3339 warn "VM still running - terminating now with SIGTERM\n";
3342 die "VM quit/powerdown failed - got timeout\n";
3345 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3350 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3353 die "VM quit/powerdown failed\n";
3361 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3366 if ($count >= $timeout) {
3367 warn "VM still running - terminating now with SIGKILL\n";
3372 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3377 my ($vmid, $skiplock) = @_;
3379 lock_config
($vmid, sub {
3381 my $conf = load_config
($vmid);
3383 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3385 vm_mon_cmd
($vmid, "stop");
3390 my ($vmid, $skiplock) = @_;
3392 lock_config
($vmid, sub {
3394 my $conf = load_config
($vmid);
3396 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3398 vm_mon_cmd
($vmid, "cont");
3403 my ($vmid, $skiplock, $key) = @_;
3405 lock_config
($vmid, sub {
3407 my $conf = load_config
($vmid);
3409 # there is no qmp command, so we use the human monitor command
3410 vm_human_monitor_command
($vmid, "sendkey $key");
3415 my ($storecfg, $vmid, $skiplock) = @_;
3417 lock_config
($vmid, sub {
3419 my $conf = load_config
($vmid);
3421 check_lock
($conf) if !$skiplock;
3423 if (!check_running
($vmid)) {
3424 fairsched_rmnod
($vmid); # try to destroy group
3425 destroy_vm
($storecfg, $vmid);
3427 die "VM $vmid is running - destroy failed\n";
3435 my ($filename, $buf) = @_;
3437 my $fh = IO
::File-
>new($filename, "w");
3438 return undef if !$fh;
3440 my $res = print $fh $buf;
3447 sub pci_device_info
{
3452 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3453 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3455 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3456 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3458 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3459 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3461 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3462 return undef if !defined($product) || $product !~ s/^0x//;
3467 product
=> $product,
3473 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3482 my $name = $dev->{name
};
3484 my $fn = "$pcisysfs/devices/$name/reset";
3486 return file_write
($fn, "1");
3489 sub pci_dev_bind_to_stub
{
3492 my $name = $dev->{name
};
3494 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3495 return 1 if -d
$testdir;
3497 my $data = "$dev->{vendor} $dev->{product}";
3498 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3500 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3501 if (!file_write
($fn, $name)) {
3502 return undef if -f
$fn;
3505 $fn = "$pcisysfs/drivers/pci-stub/bind";
3506 if (! -d
$testdir) {
3507 return undef if !file_write
($fn, $name);
3513 sub print_pci_addr
{
3514 my ($id, $bridges) = @_;
3518 piix3
=> { bus
=> 0, addr
=> 1 },
3519 #addr2 : first videocard
3520 balloon0
=> { bus
=> 0, addr
=> 3 },
3521 watchdog
=> { bus
=> 0, addr
=> 4 },
3522 scsihw0
=> { bus
=> 0, addr
=> 5 },
3523 scsihw1
=> { bus
=> 0, addr
=> 6 },
3524 ahci0
=> { bus
=> 0, addr
=> 7 },
3525 qga0
=> { bus
=> 0, addr
=> 8 },
3526 spice
=> { bus
=> 0, addr
=> 9 },
3527 virtio0
=> { bus
=> 0, addr
=> 10 },
3528 virtio1
=> { bus
=> 0, addr
=> 11 },
3529 virtio2
=> { bus
=> 0, addr
=> 12 },
3530 virtio3
=> { bus
=> 0, addr
=> 13 },
3531 virtio4
=> { bus
=> 0, addr
=> 14 },
3532 virtio5
=> { bus
=> 0, addr
=> 15 },
3533 hostpci0
=> { bus
=> 0, addr
=> 16 },
3534 hostpci1
=> { bus
=> 0, addr
=> 17 },
3535 net0
=> { bus
=> 0, addr
=> 18 },
3536 net1
=> { bus
=> 0, addr
=> 19 },
3537 net2
=> { bus
=> 0, addr
=> 20 },
3538 net3
=> { bus
=> 0, addr
=> 21 },
3539 net4
=> { bus
=> 0, addr
=> 22 },
3540 net5
=> { bus
=> 0, addr
=> 23 },
3541 vga1
=> { bus
=> 0, addr
=> 24 },
3542 vga2
=> { bus
=> 0, addr
=> 25 },
3543 vga3
=> { bus
=> 0, addr
=> 26 },
3544 #addr29 : usb-host (pve-usb.cfg)
3545 'pci.1' => { bus
=> 0, addr
=> 30 },
3546 'pci.2' => { bus
=> 0, addr
=> 31 },
3547 'net6' => { bus
=> 1, addr
=> 1 },
3548 'net7' => { bus
=> 1, addr
=> 2 },
3549 'net8' => { bus
=> 1, addr
=> 3 },
3550 'net9' => { bus
=> 1, addr
=> 4 },
3551 'net10' => { bus
=> 1, addr
=> 5 },
3552 'net11' => { bus
=> 1, addr
=> 6 },
3553 'net12' => { bus
=> 1, addr
=> 7 },
3554 'net13' => { bus
=> 1, addr
=> 8 },
3555 'net14' => { bus
=> 1, addr
=> 9 },
3556 'net15' => { bus
=> 1, addr
=> 10 },
3557 'net16' => { bus
=> 1, addr
=> 11 },
3558 'net17' => { bus
=> 1, addr
=> 12 },
3559 'net18' => { bus
=> 1, addr
=> 13 },
3560 'net19' => { bus
=> 1, addr
=> 14 },
3561 'net20' => { bus
=> 1, addr
=> 15 },
3562 'net21' => { bus
=> 1, addr
=> 16 },
3563 'net22' => { bus
=> 1, addr
=> 17 },
3564 'net23' => { bus
=> 1, addr
=> 18 },
3565 'net24' => { bus
=> 1, addr
=> 19 },
3566 'net25' => { bus
=> 1, addr
=> 20 },
3567 'net26' => { bus
=> 1, addr
=> 21 },
3568 'net27' => { bus
=> 1, addr
=> 22 },
3569 'net28' => { bus
=> 1, addr
=> 23 },
3570 'net29' => { bus
=> 1, addr
=> 24 },
3571 'net30' => { bus
=> 1, addr
=> 25 },
3572 'net31' => { bus
=> 1, addr
=> 26 },
3573 'virtio6' => { bus
=> 2, addr
=> 1 },
3574 'virtio7' => { bus
=> 2, addr
=> 2 },
3575 'virtio8' => { bus
=> 2, addr
=> 3 },
3576 'virtio9' => { bus
=> 2, addr
=> 4 },
3577 'virtio10' => { bus
=> 2, addr
=> 5 },
3578 'virtio11' => { bus
=> 2, addr
=> 6 },
3579 'virtio12' => { bus
=> 2, addr
=> 7 },
3580 'virtio13' => { bus
=> 2, addr
=> 8 },
3581 'virtio14' => { bus
=> 2, addr
=> 9 },
3582 'virtio15' => { bus
=> 2, addr
=> 10 },
3585 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3586 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3587 my $bus = $devices->{$id}->{bus
};
3588 $res = ",bus=pci.$bus,addr=$addr";
3589 $bridges->{$bus} = 1 if $bridges;
3595 # vzdump restore implementaion
3597 sub tar_archive_read_firstfile
{
3598 my $archive = shift;
3600 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3602 # try to detect archive type first
3603 my $pid = open (TMP
, "tar tf '$archive'|") ||
3604 die "unable to open file '$archive'\n";
3605 my $firstfile = <TMP
>;
3609 die "ERROR: archive contaions no data\n" if !$firstfile;
3615 sub tar_restore_cleanup
{
3616 my ($storecfg, $statfile) = @_;
3618 print STDERR
"starting cleanup\n";
3620 if (my $fd = IO
::File-
>new($statfile, "r")) {
3621 while (defined(my $line = <$fd>)) {
3622 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3625 if ($volid =~ m
|^/|) {
3626 unlink $volid || die 'unlink failed\n';
3628 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3630 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3632 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3634 print STDERR
"unable to parse line in statfile - $line";
3641 sub restore_archive
{
3642 my ($archive, $vmid, $user, $opts) = @_;
3644 my $format = $opts->{format
};
3647 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3648 $format = 'tar' if !$format;
3650 } elsif ($archive =~ m/\.tar$/) {
3651 $format = 'tar' if !$format;
3652 } elsif ($archive =~ m/.tar.lzo$/) {
3653 $format = 'tar' if !$format;
3655 } elsif ($archive =~ m/\.vma$/) {
3656 $format = 'vma' if !$format;
3657 } elsif ($archive =~ m/\.vma\.gz$/) {
3658 $format = 'vma' if !$format;
3660 } elsif ($archive =~ m/\.vma\.lzo$/) {
3661 $format = 'vma' if !$format;
3664 $format = 'vma' if !$format; # default
3667 # try to detect archive format
3668 if ($format eq 'tar') {
3669 return restore_tar_archive
($archive, $vmid, $user, $opts);
3671 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3675 sub restore_update_config_line
{
3676 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3678 return if $line =~ m/^\#qmdump\#/;
3679 return if $line =~ m/^\#vzdump\#/;
3680 return if $line =~ m/^lock:/;
3681 return if $line =~ m/^unused\d+:/;
3682 return if $line =~ m/^parent:/;
3683 return if $line =~ m/^template:/; # restored VM is never a template
3685 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3686 # try to convert old 1.X settings
3687 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3688 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3689 my ($model, $macaddr) = split(/\=/, $devconfig);
3690 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3693 bridge
=> "vmbr$ind",
3694 macaddr
=> $macaddr,
3696 my $netstr = print_net
($net);
3698 print $outfd "net$cookie->{netcount}: $netstr\n";
3699 $cookie->{netcount
}++;
3701 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3702 my ($id, $netstr) = ($1, $2);
3703 my $net = parse_net
($netstr);
3704 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3705 $netstr = print_net
($net);
3706 print $outfd "$id: $netstr\n";
3707 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3710 if ($line =~ m/backup=no/) {
3711 print $outfd "#$line";
3712 } elsif ($virtdev && $map->{$virtdev}) {
3713 my $di = parse_drive
($virtdev, $value);
3714 delete $di->{format
}; # format can change on restore
3715 $di->{file
} = $map->{$virtdev};
3716 $value = print_drive
($vmid, $di);
3717 print $outfd "$virtdev: $value\n";
3727 my ($cfg, $vmid) = @_;
3729 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3731 my $volid_hash = {};
3732 foreach my $storeid (keys %$info) {
3733 foreach my $item (@{$info->{$storeid}}) {
3734 next if !($item->{volid
} && $item->{size
});
3735 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3736 $volid_hash->{$item->{volid
}} = $item;
3743 sub get_used_paths
{
3744 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3748 my $scan_config = sub {
3749 my ($cref, $snapname) = @_;
3751 foreach my $key (keys %$cref) {
3752 my $value = $cref->{$key};
3753 if (valid_drivename
($key)) {
3754 next if $skip_drive && $key eq $skip_drive;
3755 my $drive = parse_drive
($key, $value);
3756 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3757 if ($drive->{file
} =~ m!^/!) {
3758 $used_path->{$drive->{file
}}++; # = 1;
3760 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3762 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3764 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3765 $used_path->{$path}++; # = 1;
3771 &$scan_config($conf);
3775 if ($scan_snapshots) {
3776 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3777 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3784 sub update_disksize
{
3785 my ($vmid, $conf, $volid_hash) = @_;
3791 # Note: it is allowed to define multiple storages with same path (alias), so
3792 # we need to check both 'volid' and real 'path' (two different volid can point
3793 # to the same path).
3798 foreach my $opt (keys %$conf) {
3799 if (valid_drivename
($opt)) {
3800 my $drive = parse_drive
($opt, $conf->{$opt});
3801 my $volid = $drive->{file
};
3804 $used->{$volid} = 1;
3805 if ($volid_hash->{$volid} &&
3806 (my $path = $volid_hash->{$volid}->{path
})) {
3807 $usedpath->{$path} = 1;
3810 next if drive_is_cdrom
($drive);
3811 next if !$volid_hash->{$volid};
3813 $drive->{size
} = $volid_hash->{$volid}->{size
};
3814 my $new = print_drive
($vmid, $drive);
3815 if ($new ne $conf->{$opt}) {
3817 $conf->{$opt} = $new;
3822 # remove 'unusedX' entry if volume is used
3823 foreach my $opt (keys %$conf) {
3824 next if $opt !~ m/^unused\d+$/;
3825 my $volid = $conf->{$opt};
3826 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3827 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3829 delete $conf->{$opt};
3833 foreach my $volid (sort keys %$volid_hash) {
3834 next if $volid =~ m/vm-$vmid-state-/;
3835 next if $used->{$volid};
3836 my $path = $volid_hash->{$volid}->{path
};
3837 next if !$path; # just to be sure
3838 next if $usedpath->{$path};
3840 add_unused_volume
($conf, $volid);
3841 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3848 my ($vmid, $nolock) = @_;
3850 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3852 my $volid_hash = scan_volids
($cfg, $vmid);
3854 my $updatefn = sub {
3857 my $conf = load_config
($vmid);
3862 foreach my $volid (keys %$volid_hash) {
3863 my $info = $volid_hash->{$volid};
3864 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3867 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3869 update_config_nolock
($vmid, $conf, 1) if $changes;
3872 if (defined($vmid)) {
3876 lock_config
($vmid, $updatefn, $vmid);
3879 my $vmlist = config_list
();
3880 foreach my $vmid (keys %$vmlist) {
3884 lock_config
($vmid, $updatefn, $vmid);
3890 sub restore_vma_archive
{
3891 my ($archive, $vmid, $user, $opts, $comp) = @_;
3893 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3894 my $readfrom = $archive;
3899 my $qarchive = PVE
::Tools
::shellquote
($archive);
3900 if ($comp eq 'gzip') {
3901 $uncomp = "zcat $qarchive|";
3902 } elsif ($comp eq 'lzop') {
3903 $uncomp = "lzop -d -c $qarchive|";
3905 die "unknown compression method '$comp'\n";
3910 my $tmpdir = "/var/tmp/vzdumptmp$$";
3913 # disable interrupts (always do cleanups)
3914 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3915 warn "got interrupt - ignored\n";
3918 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3919 POSIX
::mkfifo
($mapfifo, 0600);
3922 my $openfifo = sub {
3923 open($fifofh, '>', $mapfifo) || die $!;
3926 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3933 my $rpcenv = PVE
::RPCEnvironment
::get
();
3935 my $conffile = config_file
($vmid);
3936 my $tmpfn = "$conffile.$$.tmp";
3938 # Note: $oldconf is undef if VM does not exists
3939 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3941 my $print_devmap = sub {
3942 my $virtdev_hash = {};
3944 my $cfgfn = "$tmpdir/qemu-server.conf";
3946 # we can read the config - that is already extracted
3947 my $fh = IO
::File-
>new($cfgfn, "r") ||
3948 "unable to read qemu-server.conf - $!\n";
3950 while (defined(my $line = <$fh>)) {
3951 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3952 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3953 die "archive does not contain data for drive '$virtdev'\n"
3954 if !$devinfo->{$devname};
3955 if (defined($opts->{storage
})) {
3956 $storeid = $opts->{storage
} || 'local';
3957 } elsif (!$storeid) {
3960 $format = 'raw' if !$format;
3961 $devinfo->{$devname}->{devname
} = $devname;
3962 $devinfo->{$devname}->{virtdev
} = $virtdev;
3963 $devinfo->{$devname}->{format
} = $format;
3964 $devinfo->{$devname}->{storeid
} = $storeid;
3966 # check permission on storage
3967 my $pool = $opts->{pool
}; # todo: do we need that?
3968 if ($user ne 'root@pam') {
3969 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3972 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3976 foreach my $devname (keys %$devinfo) {
3977 die "found no device mapping information for device '$devname'\n"
3978 if !$devinfo->{$devname}->{virtdev
};
3981 my $cfg = cfs_read_file
('storage.cfg');
3983 # create empty/temp config
3985 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3986 foreach_drive
($oldconf, sub {
3987 my ($ds, $drive) = @_;
3989 return if drive_is_cdrom
($drive);
3991 my $volid = $drive->{file
};
3993 return if !$volid || $volid =~ m
|^/|;
3995 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3996 return if !$path || !$owner || ($owner != $vmid);
3998 # Note: only delete disk we want to restore
3999 # other volumes will become unused
4000 if ($virtdev_hash->{$ds}) {
4001 PVE
::Storage
::vdisk_free
($cfg, $volid);
4007 foreach my $virtdev (sort keys %$virtdev_hash) {
4008 my $d = $virtdev_hash->{$virtdev};
4009 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4010 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4012 # test if requested format is supported
4013 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4014 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4015 $d->{format
} = $defFormat if !$supported;
4017 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4018 $d->{format
}, undef, $alloc_size);
4019 print STDERR
"new volume ID is '$volid'\n";
4020 $d->{volid
} = $volid;
4021 my $path = PVE
::Storage
::path
($cfg, $volid);
4023 my $write_zeros = 1;
4024 # fixme: what other storages types initialize volumes with zero?
4025 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4026 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4030 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4032 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4033 $map->{$virtdev} = $volid;
4036 $fh->seek(0, 0) || die "seek failed - $!\n";
4038 my $outfd = new IO
::File
($tmpfn, "w") ||
4039 die "unable to write config for VM $vmid\n";
4041 my $cookie = { netcount
=> 0 };
4042 while (defined(my $line = <$fh>)) {
4043 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4052 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4053 die "interrupted by signal\n";
4055 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4057 $oldtimeout = alarm($timeout);
4064 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4065 my ($dev_id, $size, $devname) = ($1, $2, $3);
4066 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4067 } elsif ($line =~ m/^CTIME: /) {
4069 print $fifofh "done\n";
4070 my $tmp = $oldtimeout || 0;
4071 $oldtimeout = undef;
4077 print "restore vma archive: $cmd\n";
4078 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4082 alarm($oldtimeout) if $oldtimeout;
4090 my $cfg = cfs_read_file
('storage.cfg');
4091 foreach my $devname (keys %$devinfo) {
4092 my $volid = $devinfo->{$devname}->{volid
};
4095 if ($volid =~ m
|^/|) {
4096 unlink $volid || die 'unlink failed\n';
4098 PVE
::Storage
::vdisk_free
($cfg, $volid);
4100 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4102 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4109 rename($tmpfn, $conffile) ||
4110 die "unable to commit configuration file '$conffile'\n";
4112 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4114 eval { rescan
($vmid, 1); };
4118 sub restore_tar_archive
{
4119 my ($archive, $vmid, $user, $opts) = @_;
4121 if ($archive ne '-') {
4122 my $firstfile = tar_archive_read_firstfile
($archive);
4123 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4124 if $firstfile ne 'qemu-server.conf';
4127 my $storecfg = cfs_read_file
('storage.cfg');
4129 # destroy existing data - keep empty config
4130 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4131 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4133 my $tocmd = "/usr/lib/qemu-server/qmextract";
4135 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4136 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4137 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4138 $tocmd .= ' --info' if $opts->{info
};
4140 # tar option "xf" does not autodetect compression when read from STDIN,
4141 # so we pipe to zcat
4142 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4143 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4145 my $tmpdir = "/var/tmp/vzdumptmp$$";
4148 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4149 local $ENV{VZDUMP_VMID
} = $vmid;
4150 local $ENV{VZDUMP_USER
} = $user;
4152 my $conffile = config_file
($vmid);
4153 my $tmpfn = "$conffile.$$.tmp";
4155 # disable interrupts (always do cleanups)
4156 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4157 print STDERR
"got interrupt - ignored\n";
4162 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4163 die "interrupted by signal\n";
4166 if ($archive eq '-') {
4167 print "extracting archive from STDIN\n";
4168 run_command
($cmd, input
=> "<&STDIN");
4170 print "extracting archive '$archive'\n";
4174 return if $opts->{info
};
4178 my $statfile = "$tmpdir/qmrestore.stat";
4179 if (my $fd = IO
::File-
>new($statfile, "r")) {
4180 while (defined (my $line = <$fd>)) {
4181 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4182 $map->{$1} = $2 if $1;
4184 print STDERR
"unable to parse line in statfile - $line\n";
4190 my $confsrc = "$tmpdir/qemu-server.conf";
4192 my $srcfd = new IO
::File
($confsrc, "r") ||
4193 die "unable to open file '$confsrc'\n";
4195 my $outfd = new IO
::File
($tmpfn, "w") ||
4196 die "unable to write config for VM $vmid\n";
4198 my $cookie = { netcount
=> 0 };
4199 while (defined (my $line = <$srcfd>)) {
4200 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4212 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4219 rename $tmpfn, $conffile ||
4220 die "unable to commit configuration file '$conffile'\n";
4222 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4224 eval { rescan
($vmid, 1); };
4229 # Internal snapshots
4231 # NOTE: Snapshot create/delete involves several non-atomic
4232 # action, and can take a long time.
4233 # So we try to avoid locking the file and use 'lock' variable
4234 # inside the config file instead.
4236 my $snapshot_copy_config = sub {
4237 my ($source, $dest) = @_;
4239 foreach my $k (keys %$source) {
4240 next if $k eq 'snapshots';
4241 next if $k eq 'snapstate';
4242 next if $k eq 'snaptime';
4243 next if $k eq 'vmstate';
4244 next if $k eq 'lock';
4245 next if $k eq 'digest';
4246 next if $k eq 'description';
4247 next if $k =~ m/^unused\d+$/;
4249 $dest->{$k} = $source->{$k};
4253 my $snapshot_apply_config = sub {
4254 my ($conf, $snap) = @_;
4256 # copy snapshot list
4258 snapshots
=> $conf->{snapshots
},
4261 # keep description and list of unused disks
4262 foreach my $k (keys %$conf) {
4263 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4264 $newconf->{$k} = $conf->{$k};
4267 &$snapshot_copy_config($snap, $newconf);
4272 sub foreach_writable_storage
{
4273 my ($conf, $func) = @_;
4277 foreach my $ds (keys %$conf) {
4278 next if !valid_drivename
($ds);
4280 my $drive = parse_drive
($ds, $conf->{$ds});
4282 next if drive_is_cdrom
($drive);
4284 my $volid = $drive->{file
};
4286 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4287 $sidhash->{$sid} = $sid if $sid;
4290 foreach my $sid (sort keys %$sidhash) {
4295 my $alloc_vmstate_volid = sub {
4296 my ($storecfg, $vmid, $conf, $snapname) = @_;
4298 # Note: we try to be smart when selecting a $target storage
4302 # search shared storage first
4303 foreach_writable_storage
($conf, sub {
4305 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4306 return if !$scfg->{shared
};
4308 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4312 # now search local storage
4313 foreach_writable_storage
($conf, sub {
4315 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4316 return if $scfg->{shared
};
4318 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4322 $target = 'local' if !$target;
4324 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4325 # we abort live save after $conf->{memory}, so we need at max twice that space
4326 my $size = $conf->{memory
}*2 + $driver_state_size;
4328 my $name = "vm-$vmid-state-$snapname";
4329 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4330 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4331 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4336 my $snapshot_prepare = sub {
4337 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4341 my $updatefn = sub {
4343 my $conf = load_config
($vmid);
4345 die "you can't take a snapshot if it's a template\n"
4346 if is_template
($conf);
4350 $conf->{lock} = 'snapshot';
4352 die "snapshot name '$snapname' already used\n"
4353 if defined($conf->{snapshots
}->{$snapname});
4355 my $storecfg = PVE
::Storage
::config
();
4356 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4358 $snap = $conf->{snapshots
}->{$snapname} = {};
4360 if ($save_vmstate && check_running
($vmid)) {
4361 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4364 &$snapshot_copy_config($conf, $snap);
4366 $snap->{snapstate
} = "prepare";
4367 $snap->{snaptime
} = time();
4368 $snap->{description
} = $comment if $comment;
4370 # always overwrite machine if we save vmstate. This makes sure we
4371 # can restore it later using correct machine type
4372 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4374 update_config_nolock
($vmid, $conf, 1);
4377 lock_config
($vmid, $updatefn);
4382 my $snapshot_commit = sub {
4383 my ($vmid, $snapname) = @_;
4385 my $updatefn = sub {
4387 my $conf = load_config
($vmid);
4389 die "missing snapshot lock\n"
4390 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4392 my $snap = $conf->{snapshots
}->{$snapname};
4394 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4396 die "wrong snapshot state\n"
4397 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4399 delete $snap->{snapstate
};
4400 delete $conf->{lock};
4402 my $newconf = &$snapshot_apply_config($conf, $snap);
4404 $newconf->{parent
} = $snapname;
4406 update_config_nolock
($vmid, $newconf, 1);
4409 lock_config
($vmid, $updatefn);
4412 sub snapshot_rollback
{
4413 my ($vmid, $snapname) = @_;
4419 my $storecfg = PVE
::Storage
::config
();
4421 my $updatefn = sub {
4423 my $conf = load_config
($vmid);
4425 die "you can't rollback if vm is a template\n" if is_template
($conf);
4427 $snap = $conf->{snapshots
}->{$snapname};
4429 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4431 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4432 if $snap->{snapstate
};
4436 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4439 die "unable to rollback vm $vmid: vm is running\n"
4440 if check_running
($vmid);
4443 $conf->{lock} = 'rollback';
4445 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4446 delete $conf->{lock};
4452 my $has_machine_config = defined($conf->{machine
});
4454 # copy snapshot config to current config
4455 $conf = &$snapshot_apply_config($conf, $snap);
4456 $conf->{parent
} = $snapname;
4458 # Note: old code did not store 'machine', so we try to be smart
4459 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4460 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4461 # we remove the 'machine' configuration if not explicitly specified
4462 # in the original config.
4463 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4466 update_config_nolock
($vmid, $conf, 1);
4468 if (!$prepare && $snap->{vmstate
}) {
4469 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4470 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4474 lock_config
($vmid, $updatefn);
4476 foreach_drive
($snap, sub {
4477 my ($ds, $drive) = @_;
4479 return if drive_is_cdrom
($drive);
4481 my $volid = $drive->{file
};
4482 my $device = "drive-$ds";
4484 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4488 lock_config
($vmid, $updatefn);
4491 my $savevm_wait = sub {
4495 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4496 if (!$stat->{status
}) {
4497 die "savevm not active\n";
4498 } elsif ($stat->{status
} eq 'active') {
4501 } elsif ($stat->{status
} eq 'completed') {
4504 die "query-savevm returned status '$stat->{status}'\n";
4509 sub snapshot_create
{
4510 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4512 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4514 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4518 my $running = check_running
($vmid);
4521 # create internal snapshots of all drives
4523 my $storecfg = PVE
::Storage
::config
();
4526 if ($snap->{vmstate
}) {
4527 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4528 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4529 &$savevm_wait($vmid);
4531 vm_mon_cmd
($vmid, "savevm-start");
4535 qga_freezefs
($vmid) if $running && $freezefs;
4537 foreach_drive
($snap, sub {
4538 my ($ds, $drive) = @_;
4540 return if drive_is_cdrom
($drive);
4542 my $volid = $drive->{file
};
4543 my $device = "drive-$ds";
4545 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4546 $drivehash->{$ds} = 1;
4551 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4554 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4558 warn "snapshot create failed: starting cleanup\n";
4559 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4564 &$snapshot_commit($vmid, $snapname);
4567 # Note: $drivehash is only set when called from snapshot_create.
4568 sub snapshot_delete
{
4569 my ($vmid, $snapname, $force, $drivehash) = @_;
4576 my $unlink_parent = sub {
4577 my ($confref, $new_parent) = @_;
4579 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4581 $confref->{parent
} = $new_parent;
4583 delete $confref->{parent
};
4588 my $updatefn = sub {
4589 my ($remove_drive) = @_;
4591 my $conf = load_config
($vmid);
4595 die "you can't delete a snapshot if vm is a template\n"
4596 if is_template
($conf);
4599 $snap = $conf->{snapshots
}->{$snapname};
4601 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4603 # remove parent refs
4604 &$unlink_parent($conf, $snap->{parent
});
4605 foreach my $sn (keys %{$conf->{snapshots
}}) {
4606 next if $sn eq $snapname;
4607 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4610 if ($remove_drive) {
4611 if ($remove_drive eq 'vmstate') {
4612 delete $snap->{$remove_drive};
4614 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4615 my $volid = $drive->{file
};
4616 delete $snap->{$remove_drive};
4617 add_unused_volume
($conf, $volid);
4622 $snap->{snapstate
} = 'delete';
4624 delete $conf->{snapshots
}->{$snapname};
4625 delete $conf->{lock} if $drivehash;
4626 foreach my $volid (@$unused) {
4627 add_unused_volume
($conf, $volid);
4631 update_config_nolock
($vmid, $conf, 1);
4634 lock_config
($vmid, $updatefn);
4636 # now remove vmstate file
4638 my $storecfg = PVE
::Storage
::config
();
4640 if ($snap->{vmstate
}) {
4641 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4643 die $err if !$force;
4646 # save changes (remove vmstate from snapshot)
4647 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4650 # now remove all internal snapshots
4651 foreach_drive
($snap, sub {
4652 my ($ds, $drive) = @_;
4654 return if drive_is_cdrom
($drive);
4656 my $volid = $drive->{file
};
4657 my $device = "drive-$ds";
4659 if (!$drivehash || $drivehash->{$ds}) {
4660 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4662 die $err if !$force;
4667 # save changes (remove drive fron snapshot)
4668 lock_config
($vmid, $updatefn, $ds) if !$force;
4669 push @$unused, $volid;
4672 # now cleanup config
4674 lock_config
($vmid, $updatefn);
4678 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4681 foreach_drive
($conf, sub {
4682 my ($ds, $drive) = @_;
4684 return if drive_is_cdrom
($drive);
4685 my $volid = $drive->{file
};
4686 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4689 return $err ?
0 : 1;
4692 sub template_create
{
4693 my ($vmid, $conf, $disk) = @_;
4695 my $storecfg = PVE
::Storage
::config
();
4697 foreach_drive
($conf, sub {
4698 my ($ds, $drive) = @_;
4700 return if drive_is_cdrom
($drive);
4701 return if $disk && $ds ne $disk;
4703 my $volid = $drive->{file
};
4704 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4706 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4707 $drive->{file
} = $voliddst;
4708 $conf->{$ds} = print_drive
($vmid, $drive);
4709 update_config_nolock
($vmid, $conf, 1);
4716 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4719 sub qemu_img_convert
{
4720 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4722 my $storecfg = PVE
::Storage
::config
();
4723 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4724 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4726 if ($src_storeid && $dst_storeid) {
4727 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4728 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4730 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4731 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4733 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4734 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4737 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4738 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4739 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4743 if($line =~ m/\((\S+)\/100\
%\)/){
4745 my $transferred = int($size * $percent / 100);
4746 my $remaining = $size - $transferred;
4748 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4753 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4755 die "copy failed: $err" if $err;
4759 sub qemu_img_format
{
4760 my ($scfg, $volname) = @_;
4762 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4764 } elsif ($scfg->{type
} eq 'iscsi') {
4765 return "host_device";
4771 sub qemu_drive_mirror
{
4772 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4778 my $storecfg = PVE
::Storage
::config
();
4779 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4782 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4785 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4789 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4792 #fixme : sometime drive-mirror timeout, but works fine after.
4793 # (I have see the problem with big volume > 200GB), so we need to eval
4794 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4795 sync
=> "full", target
=> $dst_path, format
=> $format); };
4797 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4798 sync
=> "full", target
=> $dst_path); };
4803 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4804 my $stat = @$stats[0];
4805 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4806 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4808 my $transferred = $stat->{offset
};
4809 my $total = $stat->{len
};
4810 my $remaining = $total - $transferred;
4811 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4813 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4815 last if ($stat->{len
} == $stat->{offset
});
4816 if ($old_len == $stat->{offset
}) {
4817 if ($maxwait && $count > $maxwait) {
4818 # if writes to disk occurs the disk needs to be freezed
4819 # to be able to complete the migration
4820 vm_suspend
($vmid,1);
4824 $count++ unless $frozen;
4830 $old_len = $stat->{offset
};
4834 if ($vmiddst == $vmid) {
4835 # switch the disk if source and destination are on the same guest
4836 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4840 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4841 die "mirroring error: $err";
4844 if ($vmiddst != $vmid) {
4845 # if we clone a disk for a new target vm, we don't switch the disk
4846 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4852 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4853 $newvmid, $storage, $format, $full, $newvollist) = @_;
4858 print "create linked clone of drive $drivename ($drive->{file})\n";
4859 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4860 push @$newvollist, $newvolid;
4862 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4863 $storeid = $storage if $storage;
4865 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4867 $format = $drive->{format
} || $defFormat;
4870 # test if requested format is supported - else use default
4871 my $supported = grep { $_ eq $format } @$validFormats;
4872 $format = $defFormat if !$supported;
4874 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4876 print "create full clone of drive $drivename ($drive->{file})\n";
4877 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4878 push @$newvollist, $newvolid;
4880 if (!$running || $snapname) {
4881 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4883 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4887 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4890 $disk->{format
} = undef;
4891 $disk->{file
} = $newvolid;
4892 $disk->{size
} = $size;
4897 # this only works if VM is running
4898 sub get_current_qemu_machine
{
4901 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4902 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4904 my ($current, $default);
4905 foreach my $e (@$res) {
4906 $default = $e->{name
} if $e->{'is-default'};
4907 $current = $e->{name
} if $e->{'is-current'};
4910 # fallback to the default machine if current is not supported by qemu
4911 return $current || $default || 'pc';
4914 sub read_x509_subject_spice
{
4915 my ($filename) = @_;
4918 my $bio = Net
::SSLeay
::BIO_new_file
($filename, 'r');
4919 my $x509 = Net
::SSLeay
::PEM_read_bio_X509
($bio);
4920 Net
::SSLeay
::BIO_free
($bio);
4921 my $nameobj = Net
::SSLeay
::X509_get_subject_name
($x509);
4922 my $subject = Net
::SSLeay
::X509_NAME_oneline
($nameobj);
4923 Net
::SSLeay
::X509_free
($x509);
4925 # remote-viewer wants comma as seperator (not '/')
4927 $subject =~ s!/(\w+=)!,$1!g;