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 lsi53c810 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', 'vmxnet3'];
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] [,discard=ignore|on]',
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] [,discard=ignore|on]',
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] [,discard=ignore|on]',
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] [,discard=ignore|on]',
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][,discard=ignore|on]
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|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
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)$/;
931 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
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_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
938 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
939 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
940 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
941 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
943 return undef if $res->{iops_rd
} && $res->{iops
};
944 return undef if $res->{iops_wr
} && $res->{iops
};
947 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
948 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
949 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
950 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
951 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
952 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
956 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
959 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
960 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
961 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
962 return undef if $res->{interface
} eq 'virtio';
965 # rerror does not work with scsi drives
966 if ($res->{rerror
}) {
967 return undef if $res->{interface
} eq 'scsi';
973 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
976 my ($vmid, $drive) = @_;
979 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
980 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
983 if ($drive->{size
}) {
984 $opts .= ",size=" . &$format_size($drive->{size
});
987 return "$drive->{file}$opts";
991 my($fh, $noerr) = @_;
994 my $SG_GET_VERSION_NUM = 0x2282;
996 my $versionbuf = "\x00" x
8;
997 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
999 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1002 my $version = unpack("I", $versionbuf);
1003 if ($version < 30000) {
1004 die "scsi generic interface too old\n" if !$noerr;
1008 my $buf = "\x00" x
36;
1009 my $sensebuf = "\x00" x
8;
1010 my $cmd = pack("C x3 C x1", 0x12, 36);
1012 # see /usr/include/scsi/sg.h
1013 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";
1015 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1016 length($sensebuf), 0, length($buf), $buf,
1017 $cmd, $sensebuf, 6000);
1019 $ret = ioctl($fh, $SG_IO, $packet);
1021 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1025 my @res = unpack($sg_io_hdr_t, $packet);
1026 if ($res[17] || $res[18]) {
1027 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1032 (my $byte0, my $byte1, $res->{vendor
},
1033 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1035 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1036 $res->{type
} = $byte0 & 31;
1044 my $fh = IO
::File-
>new("+<$path") || return undef;
1045 my $res = scsi_inquiry
($fh, 1);
1051 sub print_drivedevice_full
{
1052 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1057 if ($drive->{interface
} eq 'virtio') {
1058 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1059 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1060 } elsif ($drive->{interface
} eq 'scsi') {
1061 $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
1062 my $controller = int($drive->{index} / $maxdev);
1063 my $unit = $drive->{index} % $maxdev;
1064 my $devicetype = 'hd';
1066 if (drive_is_cdrom
($drive)) {
1069 if ($drive->{file
} =~ m
|^/|) {
1070 $path = $drive->{file
};
1072 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1075 if($path =~ m/^iscsi\:\/\
//){
1076 $devicetype = 'generic';
1078 if (my $info = path_is_scsi
($path)) {
1079 if ($info->{type
} == 0) {
1080 $devicetype = 'block';
1081 } elsif ($info->{type
} == 1) { # tape
1082 $devicetype = 'generic';
1088 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1089 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1091 $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}";
1094 } elsif ($drive->{interface
} eq 'ide'){
1096 my $controller = int($drive->{index} / $maxdev);
1097 my $unit = $drive->{index} % $maxdev;
1098 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1100 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1101 } elsif ($drive->{interface
} eq 'sata'){
1102 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1103 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1104 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1105 } elsif ($drive->{interface
} eq 'usb') {
1107 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1109 die "unsupported interface type";
1112 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1117 sub print_drive_full
{
1118 my ($storecfg, $vmid, $drive) = @_;
1121 foreach my $o (@qemu_drive_options) {
1122 next if $o eq 'bootindex';
1123 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1126 foreach my $o (qw(bps bps_rd bps_wr)) {
1127 my $v = $drive->{"m$o"};
1128 $opts .= ",$o=" . int($v*1024*1024) if $v;
1131 # use linux-aio by default (qemu default is threads)
1132 $opts .= ",aio=native" if !$drive->{aio
};
1135 my $volid = $drive->{file
};
1136 if (drive_is_cdrom
($drive)) {
1137 $path = get_iso_path
($storecfg, $vmid, $volid);
1139 if ($volid =~ m
|^/|) {
1142 $path = PVE
::Storage
::path
($storecfg, $volid);
1146 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1148 my $pathinfo = $path ?
"file=$path," : '';
1150 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1153 sub print_netdevice_full
{
1154 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1156 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1158 my $device = $net->{model
};
1159 if ($net->{model
} eq 'virtio') {
1160 $device = 'virtio-net-pci';
1163 # qemu > 0.15 always try to boot from network - we disable that by
1164 # not loading the pxe rom file
1165 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1166 my $pciaddr = print_pci_addr
("$netid", $bridges);
1167 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1168 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1172 sub print_netdev_full
{
1173 my ($vmid, $conf, $net, $netid) = @_;
1176 if ($netid =~ m/^net(\d+)$/) {
1180 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1182 my $ifname = "tap${vmid}i$i";
1184 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1185 die "interface name '$ifname' is too long (max 15 character)\n"
1186 if length($ifname) >= 16;
1188 my $vhostparam = '';
1189 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1191 my $vmname = $conf->{name
} || "vm$vmid";
1193 if ($net->{bridge
}) {
1194 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1196 return "type=user,id=$netid,hostname=$vmname";
1200 sub drive_is_cdrom
{
1203 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1210 return undef if !$value;
1214 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1215 $res->{pciid
} = $value;
1223 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1229 foreach my $kvp (split(/,/, $data)) {
1231 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1233 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1234 $res->{model
} = $model;
1235 $res->{macaddr
} = $mac;
1236 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1237 $res->{bridge
} = $1;
1238 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1240 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1248 return undef if !$res->{model
};
1256 my $res = "$net->{model}";
1257 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1258 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1259 $res .= ",rate=$net->{rate}" if $net->{rate
};
1260 $res .= ",tag=$net->{tag}" if $net->{tag
};
1265 sub add_random_macs
{
1266 my ($settings) = @_;
1268 foreach my $opt (keys %$settings) {
1269 next if $opt !~ m/^net(\d+)$/;
1270 my $net = parse_net
($settings->{$opt});
1272 $settings->{$opt} = print_net
($net);
1276 sub add_unused_volume
{
1277 my ($config, $volid) = @_;
1280 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1281 my $test = "unused$ind";
1282 if (my $vid = $config->{$test}) {
1283 return if $vid eq $volid; # do not add duplicates
1289 die "To many unused volume - please delete them first.\n" if !$key;
1291 $config->{$key} = $volid;
1296 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1297 sub verify_bootdisk
{
1298 my ($value, $noerr) = @_;
1300 return $value if valid_drivename
($value);
1302 return undef if $noerr;
1304 die "invalid boot disk '$value'\n";
1307 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1309 my ($value, $noerr) = @_;
1311 return $value if parse_net
($value);
1313 return undef if $noerr;
1315 die "unable to parse network options\n";
1318 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1320 my ($value, $noerr) = @_;
1322 return $value if parse_drive
(undef, $value);
1324 return undef if $noerr;
1326 die "unable to parse drive options\n";
1329 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1330 sub verify_hostpci
{
1331 my ($value, $noerr) = @_;
1333 return $value if parse_hostpci
($value);
1335 return undef if $noerr;
1337 die "unable to parse pci id\n";
1340 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1341 sub verify_watchdog
{
1342 my ($value, $noerr) = @_;
1344 return $value if parse_watchdog
($value);
1346 return undef if $noerr;
1348 die "unable to parse watchdog options\n";
1351 sub parse_watchdog
{
1354 return undef if !$value;
1358 foreach my $p (split(/,/, $value)) {
1359 next if $p =~ m/^\s*$/;
1361 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1363 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1364 $res->{action
} = $2;
1373 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1374 sub verify_startup
{
1375 my ($value, $noerr) = @_;
1377 return $value if parse_startup
($value);
1379 return undef if $noerr;
1381 die "unable to parse startup options\n";
1387 return undef if !$value;
1391 foreach my $p (split(/,/, $value)) {
1392 next if $p =~ m/^\s*$/;
1394 if ($p =~ m/^(order=)?(\d+)$/) {
1396 } elsif ($p =~ m/^up=(\d+)$/) {
1398 } elsif ($p =~ m/^down=(\d+)$/) {
1408 sub parse_usb_device
{
1411 return undef if !$value;
1413 my @dl = split(/,/, $value);
1417 foreach my $v (@dl) {
1418 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1420 $res->{vendorid
} = $2;
1421 $res->{productid
} = $4;
1422 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1424 $res->{hostbus
} = $1;
1425 $res->{hostport
} = $2;
1426 } elsif ($v =~ m/^spice$/) {
1433 return undef if !$found;
1438 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1439 sub verify_usb_device
{
1440 my ($value, $noerr) = @_;
1442 return $value if parse_usb_device
($value);
1444 return undef if $noerr;
1446 die "unable to parse usb device\n";
1449 # add JSON properties for create and set function
1450 sub json_config_properties
{
1453 foreach my $opt (keys %$confdesc) {
1454 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1455 $prop->{$opt} = $confdesc->{$opt};
1462 my ($key, $value) = @_;
1464 die "unknown setting '$key'\n" if !$confdesc->{$key};
1466 my $type = $confdesc->{$key}->{type
};
1468 if (!defined($value)) {
1469 die "got undefined value\n";
1472 if ($value =~ m/[\n\r]/) {
1473 die "property contains a line feed\n";
1476 if ($type eq 'boolean') {
1477 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1478 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1479 die "type check ('boolean') failed - got '$value'\n";
1480 } elsif ($type eq 'integer') {
1481 return int($1) if $value =~ m/^(\d+)$/;
1482 die "type check ('integer') failed - got '$value'\n";
1483 } elsif ($type eq 'number') {
1484 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1485 die "type check ('number') failed - got '$value'\n";
1486 } elsif ($type eq 'string') {
1487 if (my $fmt = $confdesc->{$key}->{format
}) {
1488 if ($fmt eq 'pve-qm-drive') {
1489 # special case - we need to pass $key to parse_drive()
1490 my $drive = parse_drive
($key, $value);
1491 return $value if $drive;
1492 die "unable to parse drive options\n";
1494 PVE
::JSONSchema
::check_format
($fmt, $value);
1497 $value =~ s/^\"(.*)\"$/$1/;
1500 die "internal error"
1504 sub lock_config_full
{
1505 my ($vmid, $timeout, $code, @param) = @_;
1507 my $filename = config_file_lock
($vmid);
1509 my $res = lock_file
($filename, $timeout, $code, @param);
1516 sub lock_config_mode
{
1517 my ($vmid, $timeout, $shared, $code, @param) = @_;
1519 my $filename = config_file_lock
($vmid);
1521 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1529 my ($vmid, $code, @param) = @_;
1531 return lock_config_full
($vmid, 10, $code, @param);
1534 sub cfs_config_path
{
1535 my ($vmid, $node) = @_;
1537 $node = $nodename if !$node;
1538 return "nodes/$node/qemu-server/$vmid.conf";
1541 sub check_iommu_support
{
1542 #fixme : need to check IOMMU support
1543 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1551 my ($vmid, $node) = @_;
1553 my $cfspath = cfs_config_path
($vmid, $node);
1554 return "/etc/pve/$cfspath";
1557 sub config_file_lock
{
1560 return "$lock_dir/lock-$vmid.conf";
1566 my $conf = config_file
($vmid);
1567 utime undef, undef, $conf;
1571 my ($storecfg, $vmid, $keep_empty_config) = @_;
1573 my $conffile = config_file
($vmid);
1575 my $conf = load_config
($vmid);
1579 # only remove disks owned by this VM
1580 foreach_drive
($conf, sub {
1581 my ($ds, $drive) = @_;
1583 return if drive_is_cdrom
($drive);
1585 my $volid = $drive->{file
};
1587 return if !$volid || $volid =~ m
|^/|;
1589 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1590 return if !$path || !$owner || ($owner != $vmid);
1592 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1595 if ($keep_empty_config) {
1596 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1601 # also remove unused disk
1603 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1606 PVE
::Storage
::foreach_volid
($dl, sub {
1607 my ($volid, $sid, $volname, $d) = @_;
1608 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1618 my ($vmid, $node) = @_;
1620 my $cfspath = cfs_config_path
($vmid, $node);
1622 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1624 die "no such VM ('$vmid')\n" if !defined($conf);
1629 sub parse_vm_config
{
1630 my ($filename, $raw) = @_;
1632 return undef if !defined($raw);
1635 digest
=> Digest
::SHA
::sha1_hex
($raw),
1639 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1640 || die "got strange filename '$filename'";
1647 my @lines = split(/\n/, $raw);
1648 foreach my $line (@lines) {
1649 next if $line =~ m/^\s*$/;
1651 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1653 $conf->{description
} = $descr if $descr;
1655 $conf = $res->{snapshots
}->{$snapname} = {};
1659 if ($line =~ m/^\#(.*)\s*$/) {
1660 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1664 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1665 $descr .= PVE
::Tools
::decode_text
($2);
1666 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1667 $conf->{snapstate
} = $1;
1668 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1671 $conf->{$key} = $value;
1672 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1675 eval { $value = check_type
($key, $value); };
1677 warn "vm $vmid - unable to parse value of '$key' - $@";
1679 my $fmt = $confdesc->{$key}->{format
};
1680 if ($fmt && $fmt eq 'pve-qm-drive') {
1681 my $v = parse_drive
($key, $value);
1682 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1683 $v->{file
} = $volid;
1684 $value = print_drive
($vmid, $v);
1686 warn "vm $vmid - unable to parse value of '$key'\n";
1691 if ($key eq 'cdrom') {
1692 $conf->{ide2
} = $value;
1694 $conf->{$key} = $value;
1700 $conf->{description
} = $descr if $descr;
1702 delete $res->{snapstate
}; # just to be sure
1707 sub write_vm_config
{
1708 my ($filename, $conf) = @_;
1710 delete $conf->{snapstate
}; # just to be sure
1712 if ($conf->{cdrom
}) {
1713 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1714 $conf->{ide2
} = $conf->{cdrom
};
1715 delete $conf->{cdrom
};
1718 # we do not use 'smp' any longer
1719 if ($conf->{sockets
}) {
1720 delete $conf->{smp
};
1721 } elsif ($conf->{smp
}) {
1722 $conf->{sockets
} = $conf->{smp
};
1723 delete $conf->{cores
};
1724 delete $conf->{smp
};
1727 my $used_volids = {};
1729 my $cleanup_config = sub {
1730 my ($cref, $snapname) = @_;
1732 foreach my $key (keys %$cref) {
1733 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1734 $key eq 'snapstate';
1735 my $value = $cref->{$key};
1736 eval { $value = check_type
($key, $value); };
1737 die "unable to parse value of '$key' - $@" if $@;
1739 $cref->{$key} = $value;
1741 if (!$snapname && valid_drivename
($key)) {
1742 my $drive = parse_drive
($key, $value);
1743 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1748 &$cleanup_config($conf);
1749 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1750 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1753 # remove 'unusedX' settings if we re-add a volume
1754 foreach my $key (keys %$conf) {
1755 my $value = $conf->{$key};
1756 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1757 delete $conf->{$key};
1761 my $generate_raw_config = sub {
1766 # add description as comment to top of file
1767 my $descr = $conf->{description
} || '';
1768 foreach my $cl (split(/\n/, $descr)) {
1769 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1772 foreach my $key (sort keys %$conf) {
1773 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1774 $raw .= "$key: $conf->{$key}\n";
1779 my $raw = &$generate_raw_config($conf);
1780 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1781 $raw .= "\n[$snapname]\n";
1782 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1788 sub update_config_nolock
{
1789 my ($vmid, $conf, $skiplock) = @_;
1791 check_lock
($conf) if !$skiplock;
1793 my $cfspath = cfs_config_path
($vmid);
1795 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1799 my ($vmid, $conf, $skiplock) = @_;
1801 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1808 # we use static defaults from our JSON schema configuration
1809 foreach my $key (keys %$confdesc) {
1810 if (defined(my $default = $confdesc->{$key}->{default})) {
1811 $res->{$key} = $default;
1815 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1816 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1822 my $vmlist = PVE
::Cluster
::get_vmlist
();
1824 return $res if !$vmlist || !$vmlist->{ids
};
1825 my $ids = $vmlist->{ids
};
1827 foreach my $vmid (keys %$ids) {
1828 my $d = $ids->{$vmid};
1829 next if !$d->{node
} || $d->{node
} ne $nodename;
1830 next if !$d->{type
} || $d->{type
} ne 'qemu';
1831 $res->{$vmid}->{exists} = 1;
1836 # test if VM uses local resources (to prevent migration)
1837 sub check_local_resources
{
1838 my ($conf, $noerr) = @_;
1842 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1843 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1845 foreach my $k (keys %$conf) {
1846 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
1847 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1850 die "VM uses local resources\n" if $loc_res && !$noerr;
1855 # check if used storages are available on all nodes (use by migrate)
1856 sub check_storage_availability
{
1857 my ($storecfg, $conf, $node) = @_;
1859 foreach_drive
($conf, sub {
1860 my ($ds, $drive) = @_;
1862 my $volid = $drive->{file
};
1865 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1868 # check if storage is available on both nodes
1869 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1870 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1874 # list nodes where all VM images are available (used by has_feature API)
1876 my ($conf, $storecfg) = @_;
1878 my $nodelist = PVE
::Cluster
::get_nodelist
();
1879 my $nodehash = { map { $_ => 1 } @$nodelist };
1880 my $nodename = PVE
::INotify
::nodename
();
1882 foreach_drive
($conf, sub {
1883 my ($ds, $drive) = @_;
1885 my $volid = $drive->{file
};
1888 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1890 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1891 if ($scfg->{disable
}) {
1893 } elsif (my $avail = $scfg->{nodes
}) {
1894 foreach my $node (keys %$nodehash) {
1895 delete $nodehash->{$node} if !$avail->{$node};
1897 } elsif (!$scfg->{shared
}) {
1898 foreach my $node (keys %$nodehash) {
1899 delete $nodehash->{$node} if $node ne $nodename
1911 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1915 my ($pidfile, $pid) = @_;
1917 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1921 return undef if !$line;
1922 my @param = split(/\0/, $line);
1924 my $cmd = $param[0];
1925 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1927 for (my $i = 0; $i < scalar (@param); $i++) {
1930 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1931 my $p = $param[$i+1];
1932 return 1 if $p && ($p eq $pidfile);
1941 my ($vmid, $nocheck, $node) = @_;
1943 my $filename = config_file
($vmid, $node);
1945 die "unable to find configuration file for VM $vmid - no such machine\n"
1946 if !$nocheck && ! -f
$filename;
1948 my $pidfile = pidfile_name
($vmid);
1950 if (my $fd = IO
::File-
>new("<$pidfile")) {
1955 my $mtime = $st->mtime;
1956 if ($mtime > time()) {
1957 warn "file '$filename' modified in future\n";
1960 if ($line =~ m/^(\d+)$/) {
1962 if (check_cmdline
($pidfile, $pid)) {
1963 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1975 my $vzlist = config_list
();
1977 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1979 while (defined(my $de = $fd->read)) {
1980 next if $de !~ m/^(\d+)\.pid$/;
1982 next if !defined($vzlist->{$vmid});
1983 if (my $pid = check_running
($vmid)) {
1984 $vzlist->{$vmid}->{pid
} = $pid;
1992 my ($storecfg, $conf) = @_;
1994 my $bootdisk = $conf->{bootdisk
};
1995 return undef if !$bootdisk;
1996 return undef if !valid_drivename
($bootdisk);
1998 return undef if !$conf->{$bootdisk};
2000 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2001 return undef if !defined($drive);
2003 return undef if drive_is_cdrom
($drive);
2005 my $volid = $drive->{file
};
2006 return undef if !$volid;
2008 return $drive->{size
};
2011 my $last_proc_pid_stat;
2013 # get VM status information
2014 # This must be fast and should not block ($full == false)
2015 # We only query KVM using QMP if $full == true (this can be slow)
2017 my ($opt_vmid, $full) = @_;
2021 my $storecfg = PVE
::Storage
::config
();
2023 my $list = vzlist
();
2024 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2026 my $cpucount = $cpuinfo->{cpus
} || 1;
2028 foreach my $vmid (keys %$list) {
2029 next if $opt_vmid && ($vmid ne $opt_vmid);
2031 my $cfspath = cfs_config_path
($vmid);
2032 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2035 $d->{pid
} = $list->{$vmid}->{pid
};
2037 # fixme: better status?
2038 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2040 my $size = disksize
($storecfg, $conf);
2041 if (defined($size)) {
2042 $d->{disk
} = 0; # no info available
2043 $d->{maxdisk
} = $size;
2049 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2050 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2052 $d->{name
} = $conf->{name
} || "VM $vmid";
2053 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2055 if ($conf->{balloon
}) {
2056 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2057 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2068 $d->{diskwrite
} = 0;
2070 $d->{template
} = is_template
($conf);
2075 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2076 foreach my $dev (keys %$netdev) {
2077 next if $dev !~ m/^tap([1-9]\d*)i/;
2079 my $d = $res->{$vmid};
2082 $d->{netout
} += $netdev->{$dev}->{receive
};
2083 $d->{netin
} += $netdev->{$dev}->{transmit
};
2086 my $ctime = gettimeofday
;
2088 foreach my $vmid (keys %$list) {
2090 my $d = $res->{$vmid};
2091 my $pid = $d->{pid
};
2094 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2095 next if !$pstat; # not running
2097 my $used = $pstat->{utime} + $pstat->{stime
};
2099 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2101 if ($pstat->{vsize
}) {
2102 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2105 my $old = $last_proc_pid_stat->{$pid};
2107 $last_proc_pid_stat->{$pid} = {
2115 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2117 if ($dtime > 1000) {
2118 my $dutime = $used - $old->{used
};
2120 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2121 $last_proc_pid_stat->{$pid} = {
2127 $d->{cpu
} = $old->{cpu
};
2131 return $res if !$full;
2133 my $qmpclient = PVE
::QMPClient-
>new();
2135 my $ballooncb = sub {
2136 my ($vmid, $resp) = @_;
2138 my $info = $resp->{'return'};
2139 return if !$info->{max_mem
};
2141 my $d = $res->{$vmid};
2143 # use memory assigned to VM
2144 $d->{maxmem
} = $info->{max_mem
};
2145 $d->{balloon
} = $info->{actual
};
2147 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2148 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2149 $d->{freemem
} = $info->{free_mem
};
2154 my $blockstatscb = sub {
2155 my ($vmid, $resp) = @_;
2156 my $data = $resp->{'return'} || [];
2157 my $totalrdbytes = 0;
2158 my $totalwrbytes = 0;
2159 for my $blockstat (@$data) {
2160 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2161 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2163 $res->{$vmid}->{diskread
} = $totalrdbytes;
2164 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2167 my $statuscb = sub {
2168 my ($vmid, $resp) = @_;
2170 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2171 # this fails if ballon driver is not loaded, so this must be
2172 # the last commnand (following command are aborted if this fails).
2173 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2175 my $status = 'unknown';
2176 if (!defined($status = $resp->{'return'}->{status
})) {
2177 warn "unable to get VM status\n";
2181 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2184 foreach my $vmid (keys %$list) {
2185 next if $opt_vmid && ($vmid ne $opt_vmid);
2186 next if !$res->{$vmid}->{pid
}; # not running
2187 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2190 $qmpclient->queue_execute();
2192 foreach my $vmid (keys %$list) {
2193 next if $opt_vmid && ($vmid ne $opt_vmid);
2194 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2201 my ($conf, $func) = @_;
2203 foreach my $ds (keys %$conf) {
2204 next if !valid_drivename
($ds);
2206 my $drive = parse_drive
($ds, $conf->{$ds});
2209 &$func($ds, $drive);
2214 my ($conf, $func) = @_;
2218 my $test_volid = sub {
2219 my ($volid, $is_cdrom) = @_;
2223 $volhash->{$volid} = $is_cdrom || 0;
2226 foreach_drive
($conf, sub {
2227 my ($ds, $drive) = @_;
2228 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2231 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2232 my $snap = $conf->{snapshots
}->{$snapname};
2233 &$test_volid($snap->{vmstate
}, 0);
2234 foreach_drive
($snap, sub {
2235 my ($ds, $drive) = @_;
2236 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2240 foreach my $volid (keys %$volhash) {
2241 &$func($volid, $volhash->{$volid});
2245 sub vga_conf_has_spice
{
2248 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2253 sub config_to_command
{
2254 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2257 my $globalFlags = [];
2258 my $machineFlags = [];
2264 my $kvmver = kvm_user_version
();
2265 my $vernum = 0; # unknown
2266 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2267 $vernum = $1*1000000+$2*1000;
2268 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2269 $vernum = $1*1000000+$2*1000+$3;
2272 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2274 my $have_ovz = -f
'/proc/vz/vestat';
2276 push @$cmd, '/usr/bin/kvm';
2278 push @$cmd, '-id', $vmid;
2282 my $qmpsocket = qmp_socket
($vmid);
2283 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2284 push @$cmd, '-mon', "chardev=qmp,mode=control";
2286 my $socket = vnc_socket
($vmid);
2287 push @$cmd, '-vnc', "unix:$socket,x509,password";
2289 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2291 push @$cmd, '-daemonize';
2293 $pciaddr = print_pci_addr
("piix3", $bridges);
2294 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2297 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2298 next if !$conf->{"usb$i"};
2301 # include usb device config
2302 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2304 my $vga = $conf->{vga
};
2306 my $qxlnum = vga_conf_has_spice
($vga);
2307 $vga = 'qxl' if $qxlnum;
2310 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2311 $conf->{ostype
} eq 'win7' ||
2312 $conf->{ostype
} eq 'w2k8')) {
2319 # enable absolute mouse coordinates (needed by vnc)
2321 if (defined($conf->{tablet
})) {
2322 $tablet = $conf->{tablet
};
2324 $tablet = $defaults->{tablet
};
2325 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2326 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2329 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2332 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2333 my $d = parse_hostpci
($conf->{"hostpci$i"});
2335 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2336 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2340 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2341 my $d = parse_usb_device
($conf->{"usb$i"});
2343 if ($d->{vendorid
} && $d->{productid
}) {
2344 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2345 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2346 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2347 } elsif ($d->{spice
}) {
2348 # usb redir support for spice
2349 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2350 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2355 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2356 if (my $path = $conf->{"serial$i"}) {
2357 if ($path eq 'socket') {
2358 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2359 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2360 push @$devices, '-device', "isa-serial,chardev=serial$i";
2362 die "no such serial device\n" if ! -c
$path;
2363 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2364 push @$devices, '-device', "isa-serial,chardev=serial$i";
2370 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2371 if (my $path = $conf->{"parallel$i"}) {
2372 die "no such parallel device\n" if ! -c
$path;
2373 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2374 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2375 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2379 my $vmname = $conf->{name
} || "vm$vmid";
2381 push @$cmd, '-name', $vmname;
2384 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2385 $sockets = $conf->{sockets
} if $conf->{sockets
};
2387 my $cores = $conf->{cores
} || 1;
2388 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2390 push @$cmd, '-nodefaults';
2392 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2394 my $bootindex_hash = {};
2396 foreach my $o (split(//, $bootorder)) {
2397 $bootindex_hash->{$o} = $i*100;
2401 push @$cmd, '-boot', "menu=on";
2403 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2405 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2407 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2410 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2412 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2413 my $useLocaltime = $conf->{localtime};
2415 if (my $ost = $conf->{ostype
}) {
2416 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2418 if ($ost =~ m/^w/) { # windows
2419 $useLocaltime = 1 if !defined($conf->{localtime});
2421 # use time drift fix when acpi is enabled
2422 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2423 $tdf = 1 if !defined($conf->{tdf
});
2427 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2429 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2430 push @$cmd, '-no-hpet';
2431 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2432 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2435 if ($ost eq 'win7' || $ost eq 'win8') {
2436 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2440 push @$rtcFlags, 'driftfix=slew' if $tdf;
2443 push @$machineFlags, 'accel=tcg';
2445 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2448 my $machine_type = $forcemachine || $conf->{machine
};
2449 if ($machine_type) {
2450 push @$machineFlags, "type=${machine_type}";
2453 if ($conf->{startdate
}) {
2454 push @$rtcFlags, "base=$conf->{startdate}";
2455 } elsif ($useLocaltime) {
2456 push @$rtcFlags, 'base=localtime';
2459 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2460 $cpu = $conf->{cpu
} if $conf->{cpu
};
2462 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2464 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2466 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2468 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2470 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2472 push @$cmd, '-cpu', $cpu;
2474 push @$cmd, '-S' if $conf->{freeze
};
2476 # set keyboard layout
2477 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2478 push @$cmd, '-k', $kb if $kb;
2481 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2482 #push @$cmd, '-soundhw', 'es1370';
2483 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2485 if($conf->{agent
}) {
2486 my $qgasocket = qga_socket
($vmid);
2487 my $pciaddr = print_pci_addr
("qga0", $bridges);
2488 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2489 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2490 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2497 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
2498 for(my $i = 1; $i < $qxlnum; $i++){
2499 my $pciaddr = print_pci_addr
("vga$i", $bridges);
2500 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2503 # assume other OS works like Linux
2504 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2505 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2509 my $pciaddr = print_pci_addr
("spice", $bridges);
2511 $spice_port = PVE
::Tools
::next_spice_port
();
2513 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2515 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2516 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2517 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2520 # enable balloon by default, unless explicitly disabled
2521 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2522 $pciaddr = print_pci_addr
("balloon0", $bridges);
2523 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2526 if ($conf->{watchdog
}) {
2527 my $wdopts = parse_watchdog
($conf->{watchdog
});
2528 $pciaddr = print_pci_addr
("watchdog", $bridges);
2529 my $watchdog = $wdopts->{model
} || 'i6300esb';
2530 push @$devices, '-device', "$watchdog$pciaddr";
2531 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2535 my $scsicontroller = {};
2536 my $ahcicontroller = {};
2537 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2539 foreach_drive
($conf, sub {
2540 my ($ds, $drive) = @_;
2542 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2543 push @$vollist, $drive->{file
};
2546 $use_virtio = 1 if $ds =~ m/^virtio/;
2548 if (drive_is_cdrom
($drive)) {
2549 if ($bootindex_hash->{d
}) {
2550 $drive->{bootindex
} = $bootindex_hash->{d
};
2551 $bootindex_hash->{d
} += 1;
2554 if ($bootindex_hash->{c
}) {
2555 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2556 $bootindex_hash->{c
} += 1;
2560 if ($drive->{interface
} eq 'scsi') {
2562 my $maxdev = ($scsihw !~ m/^lsi/) ?
256 : 7;
2563 my $controller = int($drive->{index} / $maxdev);
2564 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2565 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2566 $scsicontroller->{$controller}=1;
2569 if ($drive->{interface
} eq 'sata') {
2570 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2571 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2572 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2573 $ahcicontroller->{$controller}=1;
2576 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2577 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2580 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2582 for (my $i = 0; $i < $MAX_NETS; $i++) {
2583 next if !$conf->{"net$i"};
2584 my $d = parse_net
($conf->{"net$i"});
2587 $use_virtio = 1 if $d->{model
} eq 'virtio';
2589 if ($bootindex_hash->{n
}) {
2590 $d->{bootindex
} = $bootindex_hash->{n
};
2591 $bootindex_hash->{n
} += 1;
2594 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2595 push @$devices, '-netdev', $netdevfull;
2597 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2598 push @$devices, '-device', $netdevicefull;
2602 while (my ($k, $v) = each %$bridges) {
2603 $pciaddr = print_pci_addr
("pci.$k");
2604 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2608 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2609 # when the VM uses virtio devices.
2610 if (!$use_virtio && $have_ovz) {
2612 my $cpuunits = defined($conf->{cpuunits
}) ?
2613 $conf->{cpuunits
} : $defaults->{cpuunits
};
2615 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2617 # fixme: cpulimit is currently ignored
2618 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2622 if ($conf->{args
}) {
2623 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2627 push @$cmd, @$devices;
2628 push @$cmd, '-rtc', join(',', @$rtcFlags)
2629 if scalar(@$rtcFlags);
2630 push @$cmd, '-machine', join(',', @$machineFlags)
2631 if scalar(@$machineFlags);
2632 push @$cmd, '-global', join(',', @$globalFlags)
2633 if scalar(@$globalFlags);
2635 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2640 return "${var_run_tmpdir}/$vmid.vnc";
2646 my $res = vm_mon_cmd
($vmid, 'query-spice');
2648 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2653 return "${var_run_tmpdir}/$vmid.qmp";
2658 return "${var_run_tmpdir}/$vmid.qga";
2663 return "${var_run_tmpdir}/$vmid.pid";
2666 sub vm_devices_list
{
2669 my $res = vm_mon_cmd
($vmid, 'query-pci');
2672 foreach my $pcibus (@$res) {
2673 foreach my $device (@{$pcibus->{devices
}}) {
2674 next if !$device->{'qdev_id'};
2675 $devices->{$device->{'qdev_id'}} = $device;
2683 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2685 return 1 if !check_running
($vmid);
2687 if ($deviceid eq 'tablet') {
2688 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2689 qemu_deviceadd
($vmid, $devicefull);
2693 return 1 if !$conf->{hotplug
};
2695 my $devices_list = vm_devices_list
($vmid);
2696 return 1 if defined($devices_list->{$deviceid});
2698 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2700 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2701 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2702 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2703 qemu_deviceadd
($vmid, $devicefull);
2704 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2705 qemu_drivedel
($vmid, $deviceid);
2710 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2711 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2712 my $pciaddr = print_pci_addr
($deviceid);
2713 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2714 qemu_deviceadd
($vmid, $devicefull);
2715 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2718 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2719 return 1 if ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
2720 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2721 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2722 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2723 if(!qemu_deviceadd
($vmid, $devicefull)) {
2724 qemu_drivedel
($vmid, $deviceid);
2729 if ($deviceid =~ m/^(net)(\d+)$/) {
2730 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2731 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2732 qemu_deviceadd
($vmid, $netdevicefull);
2733 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2734 qemu_netdevdel
($vmid, $deviceid);
2739 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2741 my $pciaddr = print_pci_addr
($deviceid);
2742 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2743 qemu_deviceadd
($vmid, $devicefull);
2744 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2750 sub vm_deviceunplug
{
2751 my ($vmid, $conf, $deviceid) = @_;
2753 return 1 if !check_running
($vmid);
2755 if ($deviceid eq 'tablet') {
2756 qemu_devicedel
($vmid, $deviceid);
2760 return 1 if !$conf->{hotplug
};
2762 my $devices_list = vm_devices_list
($vmid);
2763 return 1 if !defined($devices_list->{$deviceid});
2765 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2767 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2768 qemu_devicedel
($vmid, $deviceid);
2769 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2770 return undef if !qemu_drivedel
($vmid, $deviceid);
2773 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2774 return undef if !qemu_devicedel
($vmid, $deviceid);
2777 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2778 return undef if !qemu_devicedel
($vmid, $deviceid);
2779 return undef if !qemu_drivedel
($vmid, $deviceid);
2782 if ($deviceid =~ m/^(net)(\d+)$/) {
2783 qemu_devicedel
($vmid, $deviceid);
2784 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2785 return undef if !qemu_netdevdel
($vmid, $deviceid);
2791 sub qemu_deviceadd
{
2792 my ($vmid, $devicefull) = @_;
2794 $devicefull = "driver=".$devicefull;
2795 my %options = split(/[=,]/, $devicefull);
2797 vm_mon_cmd
($vmid, "device_add" , %options);
2801 sub qemu_devicedel
{
2802 my($vmid, $deviceid) = @_;
2803 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2808 my($storecfg, $vmid, $device) = @_;
2810 my $drive = print_drive_full
($storecfg, $vmid, $device);
2811 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2812 # If the command succeeds qemu prints: "OK"
2813 if ($ret !~ m/OK/s) {
2814 syslog
("err", "adding drive failed: $ret");
2821 my($vmid, $deviceid) = @_;
2823 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2825 if ($ret =~ m/Device \'.*?\' not found/s) {
2826 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2828 elsif ($ret ne "") {
2829 syslog
("err", "deleting drive $deviceid failed : $ret");
2835 sub qemu_deviceaddverify
{
2836 my ($vmid,$deviceid) = @_;
2838 for (my $i = 0; $i <= 5; $i++) {
2839 my $devices_list = vm_devices_list
($vmid);
2840 return 1 if defined($devices_list->{$deviceid});
2843 syslog
("err", "error on hotplug device $deviceid");
2848 sub qemu_devicedelverify
{
2849 my ($vmid,$deviceid) = @_;
2851 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2852 for (my $i = 0; $i <= 5; $i++) {
2853 my $devices_list = vm_devices_list
($vmid);
2854 return 1 if !defined($devices_list->{$deviceid});
2857 syslog
("err", "error on hot-unplugging device $deviceid");
2861 sub qemu_findorcreatescsihw
{
2862 my ($storecfg, $conf, $vmid, $device) = @_;
2864 my $maxdev = ($conf->{scsihw
} && ($conf->{scsihw
} !~ m/^lsi/)) ?
256 : 7;
2865 my $controller = int($device->{index} / $maxdev);
2866 my $scsihwid="scsihw$controller";
2867 my $devices_list = vm_devices_list
($vmid);
2869 if(!defined($devices_list->{$scsihwid})) {
2870 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2875 sub qemu_bridgeadd
{
2876 my ($storecfg, $conf, $vmid, $device) = @_;
2879 my $bridgeid = undef;
2880 print_pci_addr
($device, $bridges);
2882 while (my ($k, $v) = each %$bridges) {
2885 return if !$bridgeid || $bridgeid < 1;
2886 my $bridge = "pci.$bridgeid";
2887 my $devices_list = vm_devices_list
($vmid);
2889 if(!defined($devices_list->{$bridge})) {
2890 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2895 sub qemu_netdevadd
{
2896 my ($vmid, $conf, $device, $deviceid) = @_;
2898 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2899 my %options = split(/[=,]/, $netdev);
2901 vm_mon_cmd
($vmid, "netdev_add", %options);
2905 sub qemu_netdevdel
{
2906 my ($vmid, $deviceid) = @_;
2908 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2912 sub qemu_block_set_io_throttle
{
2913 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2915 return if !check_running
($vmid) ;
2917 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));
2921 # old code, only used to shutdown old VM after update
2923 my ($fh, $timeout) = @_;
2925 my $sel = new IO
::Select
;
2932 while (scalar (@ready = $sel->can_read($timeout))) {
2934 if ($count = $fh->sysread($buf, 8192)) {
2935 if ($buf =~ /^(.*)\(qemu\) $/s) {
2942 if (!defined($count)) {
2949 die "monitor read timeout\n" if !scalar(@ready);
2954 # old code, only used to shutdown old VM after update
2955 sub vm_monitor_command
{
2956 my ($vmid, $cmdstr, $nocheck) = @_;
2961 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2963 my $sname = "${var_run_tmpdir}/$vmid.mon";
2965 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2966 die "unable to connect to VM $vmid socket - $!\n";
2970 # hack: migrate sometime blocks the monitor (when migrate_downtime
2972 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2973 $timeout = 60*60; # 1 hour
2977 my $data = __read_avail
($sock, $timeout);
2979 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2980 die "got unexpected qemu monitor banner\n";
2983 my $sel = new IO
::Select
;
2986 if (!scalar(my @ready = $sel->can_write($timeout))) {
2987 die "monitor write error - timeout";
2990 my $fullcmd = "$cmdstr\r";
2992 # syslog('info', "VM $vmid monitor command: $cmdstr");
2995 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2996 die "monitor write error - $!";
2999 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3003 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3004 $timeout = 60*60; # 1 hour
3005 } elsif ($cmdstr =~ m/^(eject|change)/) {
3006 $timeout = 60; # note: cdrom mount command is slow
3008 if ($res = __read_avail
($sock, $timeout)) {
3010 my @lines = split("\r?\n", $res);
3012 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3014 $res = join("\n", @lines);
3022 syslog
("err", "VM $vmid monitor command failed - $err");
3029 sub qemu_block_resize
{
3030 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3032 my $running = check_running
($vmid);
3034 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3036 return if !$running;
3038 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3042 sub qemu_volume_snapshot
{
3043 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3045 my $running = check_running
($vmid);
3047 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3049 return if !$running;
3051 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3055 sub qemu_volume_snapshot_delete
{
3056 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3058 my $running = check_running
($vmid);
3060 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3062 return if !$running;
3064 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3070 #need to impplement call to qemu-ga
3073 sub qga_unfreezefs
{
3076 #need to impplement call to qemu-ga
3080 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3082 lock_config
($vmid, sub {
3083 my $conf = load_config
($vmid, $migratedfrom);
3085 die "you can't start a vm if it's a template\n" if is_template
($conf);
3087 check_lock
($conf) if !$skiplock;
3089 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3091 my $defaults = load_defaults
();
3093 # set environment variable useful inside network script
3094 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3096 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3098 my $migrate_port = 0;
3101 if ($statefile eq 'tcp') {
3102 my $localip = "localhost";
3103 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3104 if ($datacenterconf->{migration_unsecure
}) {
3105 my $nodename = PVE
::INotify
::nodename
();
3106 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3108 $migrate_port = PVE
::Tools
::next_migrate_port
();
3109 $migrate_uri = "tcp:${localip}:${migrate_port}";
3110 push @$cmd, '-incoming', $migrate_uri;
3113 push @$cmd, '-loadstate', $statefile;
3120 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3121 my $d = parse_hostpci
($conf->{"hostpci$i"});
3123 my $info = pci_device_info
("0000:$d->{pciid}");
3124 die "IOMMU not present\n" if !check_iommu_support
();
3125 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3126 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3127 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3130 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3132 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3135 die "start failed: $err" if $err;
3137 print "migration listens on $migrate_uri\n" if $migrate_uri;
3139 if ($statefile && $statefile ne 'tcp') {
3140 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3144 if ($migratedfrom) {
3145 my $capabilities = {};
3146 $capabilities->{capability
} = "xbzrle";
3147 $capabilities->{state} = JSON
::true
;
3148 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
3152 print "spice listens on port $spice_port\n";
3153 if ($spice_ticket) {
3154 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3155 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3161 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3162 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3163 if $conf->{balloon
};
3164 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3165 path
=> "machine/peripheral/balloon0",
3166 property
=> "guest-stats-polling-interval",
3174 my ($vmid, $execute, %params) = @_;
3176 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3177 vm_qmp_command
($vmid, $cmd);
3180 sub vm_mon_cmd_nocheck
{
3181 my ($vmid, $execute, %params) = @_;
3183 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3184 vm_qmp_command
($vmid, $cmd, 1);
3187 sub vm_qmp_command
{
3188 my ($vmid, $cmd, $nocheck) = @_;
3193 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3194 $timeout = $cmd->{arguments
}->{timeout
};
3195 delete $cmd->{arguments
}->{timeout
};
3199 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3200 my $sname = qmp_socket
($vmid);
3202 my $qmpclient = PVE
::QMPClient-
>new();
3204 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3205 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3206 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3207 if scalar(%{$cmd->{arguments
}});
3208 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3210 die "unable to open monitor socket\n";
3214 syslog
("err", "VM $vmid qmp command failed - $err");
3221 sub vm_human_monitor_command
{
3222 my ($vmid, $cmdline) = @_;
3227 execute
=> 'human-monitor-command',
3228 arguments
=> { 'command-line' => $cmdline},
3231 return vm_qmp_command
($vmid, $cmd);
3234 sub vm_commandline
{
3235 my ($storecfg, $vmid) = @_;
3237 my $conf = load_config
($vmid);
3239 my $defaults = load_defaults
();
3241 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3243 return join(' ', @$cmd);
3247 my ($vmid, $skiplock) = @_;
3249 lock_config
($vmid, sub {
3251 my $conf = load_config
($vmid);
3253 check_lock
($conf) if !$skiplock;
3255 vm_mon_cmd
($vmid, "system_reset");
3259 sub get_vm_volumes
{
3263 foreach_volid
($conf, sub {
3264 my ($volid, $is_cdrom) = @_;
3266 return if $volid =~ m
|^/|;
3268 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3271 push @$vollist, $volid;
3277 sub vm_stop_cleanup
{
3278 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3281 fairsched_rmnod
($vmid); # try to destroy group
3284 my $vollist = get_vm_volumes
($conf);
3285 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3288 foreach my $ext (qw(mon qmp pid vnc qga)) {
3289 unlink "/var/run/qemu-server/${vmid}.$ext";
3292 warn $@ if $@; # avoid errors - just warn
3295 # Note: use $nockeck to skip tests if VM configuration file exists.
3296 # We need that when migration VMs to other nodes (files already moved)
3297 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3299 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3301 $force = 1 if !defined($force) && !$shutdown;
3304 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3305 kill 15, $pid if $pid;
3306 my $conf = load_config
($vmid, $migratedfrom);
3307 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3311 lock_config
($vmid, sub {
3313 my $pid = check_running
($vmid, $nocheck);
3318 $conf = load_config
($vmid);
3319 check_lock
($conf) if !$skiplock;
3320 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3321 my $opts = parse_startup
($conf->{startup
});
3322 $timeout = $opts->{down
} if $opts->{down
};
3326 $timeout = 60 if !defined($timeout);
3330 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3333 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3340 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3345 if ($count >= $timeout) {
3347 warn "VM still running - terminating now with SIGTERM\n";
3350 die "VM quit/powerdown failed - got timeout\n";
3353 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3358 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3361 die "VM quit/powerdown failed\n";
3369 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3374 if ($count >= $timeout) {
3375 warn "VM still running - terminating now with SIGKILL\n";
3380 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3385 my ($vmid, $skiplock) = @_;
3387 lock_config
($vmid, sub {
3389 my $conf = load_config
($vmid);
3391 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3393 vm_mon_cmd
($vmid, "stop");
3398 my ($vmid, $skiplock) = @_;
3400 lock_config
($vmid, sub {
3402 my $conf = load_config
($vmid);
3404 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3406 vm_mon_cmd
($vmid, "cont");
3411 my ($vmid, $skiplock, $key) = @_;
3413 lock_config
($vmid, sub {
3415 my $conf = load_config
($vmid);
3417 # there is no qmp command, so we use the human monitor command
3418 vm_human_monitor_command
($vmid, "sendkey $key");
3423 my ($storecfg, $vmid, $skiplock) = @_;
3425 lock_config
($vmid, sub {
3427 my $conf = load_config
($vmid);
3429 check_lock
($conf) if !$skiplock;
3431 if (!check_running
($vmid)) {
3432 fairsched_rmnod
($vmid); # try to destroy group
3433 destroy_vm
($storecfg, $vmid);
3435 die "VM $vmid is running - destroy failed\n";
3443 my ($filename, $buf) = @_;
3445 my $fh = IO
::File-
>new($filename, "w");
3446 return undef if !$fh;
3448 my $res = print $fh $buf;
3455 sub pci_device_info
{
3460 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3461 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3463 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3464 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3466 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3467 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3469 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3470 return undef if !defined($product) || $product !~ s/^0x//;
3475 product
=> $product,
3481 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3490 my $name = $dev->{name
};
3492 my $fn = "$pcisysfs/devices/$name/reset";
3494 return file_write
($fn, "1");
3497 sub pci_dev_bind_to_stub
{
3500 my $name = $dev->{name
};
3502 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3503 return 1 if -d
$testdir;
3505 my $data = "$dev->{vendor} $dev->{product}";
3506 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3508 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3509 if (!file_write
($fn, $name)) {
3510 return undef if -f
$fn;
3513 $fn = "$pcisysfs/drivers/pci-stub/bind";
3514 if (! -d
$testdir) {
3515 return undef if !file_write
($fn, $name);
3521 sub print_pci_addr
{
3522 my ($id, $bridges) = @_;
3526 piix3
=> { bus
=> 0, addr
=> 1 },
3527 #addr2 : first videocard
3528 balloon0
=> { bus
=> 0, addr
=> 3 },
3529 watchdog
=> { bus
=> 0, addr
=> 4 },
3530 scsihw0
=> { bus
=> 0, addr
=> 5 },
3531 scsihw1
=> { bus
=> 0, addr
=> 6 },
3532 ahci0
=> { bus
=> 0, addr
=> 7 },
3533 qga0
=> { bus
=> 0, addr
=> 8 },
3534 spice
=> { bus
=> 0, addr
=> 9 },
3535 virtio0
=> { bus
=> 0, addr
=> 10 },
3536 virtio1
=> { bus
=> 0, addr
=> 11 },
3537 virtio2
=> { bus
=> 0, addr
=> 12 },
3538 virtio3
=> { bus
=> 0, addr
=> 13 },
3539 virtio4
=> { bus
=> 0, addr
=> 14 },
3540 virtio5
=> { bus
=> 0, addr
=> 15 },
3541 hostpci0
=> { bus
=> 0, addr
=> 16 },
3542 hostpci1
=> { bus
=> 0, addr
=> 17 },
3543 net0
=> { bus
=> 0, addr
=> 18 },
3544 net1
=> { bus
=> 0, addr
=> 19 },
3545 net2
=> { bus
=> 0, addr
=> 20 },
3546 net3
=> { bus
=> 0, addr
=> 21 },
3547 net4
=> { bus
=> 0, addr
=> 22 },
3548 net5
=> { bus
=> 0, addr
=> 23 },
3549 vga1
=> { bus
=> 0, addr
=> 24 },
3550 vga2
=> { bus
=> 0, addr
=> 25 },
3551 vga3
=> { bus
=> 0, addr
=> 26 },
3552 #addr29 : usb-host (pve-usb.cfg)
3553 'pci.1' => { bus
=> 0, addr
=> 30 },
3554 'pci.2' => { bus
=> 0, addr
=> 31 },
3555 'net6' => { bus
=> 1, addr
=> 1 },
3556 'net7' => { bus
=> 1, addr
=> 2 },
3557 'net8' => { bus
=> 1, addr
=> 3 },
3558 'net9' => { bus
=> 1, addr
=> 4 },
3559 'net10' => { bus
=> 1, addr
=> 5 },
3560 'net11' => { bus
=> 1, addr
=> 6 },
3561 'net12' => { bus
=> 1, addr
=> 7 },
3562 'net13' => { bus
=> 1, addr
=> 8 },
3563 'net14' => { bus
=> 1, addr
=> 9 },
3564 'net15' => { bus
=> 1, addr
=> 10 },
3565 'net16' => { bus
=> 1, addr
=> 11 },
3566 'net17' => { bus
=> 1, addr
=> 12 },
3567 'net18' => { bus
=> 1, addr
=> 13 },
3568 'net19' => { bus
=> 1, addr
=> 14 },
3569 'net20' => { bus
=> 1, addr
=> 15 },
3570 'net21' => { bus
=> 1, addr
=> 16 },
3571 'net22' => { bus
=> 1, addr
=> 17 },
3572 'net23' => { bus
=> 1, addr
=> 18 },
3573 'net24' => { bus
=> 1, addr
=> 19 },
3574 'net25' => { bus
=> 1, addr
=> 20 },
3575 'net26' => { bus
=> 1, addr
=> 21 },
3576 'net27' => { bus
=> 1, addr
=> 22 },
3577 'net28' => { bus
=> 1, addr
=> 23 },
3578 'net29' => { bus
=> 1, addr
=> 24 },
3579 'net30' => { bus
=> 1, addr
=> 25 },
3580 'net31' => { bus
=> 1, addr
=> 26 },
3581 'virtio6' => { bus
=> 2, addr
=> 1 },
3582 'virtio7' => { bus
=> 2, addr
=> 2 },
3583 'virtio8' => { bus
=> 2, addr
=> 3 },
3584 'virtio9' => { bus
=> 2, addr
=> 4 },
3585 'virtio10' => { bus
=> 2, addr
=> 5 },
3586 'virtio11' => { bus
=> 2, addr
=> 6 },
3587 'virtio12' => { bus
=> 2, addr
=> 7 },
3588 'virtio13' => { bus
=> 2, addr
=> 8 },
3589 'virtio14' => { bus
=> 2, addr
=> 9 },
3590 'virtio15' => { bus
=> 2, addr
=> 10 },
3593 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3594 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3595 my $bus = $devices->{$id}->{bus
};
3596 $res = ",bus=pci.$bus,addr=$addr";
3597 $bridges->{$bus} = 1 if $bridges;
3603 # vzdump restore implementaion
3605 sub tar_archive_read_firstfile
{
3606 my $archive = shift;
3608 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3610 # try to detect archive type first
3611 my $pid = open (TMP
, "tar tf '$archive'|") ||
3612 die "unable to open file '$archive'\n";
3613 my $firstfile = <TMP
>;
3617 die "ERROR: archive contaions no data\n" if !$firstfile;
3623 sub tar_restore_cleanup
{
3624 my ($storecfg, $statfile) = @_;
3626 print STDERR
"starting cleanup\n";
3628 if (my $fd = IO
::File-
>new($statfile, "r")) {
3629 while (defined(my $line = <$fd>)) {
3630 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3633 if ($volid =~ m
|^/|) {
3634 unlink $volid || die 'unlink failed\n';
3636 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3638 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3640 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3642 print STDERR
"unable to parse line in statfile - $line";
3649 sub restore_archive
{
3650 my ($archive, $vmid, $user, $opts) = @_;
3652 my $format = $opts->{format
};
3655 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3656 $format = 'tar' if !$format;
3658 } elsif ($archive =~ m/\.tar$/) {
3659 $format = 'tar' if !$format;
3660 } elsif ($archive =~ m/.tar.lzo$/) {
3661 $format = 'tar' if !$format;
3663 } elsif ($archive =~ m/\.vma$/) {
3664 $format = 'vma' if !$format;
3665 } elsif ($archive =~ m/\.vma\.gz$/) {
3666 $format = 'vma' if !$format;
3668 } elsif ($archive =~ m/\.vma\.lzo$/) {
3669 $format = 'vma' if !$format;
3672 $format = 'vma' if !$format; # default
3675 # try to detect archive format
3676 if ($format eq 'tar') {
3677 return restore_tar_archive
($archive, $vmid, $user, $opts);
3679 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3683 sub restore_update_config_line
{
3684 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3686 return if $line =~ m/^\#qmdump\#/;
3687 return if $line =~ m/^\#vzdump\#/;
3688 return if $line =~ m/^lock:/;
3689 return if $line =~ m/^unused\d+:/;
3690 return if $line =~ m/^parent:/;
3691 return if $line =~ m/^template:/; # restored VM is never a template
3693 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3694 # try to convert old 1.X settings
3695 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3696 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3697 my ($model, $macaddr) = split(/\=/, $devconfig);
3698 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3701 bridge
=> "vmbr$ind",
3702 macaddr
=> $macaddr,
3704 my $netstr = print_net
($net);
3706 print $outfd "net$cookie->{netcount}: $netstr\n";
3707 $cookie->{netcount
}++;
3709 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3710 my ($id, $netstr) = ($1, $2);
3711 my $net = parse_net
($netstr);
3712 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3713 $netstr = print_net
($net);
3714 print $outfd "$id: $netstr\n";
3715 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3718 if ($line =~ m/backup=no/) {
3719 print $outfd "#$line";
3720 } elsif ($virtdev && $map->{$virtdev}) {
3721 my $di = parse_drive
($virtdev, $value);
3722 delete $di->{format
}; # format can change on restore
3723 $di->{file
} = $map->{$virtdev};
3724 $value = print_drive
($vmid, $di);
3725 print $outfd "$virtdev: $value\n";
3735 my ($cfg, $vmid) = @_;
3737 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3739 my $volid_hash = {};
3740 foreach my $storeid (keys %$info) {
3741 foreach my $item (@{$info->{$storeid}}) {
3742 next if !($item->{volid
} && $item->{size
});
3743 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3744 $volid_hash->{$item->{volid
}} = $item;
3751 sub get_used_paths
{
3752 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3756 my $scan_config = sub {
3757 my ($cref, $snapname) = @_;
3759 foreach my $key (keys %$cref) {
3760 my $value = $cref->{$key};
3761 if (valid_drivename
($key)) {
3762 next if $skip_drive && $key eq $skip_drive;
3763 my $drive = parse_drive
($key, $value);
3764 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3765 if ($drive->{file
} =~ m!^/!) {
3766 $used_path->{$drive->{file
}}++; # = 1;
3768 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3770 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3772 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3773 $used_path->{$path}++; # = 1;
3779 &$scan_config($conf);
3783 if ($scan_snapshots) {
3784 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3785 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3792 sub update_disksize
{
3793 my ($vmid, $conf, $volid_hash) = @_;
3799 # Note: it is allowed to define multiple storages with same path (alias), so
3800 # we need to check both 'volid' and real 'path' (two different volid can point
3801 # to the same path).
3806 foreach my $opt (keys %$conf) {
3807 if (valid_drivename
($opt)) {
3808 my $drive = parse_drive
($opt, $conf->{$opt});
3809 my $volid = $drive->{file
};
3812 $used->{$volid} = 1;
3813 if ($volid_hash->{$volid} &&
3814 (my $path = $volid_hash->{$volid}->{path
})) {
3815 $usedpath->{$path} = 1;
3818 next if drive_is_cdrom
($drive);
3819 next if !$volid_hash->{$volid};
3821 $drive->{size
} = $volid_hash->{$volid}->{size
};
3822 my $new = print_drive
($vmid, $drive);
3823 if ($new ne $conf->{$opt}) {
3825 $conf->{$opt} = $new;
3830 # remove 'unusedX' entry if volume is used
3831 foreach my $opt (keys %$conf) {
3832 next if $opt !~ m/^unused\d+$/;
3833 my $volid = $conf->{$opt};
3834 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3835 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3837 delete $conf->{$opt};
3841 foreach my $volid (sort keys %$volid_hash) {
3842 next if $volid =~ m/vm-$vmid-state-/;
3843 next if $used->{$volid};
3844 my $path = $volid_hash->{$volid}->{path
};
3845 next if !$path; # just to be sure
3846 next if $usedpath->{$path};
3848 add_unused_volume
($conf, $volid);
3849 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3856 my ($vmid, $nolock) = @_;
3858 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3860 my $volid_hash = scan_volids
($cfg, $vmid);
3862 my $updatefn = sub {
3865 my $conf = load_config
($vmid);
3870 foreach my $volid (keys %$volid_hash) {
3871 my $info = $volid_hash->{$volid};
3872 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3875 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3877 update_config_nolock
($vmid, $conf, 1) if $changes;
3880 if (defined($vmid)) {
3884 lock_config
($vmid, $updatefn, $vmid);
3887 my $vmlist = config_list
();
3888 foreach my $vmid (keys %$vmlist) {
3892 lock_config
($vmid, $updatefn, $vmid);
3898 sub restore_vma_archive
{
3899 my ($archive, $vmid, $user, $opts, $comp) = @_;
3901 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3902 my $readfrom = $archive;
3907 my $qarchive = PVE
::Tools
::shellquote
($archive);
3908 if ($comp eq 'gzip') {
3909 $uncomp = "zcat $qarchive|";
3910 } elsif ($comp eq 'lzop') {
3911 $uncomp = "lzop -d -c $qarchive|";
3913 die "unknown compression method '$comp'\n";
3918 my $tmpdir = "/var/tmp/vzdumptmp$$";
3921 # disable interrupts (always do cleanups)
3922 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3923 warn "got interrupt - ignored\n";
3926 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3927 POSIX
::mkfifo
($mapfifo, 0600);
3930 my $openfifo = sub {
3931 open($fifofh, '>', $mapfifo) || die $!;
3934 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3941 my $rpcenv = PVE
::RPCEnvironment
::get
();
3943 my $conffile = config_file
($vmid);
3944 my $tmpfn = "$conffile.$$.tmp";
3946 # Note: $oldconf is undef if VM does not exists
3947 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3949 my $print_devmap = sub {
3950 my $virtdev_hash = {};
3952 my $cfgfn = "$tmpdir/qemu-server.conf";
3954 # we can read the config - that is already extracted
3955 my $fh = IO
::File-
>new($cfgfn, "r") ||
3956 "unable to read qemu-server.conf - $!\n";
3958 while (defined(my $line = <$fh>)) {
3959 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3960 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3961 die "archive does not contain data for drive '$virtdev'\n"
3962 if !$devinfo->{$devname};
3963 if (defined($opts->{storage
})) {
3964 $storeid = $opts->{storage
} || 'local';
3965 } elsif (!$storeid) {
3968 $format = 'raw' if !$format;
3969 $devinfo->{$devname}->{devname
} = $devname;
3970 $devinfo->{$devname}->{virtdev
} = $virtdev;
3971 $devinfo->{$devname}->{format
} = $format;
3972 $devinfo->{$devname}->{storeid
} = $storeid;
3974 # check permission on storage
3975 my $pool = $opts->{pool
}; # todo: do we need that?
3976 if ($user ne 'root@pam') {
3977 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3980 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3984 foreach my $devname (keys %$devinfo) {
3985 die "found no device mapping information for device '$devname'\n"
3986 if !$devinfo->{$devname}->{virtdev
};
3989 my $cfg = cfs_read_file
('storage.cfg');
3991 # create empty/temp config
3993 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3994 foreach_drive
($oldconf, sub {
3995 my ($ds, $drive) = @_;
3997 return if drive_is_cdrom
($drive);
3999 my $volid = $drive->{file
};
4001 return if !$volid || $volid =~ m
|^/|;
4003 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
4004 return if !$path || !$owner || ($owner != $vmid);
4006 # Note: only delete disk we want to restore
4007 # other volumes will become unused
4008 if ($virtdev_hash->{$ds}) {
4009 PVE
::Storage
::vdisk_free
($cfg, $volid);
4015 foreach my $virtdev (sort keys %$virtdev_hash) {
4016 my $d = $virtdev_hash->{$virtdev};
4017 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
4018 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
4020 # test if requested format is supported
4021 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
4022 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
4023 $d->{format
} = $defFormat if !$supported;
4025 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
4026 $d->{format
}, undef, $alloc_size);
4027 print STDERR
"new volume ID is '$volid'\n";
4028 $d->{volid
} = $volid;
4029 my $path = PVE
::Storage
::path
($cfg, $volid);
4031 my $write_zeros = 1;
4032 # fixme: what other storages types initialize volumes with zero?
4033 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
4034 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4038 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4040 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4041 $map->{$virtdev} = $volid;
4044 $fh->seek(0, 0) || die "seek failed - $!\n";
4046 my $outfd = new IO
::File
($tmpfn, "w") ||
4047 die "unable to write config for VM $vmid\n";
4049 my $cookie = { netcount
=> 0 };
4050 while (defined(my $line = <$fh>)) {
4051 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4060 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4061 die "interrupted by signal\n";
4063 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4065 $oldtimeout = alarm($timeout);
4072 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4073 my ($dev_id, $size, $devname) = ($1, $2, $3);
4074 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4075 } elsif ($line =~ m/^CTIME: /) {
4077 print $fifofh "done\n";
4078 my $tmp = $oldtimeout || 0;
4079 $oldtimeout = undef;
4085 print "restore vma archive: $cmd\n";
4086 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4090 alarm($oldtimeout) if $oldtimeout;
4098 my $cfg = cfs_read_file
('storage.cfg');
4099 foreach my $devname (keys %$devinfo) {
4100 my $volid = $devinfo->{$devname}->{volid
};
4103 if ($volid =~ m
|^/|) {
4104 unlink $volid || die 'unlink failed\n';
4106 PVE
::Storage
::vdisk_free
($cfg, $volid);
4108 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4110 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4117 rename($tmpfn, $conffile) ||
4118 die "unable to commit configuration file '$conffile'\n";
4120 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4122 eval { rescan
($vmid, 1); };
4126 sub restore_tar_archive
{
4127 my ($archive, $vmid, $user, $opts) = @_;
4129 if ($archive ne '-') {
4130 my $firstfile = tar_archive_read_firstfile
($archive);
4131 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4132 if $firstfile ne 'qemu-server.conf';
4135 my $storecfg = cfs_read_file
('storage.cfg');
4137 # destroy existing data - keep empty config
4138 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4139 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4141 my $tocmd = "/usr/lib/qemu-server/qmextract";
4143 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4144 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4145 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4146 $tocmd .= ' --info' if $opts->{info
};
4148 # tar option "xf" does not autodetect compression when read from STDIN,
4149 # so we pipe to zcat
4150 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4151 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4153 my $tmpdir = "/var/tmp/vzdumptmp$$";
4156 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4157 local $ENV{VZDUMP_VMID
} = $vmid;
4158 local $ENV{VZDUMP_USER
} = $user;
4160 my $conffile = config_file
($vmid);
4161 my $tmpfn = "$conffile.$$.tmp";
4163 # disable interrupts (always do cleanups)
4164 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4165 print STDERR
"got interrupt - ignored\n";
4170 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4171 die "interrupted by signal\n";
4174 if ($archive eq '-') {
4175 print "extracting archive from STDIN\n";
4176 run_command
($cmd, input
=> "<&STDIN");
4178 print "extracting archive '$archive'\n";
4182 return if $opts->{info
};
4186 my $statfile = "$tmpdir/qmrestore.stat";
4187 if (my $fd = IO
::File-
>new($statfile, "r")) {
4188 while (defined (my $line = <$fd>)) {
4189 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4190 $map->{$1} = $2 if $1;
4192 print STDERR
"unable to parse line in statfile - $line\n";
4198 my $confsrc = "$tmpdir/qemu-server.conf";
4200 my $srcfd = new IO
::File
($confsrc, "r") ||
4201 die "unable to open file '$confsrc'\n";
4203 my $outfd = new IO
::File
($tmpfn, "w") ||
4204 die "unable to write config for VM $vmid\n";
4206 my $cookie = { netcount
=> 0 };
4207 while (defined (my $line = <$srcfd>)) {
4208 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4220 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4227 rename $tmpfn, $conffile ||
4228 die "unable to commit configuration file '$conffile'\n";
4230 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4232 eval { rescan
($vmid, 1); };
4237 # Internal snapshots
4239 # NOTE: Snapshot create/delete involves several non-atomic
4240 # action, and can take a long time.
4241 # So we try to avoid locking the file and use 'lock' variable
4242 # inside the config file instead.
4244 my $snapshot_copy_config = sub {
4245 my ($source, $dest) = @_;
4247 foreach my $k (keys %$source) {
4248 next if $k eq 'snapshots';
4249 next if $k eq 'snapstate';
4250 next if $k eq 'snaptime';
4251 next if $k eq 'vmstate';
4252 next if $k eq 'lock';
4253 next if $k eq 'digest';
4254 next if $k eq 'description';
4255 next if $k =~ m/^unused\d+$/;
4257 $dest->{$k} = $source->{$k};
4261 my $snapshot_apply_config = sub {
4262 my ($conf, $snap) = @_;
4264 # copy snapshot list
4266 snapshots
=> $conf->{snapshots
},
4269 # keep description and list of unused disks
4270 foreach my $k (keys %$conf) {
4271 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4272 $newconf->{$k} = $conf->{$k};
4275 &$snapshot_copy_config($snap, $newconf);
4280 sub foreach_writable_storage
{
4281 my ($conf, $func) = @_;
4285 foreach my $ds (keys %$conf) {
4286 next if !valid_drivename
($ds);
4288 my $drive = parse_drive
($ds, $conf->{$ds});
4290 next if drive_is_cdrom
($drive);
4292 my $volid = $drive->{file
};
4294 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4295 $sidhash->{$sid} = $sid if $sid;
4298 foreach my $sid (sort keys %$sidhash) {
4303 my $alloc_vmstate_volid = sub {
4304 my ($storecfg, $vmid, $conf, $snapname) = @_;
4306 # Note: we try to be smart when selecting a $target storage
4310 # search shared storage first
4311 foreach_writable_storage
($conf, sub {
4313 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4314 return if !$scfg->{shared
};
4316 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4320 # now search local storage
4321 foreach_writable_storage
($conf, sub {
4323 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4324 return if $scfg->{shared
};
4326 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4330 $target = 'local' if !$target;
4332 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4333 # we abort live save after $conf->{memory}, so we need at max twice that space
4334 my $size = $conf->{memory
}*2 + $driver_state_size;
4336 my $name = "vm-$vmid-state-$snapname";
4337 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4338 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4339 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4344 my $snapshot_prepare = sub {
4345 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4349 my $updatefn = sub {
4351 my $conf = load_config
($vmid);
4353 die "you can't take a snapshot if it's a template\n"
4354 if is_template
($conf);
4358 $conf->{lock} = 'snapshot';
4360 die "snapshot name '$snapname' already used\n"
4361 if defined($conf->{snapshots
}->{$snapname});
4363 my $storecfg = PVE
::Storage
::config
();
4364 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4366 $snap = $conf->{snapshots
}->{$snapname} = {};
4368 if ($save_vmstate && check_running
($vmid)) {
4369 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4372 &$snapshot_copy_config($conf, $snap);
4374 $snap->{snapstate
} = "prepare";
4375 $snap->{snaptime
} = time();
4376 $snap->{description
} = $comment if $comment;
4378 # always overwrite machine if we save vmstate. This makes sure we
4379 # can restore it later using correct machine type
4380 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4382 update_config_nolock
($vmid, $conf, 1);
4385 lock_config
($vmid, $updatefn);
4390 my $snapshot_commit = sub {
4391 my ($vmid, $snapname) = @_;
4393 my $updatefn = sub {
4395 my $conf = load_config
($vmid);
4397 die "missing snapshot lock\n"
4398 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4400 my $snap = $conf->{snapshots
}->{$snapname};
4402 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4404 die "wrong snapshot state\n"
4405 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4407 delete $snap->{snapstate
};
4408 delete $conf->{lock};
4410 my $newconf = &$snapshot_apply_config($conf, $snap);
4412 $newconf->{parent
} = $snapname;
4414 update_config_nolock
($vmid, $newconf, 1);
4417 lock_config
($vmid, $updatefn);
4420 sub snapshot_rollback
{
4421 my ($vmid, $snapname) = @_;
4427 my $storecfg = PVE
::Storage
::config
();
4429 my $updatefn = sub {
4431 my $conf = load_config
($vmid);
4433 die "you can't rollback if vm is a template\n" if is_template
($conf);
4435 $snap = $conf->{snapshots
}->{$snapname};
4437 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4439 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4440 if $snap->{snapstate
};
4444 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4447 die "unable to rollback vm $vmid: vm is running\n"
4448 if check_running
($vmid);
4451 $conf->{lock} = 'rollback';
4453 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4454 delete $conf->{lock};
4460 my $has_machine_config = defined($conf->{machine
});
4462 # copy snapshot config to current config
4463 $conf = &$snapshot_apply_config($conf, $snap);
4464 $conf->{parent
} = $snapname;
4466 # Note: old code did not store 'machine', so we try to be smart
4467 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4468 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4469 # we remove the 'machine' configuration if not explicitly specified
4470 # in the original config.
4471 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4474 update_config_nolock
($vmid, $conf, 1);
4476 if (!$prepare && $snap->{vmstate
}) {
4477 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4478 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4482 lock_config
($vmid, $updatefn);
4484 foreach_drive
($snap, sub {
4485 my ($ds, $drive) = @_;
4487 return if drive_is_cdrom
($drive);
4489 my $volid = $drive->{file
};
4490 my $device = "drive-$ds";
4492 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4496 lock_config
($vmid, $updatefn);
4499 my $savevm_wait = sub {
4503 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4504 if (!$stat->{status
}) {
4505 die "savevm not active\n";
4506 } elsif ($stat->{status
} eq 'active') {
4509 } elsif ($stat->{status
} eq 'completed') {
4512 die "query-savevm returned status '$stat->{status}'\n";
4517 sub snapshot_create
{
4518 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4520 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4522 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4526 my $running = check_running
($vmid);
4529 # create internal snapshots of all drives
4531 my $storecfg = PVE
::Storage
::config
();
4534 if ($snap->{vmstate
}) {
4535 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4536 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4537 &$savevm_wait($vmid);
4539 vm_mon_cmd
($vmid, "savevm-start");
4543 qga_freezefs
($vmid) if $running && $freezefs;
4545 foreach_drive
($snap, sub {
4546 my ($ds, $drive) = @_;
4548 return if drive_is_cdrom
($drive);
4550 my $volid = $drive->{file
};
4551 my $device = "drive-$ds";
4553 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4554 $drivehash->{$ds} = 1;
4559 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4562 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4566 warn "snapshot create failed: starting cleanup\n";
4567 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4572 &$snapshot_commit($vmid, $snapname);
4575 # Note: $drivehash is only set when called from snapshot_create.
4576 sub snapshot_delete
{
4577 my ($vmid, $snapname, $force, $drivehash) = @_;
4584 my $unlink_parent = sub {
4585 my ($confref, $new_parent) = @_;
4587 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4589 $confref->{parent
} = $new_parent;
4591 delete $confref->{parent
};
4596 my $updatefn = sub {
4597 my ($remove_drive) = @_;
4599 my $conf = load_config
($vmid);
4603 die "you can't delete a snapshot if vm is a template\n"
4604 if is_template
($conf);
4607 $snap = $conf->{snapshots
}->{$snapname};
4609 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4611 # remove parent refs
4612 &$unlink_parent($conf, $snap->{parent
});
4613 foreach my $sn (keys %{$conf->{snapshots
}}) {
4614 next if $sn eq $snapname;
4615 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4618 if ($remove_drive) {
4619 if ($remove_drive eq 'vmstate') {
4620 delete $snap->{$remove_drive};
4622 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4623 my $volid = $drive->{file
};
4624 delete $snap->{$remove_drive};
4625 add_unused_volume
($conf, $volid);
4630 $snap->{snapstate
} = 'delete';
4632 delete $conf->{snapshots
}->{$snapname};
4633 delete $conf->{lock} if $drivehash;
4634 foreach my $volid (@$unused) {
4635 add_unused_volume
($conf, $volid);
4639 update_config_nolock
($vmid, $conf, 1);
4642 lock_config
($vmid, $updatefn);
4644 # now remove vmstate file
4646 my $storecfg = PVE
::Storage
::config
();
4648 if ($snap->{vmstate
}) {
4649 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4651 die $err if !$force;
4654 # save changes (remove vmstate from snapshot)
4655 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4658 # now remove all internal snapshots
4659 foreach_drive
($snap, sub {
4660 my ($ds, $drive) = @_;
4662 return if drive_is_cdrom
($drive);
4664 my $volid = $drive->{file
};
4665 my $device = "drive-$ds";
4667 if (!$drivehash || $drivehash->{$ds}) {
4668 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4670 die $err if !$force;
4675 # save changes (remove drive fron snapshot)
4676 lock_config
($vmid, $updatefn, $ds) if !$force;
4677 push @$unused, $volid;
4680 # now cleanup config
4682 lock_config
($vmid, $updatefn);
4686 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4689 foreach_drive
($conf, sub {
4690 my ($ds, $drive) = @_;
4692 return if drive_is_cdrom
($drive);
4693 my $volid = $drive->{file
};
4694 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4697 return $err ?
0 : 1;
4700 sub template_create
{
4701 my ($vmid, $conf, $disk) = @_;
4703 my $storecfg = PVE
::Storage
::config
();
4705 foreach_drive
($conf, sub {
4706 my ($ds, $drive) = @_;
4708 return if drive_is_cdrom
($drive);
4709 return if $disk && $ds ne $disk;
4711 my $volid = $drive->{file
};
4712 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4714 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4715 $drive->{file
} = $voliddst;
4716 $conf->{$ds} = print_drive
($vmid, $drive);
4717 update_config_nolock
($vmid, $conf, 1);
4724 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4727 sub qemu_img_convert
{
4728 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4730 my $storecfg = PVE
::Storage
::config
();
4731 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4732 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4734 if ($src_storeid && $dst_storeid) {
4735 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4736 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4738 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4739 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4741 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4742 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4745 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
4746 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4747 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4751 if($line =~ m/\((\S+)\/100\
%\)/){
4753 my $transferred = int($size * $percent / 100);
4754 my $remaining = $size - $transferred;
4756 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4761 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4763 die "copy failed: $err" if $err;
4767 sub qemu_img_format
{
4768 my ($scfg, $volname) = @_;
4770 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4772 } elsif ($scfg->{type
} eq 'iscsi') {
4773 return "host_device";
4779 sub qemu_drive_mirror
{
4780 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4786 my $storecfg = PVE
::Storage
::config
();
4787 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4790 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4793 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4797 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4800 #fixme : sometime drive-mirror timeout, but works fine after.
4801 # (I have see the problem with big volume > 200GB), so we need to eval
4802 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4803 sync
=> "full", target
=> $dst_path, format
=> $format); };
4805 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4806 sync
=> "full", target
=> $dst_path); };
4811 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4812 my $stat = @$stats[0];
4813 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4814 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4816 my $transferred = $stat->{offset
};
4817 my $total = $stat->{len
};
4818 my $remaining = $total - $transferred;
4819 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4821 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4823 last if ($stat->{len
} == $stat->{offset
});
4824 if ($old_len == $stat->{offset
}) {
4825 if ($maxwait && $count > $maxwait) {
4826 # if writes to disk occurs the disk needs to be freezed
4827 # to be able to complete the migration
4828 vm_suspend
($vmid,1);
4832 $count++ unless $frozen;
4838 $old_len = $stat->{offset
};
4842 if ($vmiddst == $vmid) {
4843 # switch the disk if source and destination are on the same guest
4844 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4848 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4849 die "mirroring error: $err";
4852 if ($vmiddst != $vmid) {
4853 # if we clone a disk for a new target vm, we don't switch the disk
4854 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4860 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4861 $newvmid, $storage, $format, $full, $newvollist) = @_;
4866 print "create linked clone of drive $drivename ($drive->{file})\n";
4867 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4868 push @$newvollist, $newvolid;
4870 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4871 $storeid = $storage if $storage;
4873 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4875 $format = $drive->{format
} || $defFormat;
4878 # test if requested format is supported - else use default
4879 my $supported = grep { $_ eq $format } @$validFormats;
4880 $format = $defFormat if !$supported;
4882 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4884 print "create full clone of drive $drivename ($drive->{file})\n";
4885 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4886 push @$newvollist, $newvolid;
4888 if (!$running || $snapname) {
4889 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4891 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4895 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4898 $disk->{format
} = undef;
4899 $disk->{file
} = $newvolid;
4900 $disk->{size
} = $size;
4905 # this only works if VM is running
4906 sub get_current_qemu_machine
{
4909 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4910 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4912 my ($current, $default);
4913 foreach my $e (@$res) {
4914 $default = $e->{name
} if $e->{'is-default'};
4915 $current = $e->{name
} if $e->{'is-current'};
4918 # fallback to the default machine if current is not supported by qemu
4919 return $current || $default || 'pc';
4922 sub read_x509_subject_spice
{
4923 my ($filename) = @_;
4926 my $bio = Net
::SSLeay
::BIO_new_file
($filename, 'r');
4927 my $x509 = Net
::SSLeay
::PEM_read_bio_X509
($bio);
4928 Net
::SSLeay
::BIO_free
($bio);
4929 my $nameobj = Net
::SSLeay
::X509_get_subject_name
($x509);
4930 my $subject = Net
::SSLeay
::X509_NAME_oneline
($nameobj);
4931 Net
::SSLeay
::X509_free
($x509);
4933 # remote-viewer wants comma as seperator (not '/')
4935 $subject =~ s!/(\w+=)!,$1!g;