1 package PVE
::QemuServer
;
21 use Storable
qw(dclone);
22 use PVE
::Exception
qw(raise raise_param_exc);
24 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline);
25 use PVE
::JSONSchema
qw(get_standard_option);
26 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
30 use PVE
::RPCEnvironment
;
31 use Time
::HiRes
qw(gettimeofday);
33 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
35 # Note about locking: we use flock on the config file protect
36 # against concurent actions.
37 # Aditionaly, we have a 'lock' setting in the config file. This
38 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
39 # allowed when such lock is set. But you can ignore this kind of
40 # lock with the --skiplock flag.
42 cfs_register_file
('/qemu-server/',
46 PVE
::JSONSchema
::register_standard_option
('skiplock', {
47 description
=> "Ignore locks - only root is allowed to use this option.",
52 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
53 description
=> "Some command save/restore state from this location.",
59 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
60 description
=> "The name of the snapshot.",
61 type
=> 'string', format
=> 'pve-configid',
65 #no warnings 'redefine';
67 unless(defined(&_VZSYSCALLS_H_
)) {
68 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
69 require 'sys/syscall.ph';
70 if(defined(&__x86_64__
)) {
71 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
72 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
73 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
74 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
75 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
76 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
77 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
78 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
80 elsif(defined( &__i386__
) ) {
81 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
82 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
83 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
84 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
85 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
86 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
87 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
88 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
90 die("no fairsched syscall for this arch");
92 require 'asm/ioctl.ph';
93 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
97 my ($parent, $weight, $desired) = @_;
99 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
102 sub fairsched_rmnod
{
105 return syscall(&__NR_fairsched_rmnod
, int($id));
109 my ($pid, $newid) = @_;
111 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
114 sub fairsched_vcpus
{
115 my ($id, $vcpus) = @_;
117 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
121 my ($id, $op, $rate) = @_;
123 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
126 use constant FAIRSCHED_SET_RATE
=> 0;
127 use constant FAIRSCHED_DROP_RATE
=> 1;
128 use constant FAIRSCHED_GET_RATE
=> 2;
130 sub fairsched_cpulimit
{
131 my ($id, $limit) = @_;
133 my $cpulim1024 = int($limit * 1024 / 100);
134 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
136 return fairsched_rate
($id, $op, $cpulim1024);
139 my $nodename = PVE
::INotify
::nodename
();
141 mkdir "/etc/pve/nodes/$nodename";
142 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
145 my $var_run_tmpdir = "/var/run/qemu-server";
146 mkdir $var_run_tmpdir;
148 my $lock_dir = "/var/lock/qemu-server";
151 my $pcisysfs = "/sys/bus/pci";
157 description
=> "Specifies whether a VM will be started during system bootup.",
163 description
=> "Automatic restart after crash (currently ignored).",
169 description
=> "Allow hotplug for disk and network device",
175 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
181 description
=> "Lock/unlock the VM.",
182 enum
=> [qw(migrate backup snapshot rollback)],
187 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
194 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
202 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
209 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
215 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
223 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
224 enum
=> PVE
::Tools
::kvmkeymaplist
(),
229 type
=> 'string', format
=> 'dns-name',
230 description
=> "Set a name for the VM. Only used on the configuration web interface.",
235 description
=> "scsi controller model",
236 enum
=> [qw(lsi virtio-scsi-pci megasas)],
242 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
247 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
248 description
=> <<EODESC,
249 Used to enable special optimization/features for specific
252 other => unspecified OS
253 wxp => Microsoft Windows XP
254 w2k => Microsoft Windows 2000
255 w2k3 => Microsoft Windows 2003
256 w2k8 => Microsoft Windows 2008
257 wvista => Microsoft Windows Vista
258 win7 => Microsoft Windows 7
259 win8 => Microsoft Windows 8/2012
260 l24 => Linux 2.4 Kernel
261 l26 => Linux 2.6/3.X Kernel
262 solaris => solaris/opensolaris/openindiania kernel
264 other|l24|l26|solaris ... no special behaviour
265 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
271 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
272 pattern
=> '[acdn]{1,4}',
277 type
=> 'string', format
=> 'pve-qm-bootdisk',
278 description
=> "Enable booting from specified disk.",
279 pattern
=> '(ide|sata|scsi|virtio)\d+',
284 description
=> "The number of CPUs. Please use option -sockets instead.",
291 description
=> "The number of CPU sockets.",
298 description
=> "The number of cores per socket.",
305 description
=> "Enable/disable ACPI.",
311 description
=> "Enable/disable Qemu GuestAgent.",
317 description
=> "Enable/disable KVM hardware virtualization.",
323 description
=> "Enable/disable time drift fix.",
329 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
334 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
339 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.",
340 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3)],
344 type
=> 'string', format
=> 'pve-qm-watchdog',
345 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
346 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)",
351 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
352 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'.",
353 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
358 type
=> 'string', format
=> 'pve-qm-startup',
359 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
360 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.",
365 description
=> "Enable/disable Template.",
371 description
=> <<EODESCR,
372 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
374 args: -no-reboot -no-hpet
381 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).",
386 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
390 migrate_downtime
=> {
393 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
399 type
=> 'string', format
=> 'pve-qm-drive',
400 typetext
=> 'volume',
401 description
=> "This is an alias for option -ide2",
405 description
=> "Emulated CPU type.",
407 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) ],
410 parent
=> get_standard_option
('pve-snapshot-name', {
412 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
416 description
=> "Timestamp for snapshots.",
422 type
=> 'string', format
=> 'pve-volume-id',
423 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
426 description
=> "Specific the Qemu machine type.",
428 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
434 # what about other qemu settings ?
436 #machine => 'string',
449 ##soundhw => 'string',
451 while (my ($k, $v) = each %$confdesc) {
452 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
455 my $MAX_IDE_DISKS = 4;
456 my $MAX_SCSI_DISKS = 14;
457 my $MAX_VIRTIO_DISKS = 16;
458 my $MAX_SATA_DISKS = 6;
459 my $MAX_USB_DEVICES = 5;
461 my $MAX_UNUSED_DISKS = 8;
462 my $MAX_HOSTPCI_DEVICES = 2;
463 my $MAX_SERIAL_PORTS = 4;
464 my $MAX_PARALLEL_PORTS = 3;
466 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
467 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
468 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
472 type
=> 'string', format
=> 'pve-qm-net',
473 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
474 description
=> <<EODESCR,
475 Specify network devices.
477 MODEL is one of: $nic_model_list_txt
479 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
480 automatically generated if not specified.
482 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
484 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'.
486 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
492 The DHCP server assign addresses to the guest starting from 10.0.2.15.
496 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
498 for (my $i = 0; $i < $MAX_NETS; $i++) {
499 $confdesc->{"net$i"} = $netdesc;
506 type
=> 'string', format
=> 'pve-qm-drive',
507 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
508 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
510 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
514 type
=> 'string', format
=> 'pve-qm-drive',
515 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
516 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
518 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
522 type
=> 'string', format
=> 'pve-qm-drive',
523 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
524 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
530 type
=> 'string', format
=> 'pve-qm-drive',
531 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]',
532 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
534 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
538 type
=> 'string', format
=> 'pve-qm-usb-device',
539 typetext
=> 'host=HOSTUSBDEVICE|spice',
540 description
=> <<EODESCR,
541 Configure an USB device (n is 0 to 4). This can be used to
542 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
544 'bus-port(.port)*' (decimal numbers) or
545 'vendor_id:product_id' (hexadeciaml numbers)
547 You can use the 'lsusb -t' command to list existing usb devices.
549 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
551 The value 'spice' can be used to add a usb redirection devices for spice.
555 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
559 type
=> 'string', format
=> 'pve-qm-hostpci',
560 typetext
=> "HOSTPCIDEVICE",
561 description
=> <<EODESCR,
562 Map host pci devices. HOSTPCIDEVICE syntax is:
564 'bus:dev.func' (hexadecimal numbers)
566 You can us the 'lspci' command to list existing pci devices.
568 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
570 Experimental: user reported problems with this option.
573 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
578 pattern
=> '(/dev/ttyS\d+|socket)',
579 description
=> <<EODESCR,
580 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).
582 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
584 Experimental: user reported problems with this option.
591 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
592 description
=> <<EODESCR,
593 Map host parallel devices (n is 0 to 2).
595 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
597 Experimental: user reported problems with this option.
601 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
602 $confdesc->{"parallel$i"} = $paralleldesc;
605 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
606 $confdesc->{"serial$i"} = $serialdesc;
609 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
610 $confdesc->{"hostpci$i"} = $hostpcidesc;
613 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
614 $drivename_hash->{"ide$i"} = 1;
615 $confdesc->{"ide$i"} = $idedesc;
618 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
619 $drivename_hash->{"sata$i"} = 1;
620 $confdesc->{"sata$i"} = $satadesc;
623 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
624 $drivename_hash->{"scsi$i"} = 1;
625 $confdesc->{"scsi$i"} = $scsidesc ;
628 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
629 $drivename_hash->{"virtio$i"} = 1;
630 $confdesc->{"virtio$i"} = $virtiodesc;
633 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
634 $confdesc->{"usb$i"} = $usbdesc;
639 type
=> 'string', format
=> 'pve-volume-id',
640 description
=> "Reference to unused volumes.",
643 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
644 $confdesc->{"unused$i"} = $unuseddesc;
647 my $kvm_api_version = 0;
651 return $kvm_api_version if $kvm_api_version;
653 my $fh = IO
::File-
>new("</dev/kvm") ||
656 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
657 $kvm_api_version = $v;
662 return $kvm_api_version;
665 my $kvm_user_version;
667 sub kvm_user_version
{
669 return $kvm_user_version if $kvm_user_version;
671 $kvm_user_version = 'unknown';
673 my $tmp = `kvm -help 2>/dev/null`;
675 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
676 $kvm_user_version = $2;
679 return $kvm_user_version;
683 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
686 # order is important - used to autoselect boot disk
687 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
688 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
689 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
690 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
693 sub valid_drivename
{
696 return defined($drivename_hash->{$dev});
701 return defined($confdesc->{$key});
705 return $nic_model_list;
708 sub os_list_description
{
713 w2k
=> 'Windows 2000',
714 w2k3
=>, 'Windows 2003',
715 w2k8
=> 'Windows 2008',
716 wvista
=> 'Windows Vista',
718 win8
=> 'Windows 8/2012',
728 return $cdrom_path if $cdrom_path;
730 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
731 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
732 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
736 my ($storecfg, $vmid, $cdrom) = @_;
738 if ($cdrom eq 'cdrom') {
739 return get_cdrom_path
();
740 } elsif ($cdrom eq 'none') {
742 } elsif ($cdrom =~ m
|^/|) {
745 return PVE
::Storage
::path
($storecfg, $cdrom);
749 # try to convert old style file names to volume IDs
750 sub filename_to_volume_id
{
751 my ($vmid, $file, $media) = @_;
753 if (!($file eq 'none' || $file eq 'cdrom' ||
754 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
756 return undef if $file =~ m
|/|;
758 if ($media && $media eq 'cdrom') {
759 $file = "local:iso/$file";
761 $file = "local:$vmid/$file";
768 sub verify_media_type
{
769 my ($opt, $vtype, $media) = @_;
774 if ($media eq 'disk') {
776 } elsif ($media eq 'cdrom') {
779 die "internal error";
782 return if ($vtype eq $etype);
784 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
787 sub cleanup_drive_path
{
788 my ($opt, $storecfg, $drive) = @_;
790 # try to convert filesystem paths to volume IDs
792 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
793 ($drive->{file
} !~ m
|^/dev/.+|) &&
794 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
795 ($drive->{file
} !~ m/^\d+$/)) {
796 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
797 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
798 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
799 verify_media_type
($opt, $vtype, $drive->{media
});
800 $drive->{file
} = $volid;
803 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
806 sub create_conf_nolock
{
807 my ($vmid, $settings) = @_;
809 my $filename = config_file
($vmid);
811 die "configuration file '$filename' already exists\n" if -f
$filename;
813 my $defaults = load_defaults
();
815 $settings->{name
} = "vm$vmid" if !$settings->{name
};
816 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
819 foreach my $opt (keys %$settings) {
820 next if !$confdesc->{$opt};
822 my $value = $settings->{$opt};
825 $data .= "$opt: $value\n";
828 PVE
::Tools
::file_set_contents
($filename, $data);
831 my $parse_size = sub {
834 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
835 my ($size, $unit) = ($1, $3);
838 $size = $size * 1024;
839 } elsif ($unit eq 'M') {
840 $size = $size * 1024 * 1024;
841 } elsif ($unit eq 'G') {
842 $size = $size * 1024 * 1024 * 1024;
848 my $format_size = sub {
853 my $kb = int($size/1024);
854 return $size if $kb*1024 != $size;
856 my $mb = int($kb/1024);
857 return "${kb}K" if $mb*1024 != $kb;
859 my $gb = int($mb/1024);
860 return "${mb}M" if $gb*1024 != $mb;
865 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
866 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
867 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
868 # [,aio=native|threads]
871 my ($key, $data) = @_;
875 # $key may be undefined - used to verify JSON parameters
876 if (!defined($key)) {
877 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
879 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
880 $res->{interface
} = $1;
886 foreach my $p (split (/,/, $data)) {
887 next if $p =~ m/^\s*$/;
889 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|bps_rd|mbps_rd|bps_wr|mbps_wr|iops|iops_rd|iops_wr|size)=(.+)$/) {
890 my ($k, $v) = ($1, $2);
892 $k = 'file' if $k eq 'volume';
894 return undef if defined $res->{$k};
896 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
897 return undef if !$v || $v !~ m/^\d+/;
899 $v = sprintf("%.3f", $v / (1024*1024));
903 if (!$res->{file
} && $p !~ m/=/) {
911 return undef if !$res->{file
};
913 if($res->{file
} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
917 return undef if $res->{cache
} &&
918 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
919 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
920 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
921 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
922 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
923 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
924 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
925 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
926 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
927 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
928 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
929 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
932 return undef if $res->{mbps_rd
} && $res->{mbps
};
933 return undef if $res->{mbps_wr
} && $res->{mbps
};
935 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
936 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
937 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
939 return undef if $res->{iops_rd
} && $res->{iops
};
940 return undef if $res->{iops_wr
} && $res->{iops
};
941 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
942 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
943 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
947 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
950 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
951 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
952 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
953 return undef if $res->{interface
} eq 'virtio';
956 # rerror does not work with scsi drives
957 if ($res->{rerror
}) {
958 return undef if $res->{interface
} eq 'scsi';
964 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
967 my ($vmid, $drive) = @_;
970 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
971 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
974 if ($drive->{size
}) {
975 $opts .= ",size=" . &$format_size($drive->{size
});
978 return "$drive->{file}$opts";
982 my($fh, $noerr) = @_;
985 my $SG_GET_VERSION_NUM = 0x2282;
987 my $versionbuf = "\x00" x
8;
988 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
990 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
993 my $version = unpack("I", $versionbuf);
994 if ($version < 30000) {
995 die "scsi generic interface too old\n" if !$noerr;
999 my $buf = "\x00" x
36;
1000 my $sensebuf = "\x00" x
8;
1001 my $cmd = pack("C x3 C x1", 0x12, 36);
1003 # see /usr/include/scsi/sg.h
1004 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";
1006 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1007 length($sensebuf), 0, length($buf), $buf,
1008 $cmd, $sensebuf, 6000);
1010 $ret = ioctl($fh, $SG_IO, $packet);
1012 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1016 my @res = unpack($sg_io_hdr_t, $packet);
1017 if ($res[17] || $res[18]) {
1018 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1023 (my $byte0, my $byte1, $res->{vendor
},
1024 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1026 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1027 $res->{type
} = $byte0 & 31;
1035 my $fh = IO
::File-
>new("+<$path") || return undef;
1036 my $res = scsi_inquiry
($fh, 1);
1042 sub print_drivedevice_full
{
1043 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1048 if ($drive->{interface
} eq 'virtio') {
1049 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1050 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1051 } elsif ($drive->{interface
} eq 'scsi') {
1052 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1053 my $controller = int($drive->{index} / $maxdev);
1054 my $unit = $drive->{index} % $maxdev;
1055 my $devicetype = 'hd';
1057 if (drive_is_cdrom
($drive)) {
1060 if ($drive->{file
} =~ m
|^/|) {
1061 $path = $drive->{file
};
1063 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1066 if($path =~ m/^iscsi\:\/\
//){
1067 $devicetype = 'generic';
1069 if (my $info = path_is_scsi
($path)) {
1070 if ($info->{type
} == 0) {
1071 $devicetype = 'block';
1072 } elsif ($info->{type
} == 1) { # tape
1073 $devicetype = 'generic';
1079 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1080 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}" if !$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi';
1082 $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}";
1085 } elsif ($drive->{interface
} eq 'ide'){
1087 my $controller = int($drive->{index} / $maxdev);
1088 my $unit = $drive->{index} % $maxdev;
1089 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1091 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1092 } elsif ($drive->{interface
} eq 'sata'){
1093 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1094 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1095 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1096 } elsif ($drive->{interface
} eq 'usb') {
1098 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1100 die "unsupported interface type";
1103 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1108 sub print_drive_full
{
1109 my ($storecfg, $vmid, $drive) = @_;
1112 foreach my $o (@qemu_drive_options) {
1113 next if $o eq 'bootindex';
1114 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1117 foreach my $o (qw(bps bps_rd bps_wr)) {
1118 my $v = $drive->{"m$o"};
1119 $opts .= ",$o=" . int($v*1024*1024) if $v;
1122 # use linux-aio by default (qemu default is threads)
1123 $opts .= ",aio=native" if !$drive->{aio
};
1126 my $volid = $drive->{file
};
1127 if (drive_is_cdrom
($drive)) {
1128 $path = get_iso_path
($storecfg, $vmid, $volid);
1130 if ($volid =~ m
|^/|) {
1133 $path = PVE
::Storage
::path
($storecfg, $volid);
1137 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1139 my $pathinfo = $path ?
"file=$path," : '';
1141 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1144 sub print_netdevice_full
{
1145 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1147 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1149 my $device = $net->{model
};
1150 if ($net->{model
} eq 'virtio') {
1151 $device = 'virtio-net-pci';
1154 # qemu > 0.15 always try to boot from network - we disable that by
1155 # not loading the pxe rom file
1156 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1157 my $pciaddr = print_pci_addr
("$netid", $bridges);
1158 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1159 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1163 sub print_netdev_full
{
1164 my ($vmid, $conf, $net, $netid) = @_;
1167 if ($netid =~ m/^net(\d+)$/) {
1171 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1173 my $ifname = "tap${vmid}i$i";
1175 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1176 die "interface name '$ifname' is too long (max 15 character)\n"
1177 if length($ifname) >= 16;
1179 my $vhostparam = '';
1180 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1182 my $vmname = $conf->{name
} || "vm$vmid";
1184 if ($net->{bridge
}) {
1185 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1187 return "type=user,id=$netid,hostname=$vmname";
1191 sub drive_is_cdrom
{
1194 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1201 return undef if !$value;
1205 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1206 $res->{pciid
} = $value;
1214 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1220 foreach my $kvp (split(/,/, $data)) {
1222 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1224 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1225 $res->{model
} = $model;
1226 $res->{macaddr
} = $mac;
1227 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1228 $res->{bridge
} = $1;
1229 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1231 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1239 return undef if !$res->{model
};
1247 my $res = "$net->{model}";
1248 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1249 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1250 $res .= ",rate=$net->{rate}" if $net->{rate
};
1251 $res .= ",tag=$net->{tag}" if $net->{tag
};
1256 sub add_random_macs
{
1257 my ($settings) = @_;
1259 foreach my $opt (keys %$settings) {
1260 next if $opt !~ m/^net(\d+)$/;
1261 my $net = parse_net
($settings->{$opt});
1263 $settings->{$opt} = print_net
($net);
1267 sub add_unused_volume
{
1268 my ($config, $volid) = @_;
1271 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1272 my $test = "unused$ind";
1273 if (my $vid = $config->{$test}) {
1274 return if $vid eq $volid; # do not add duplicates
1280 die "To many unused volume - please delete them first.\n" if !$key;
1282 $config->{$key} = $volid;
1287 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1288 sub verify_bootdisk
{
1289 my ($value, $noerr) = @_;
1291 return $value if valid_drivename
($value);
1293 return undef if $noerr;
1295 die "invalid boot disk '$value'\n";
1298 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1300 my ($value, $noerr) = @_;
1302 return $value if parse_net
($value);
1304 return undef if $noerr;
1306 die "unable to parse network options\n";
1309 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1311 my ($value, $noerr) = @_;
1313 return $value if parse_drive
(undef, $value);
1315 return undef if $noerr;
1317 die "unable to parse drive options\n";
1320 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1321 sub verify_hostpci
{
1322 my ($value, $noerr) = @_;
1324 return $value if parse_hostpci
($value);
1326 return undef if $noerr;
1328 die "unable to parse pci id\n";
1331 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1332 sub verify_watchdog
{
1333 my ($value, $noerr) = @_;
1335 return $value if parse_watchdog
($value);
1337 return undef if $noerr;
1339 die "unable to parse watchdog options\n";
1342 sub parse_watchdog
{
1345 return undef if !$value;
1349 foreach my $p (split(/,/, $value)) {
1350 next if $p =~ m/^\s*$/;
1352 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1354 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1355 $res->{action
} = $2;
1364 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1365 sub verify_startup
{
1366 my ($value, $noerr) = @_;
1368 return $value if parse_startup
($value);
1370 return undef if $noerr;
1372 die "unable to parse startup options\n";
1378 return undef if !$value;
1382 foreach my $p (split(/,/, $value)) {
1383 next if $p =~ m/^\s*$/;
1385 if ($p =~ m/^(order=)?(\d+)$/) {
1387 } elsif ($p =~ m/^up=(\d+)$/) {
1389 } elsif ($p =~ m/^down=(\d+)$/) {
1399 sub parse_usb_device
{
1402 return undef if !$value;
1404 my @dl = split(/,/, $value);
1408 foreach my $v (@dl) {
1409 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1411 $res->{vendorid
} = $2;
1412 $res->{productid
} = $4;
1413 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1415 $res->{hostbus
} = $1;
1416 $res->{hostport
} = $2;
1417 } elsif ($v =~ m/^spice$/) {
1424 return undef if !$found;
1429 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1430 sub verify_usb_device
{
1431 my ($value, $noerr) = @_;
1433 return $value if parse_usb_device
($value);
1435 return undef if $noerr;
1437 die "unable to parse usb device\n";
1440 # add JSON properties for create and set function
1441 sub json_config_properties
{
1444 foreach my $opt (keys %$confdesc) {
1445 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1446 $prop->{$opt} = $confdesc->{$opt};
1453 my ($key, $value) = @_;
1455 die "unknown setting '$key'\n" if !$confdesc->{$key};
1457 my $type = $confdesc->{$key}->{type
};
1459 if (!defined($value)) {
1460 die "got undefined value\n";
1463 if ($value =~ m/[\n\r]/) {
1464 die "property contains a line feed\n";
1467 if ($type eq 'boolean') {
1468 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1469 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1470 die "type check ('boolean') failed - got '$value'\n";
1471 } elsif ($type eq 'integer') {
1472 return int($1) if $value =~ m/^(\d+)$/;
1473 die "type check ('integer') failed - got '$value'\n";
1474 } elsif ($type eq 'number') {
1475 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1476 die "type check ('number') failed - got '$value'\n";
1477 } elsif ($type eq 'string') {
1478 if (my $fmt = $confdesc->{$key}->{format
}) {
1479 if ($fmt eq 'pve-qm-drive') {
1480 # special case - we need to pass $key to parse_drive()
1481 my $drive = parse_drive
($key, $value);
1482 return $value if $drive;
1483 die "unable to parse drive options\n";
1485 PVE
::JSONSchema
::check_format
($fmt, $value);
1488 $value =~ s/^\"(.*)\"$/$1/;
1491 die "internal error"
1495 sub lock_config_full
{
1496 my ($vmid, $timeout, $code, @param) = @_;
1498 my $filename = config_file_lock
($vmid);
1500 my $res = lock_file
($filename, $timeout, $code, @param);
1507 sub lock_config_mode
{
1508 my ($vmid, $timeout, $shared, $code, @param) = @_;
1510 my $filename = config_file_lock
($vmid);
1512 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1520 my ($vmid, $code, @param) = @_;
1522 return lock_config_full
($vmid, 10, $code, @param);
1525 sub cfs_config_path
{
1526 my ($vmid, $node) = @_;
1528 $node = $nodename if !$node;
1529 return "nodes/$node/qemu-server/$vmid.conf";
1532 sub check_iommu_support
{
1533 #fixme : need to check IOMMU support
1534 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1542 my ($vmid, $node) = @_;
1544 my $cfspath = cfs_config_path
($vmid, $node);
1545 return "/etc/pve/$cfspath";
1548 sub config_file_lock
{
1551 return "$lock_dir/lock-$vmid.conf";
1557 my $conf = config_file
($vmid);
1558 utime undef, undef, $conf;
1562 my ($storecfg, $vmid, $keep_empty_config) = @_;
1564 my $conffile = config_file
($vmid);
1566 my $conf = load_config
($vmid);
1570 # only remove disks owned by this VM
1571 foreach_drive
($conf, sub {
1572 my ($ds, $drive) = @_;
1574 return if drive_is_cdrom
($drive);
1576 my $volid = $drive->{file
};
1578 return if !$volid || $volid =~ m
|^/|;
1580 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1581 return if !$path || !$owner || ($owner != $vmid);
1583 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1586 if ($keep_empty_config) {
1587 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1592 # also remove unused disk
1594 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1597 PVE
::Storage
::foreach_volid
($dl, sub {
1598 my ($volid, $sid, $volname, $d) = @_;
1599 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1609 my ($vmid, $node) = @_;
1611 my $cfspath = cfs_config_path
($vmid, $node);
1613 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1615 die "no such VM ('$vmid')\n" if !defined($conf);
1620 sub parse_vm_config
{
1621 my ($filename, $raw) = @_;
1623 return undef if !defined($raw);
1626 digest
=> Digest
::SHA
::sha1_hex
($raw),
1630 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1631 || die "got strange filename '$filename'";
1638 my @lines = split(/\n/, $raw);
1639 foreach my $line (@lines) {
1640 next if $line =~ m/^\s*$/;
1642 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1644 $conf->{description
} = $descr if $descr;
1646 $conf = $res->{snapshots
}->{$snapname} = {};
1650 if ($line =~ m/^\#(.*)\s*$/) {
1651 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1655 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1656 $descr .= PVE
::Tools
::decode_text
($2);
1657 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1658 $conf->{snapstate
} = $1;
1659 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1662 $conf->{$key} = $value;
1663 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1666 eval { $value = check_type
($key, $value); };
1668 warn "vm $vmid - unable to parse value of '$key' - $@";
1670 my $fmt = $confdesc->{$key}->{format
};
1671 if ($fmt && $fmt eq 'pve-qm-drive') {
1672 my $v = parse_drive
($key, $value);
1673 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1674 $v->{file
} = $volid;
1675 $value = print_drive
($vmid, $v);
1677 warn "vm $vmid - unable to parse value of '$key'\n";
1682 if ($key eq 'cdrom') {
1683 $conf->{ide2
} = $value;
1685 $conf->{$key} = $value;
1691 $conf->{description
} = $descr if $descr;
1693 delete $res->{snapstate
}; # just to be sure
1698 sub write_vm_config
{
1699 my ($filename, $conf) = @_;
1701 delete $conf->{snapstate
}; # just to be sure
1703 if ($conf->{cdrom
}) {
1704 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1705 $conf->{ide2
} = $conf->{cdrom
};
1706 delete $conf->{cdrom
};
1709 # we do not use 'smp' any longer
1710 if ($conf->{sockets
}) {
1711 delete $conf->{smp
};
1712 } elsif ($conf->{smp
}) {
1713 $conf->{sockets
} = $conf->{smp
};
1714 delete $conf->{cores
};
1715 delete $conf->{smp
};
1718 my $used_volids = {};
1720 my $cleanup_config = sub {
1721 my ($cref, $snapname) = @_;
1723 foreach my $key (keys %$cref) {
1724 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1725 $key eq 'snapstate';
1726 my $value = $cref->{$key};
1727 eval { $value = check_type
($key, $value); };
1728 die "unable to parse value of '$key' - $@" if $@;
1730 $cref->{$key} = $value;
1732 if (!$snapname && valid_drivename
($key)) {
1733 my $drive = parse_drive
($key, $value);
1734 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1739 &$cleanup_config($conf);
1740 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1741 &$cleanup_config($conf->{snapshots
}->{$snapname}, $snapname);
1744 # remove 'unusedX' settings if we re-add a volume
1745 foreach my $key (keys %$conf) {
1746 my $value = $conf->{$key};
1747 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1748 delete $conf->{$key};
1752 my $generate_raw_config = sub {
1757 # add description as comment to top of file
1758 my $descr = $conf->{description
} || '';
1759 foreach my $cl (split(/\n/, $descr)) {
1760 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1763 foreach my $key (sort keys %$conf) {
1764 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1765 $raw .= "$key: $conf->{$key}\n";
1770 my $raw = &$generate_raw_config($conf);
1771 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1772 $raw .= "\n[$snapname]\n";
1773 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1779 sub update_config_nolock
{
1780 my ($vmid, $conf, $skiplock) = @_;
1782 check_lock
($conf) if !$skiplock;
1784 my $cfspath = cfs_config_path
($vmid);
1786 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1790 my ($vmid, $conf, $skiplock) = @_;
1792 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1799 # we use static defaults from our JSON schema configuration
1800 foreach my $key (keys %$confdesc) {
1801 if (defined(my $default = $confdesc->{$key}->{default})) {
1802 $res->{$key} = $default;
1806 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1807 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1813 my $vmlist = PVE
::Cluster
::get_vmlist
();
1815 return $res if !$vmlist || !$vmlist->{ids
};
1816 my $ids = $vmlist->{ids
};
1818 foreach my $vmid (keys %$ids) {
1819 my $d = $ids->{$vmid};
1820 next if !$d->{node
} || $d->{node
} ne $nodename;
1821 next if !$d->{type
} || $d->{type
} ne 'qemu';
1822 $res->{$vmid}->{exists} = 1;
1827 # test if VM uses local resources (to prevent migration)
1828 sub check_local_resources
{
1829 my ($conf, $noerr) = @_;
1833 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1834 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1836 foreach my $k (keys %$conf) {
1837 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1840 die "VM uses local resources\n" if $loc_res && !$noerr;
1845 # check if used storages are available on all nodes (use by migrate)
1846 sub check_storage_availability
{
1847 my ($storecfg, $conf, $node) = @_;
1849 foreach_drive
($conf, sub {
1850 my ($ds, $drive) = @_;
1852 my $volid = $drive->{file
};
1855 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1858 # check if storage is available on both nodes
1859 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1860 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1864 # list nodes where all VM images are available (used by has_feature API)
1866 my ($conf, $storecfg) = @_;
1868 my $nodelist = PVE
::Cluster
::get_nodelist
();
1869 my $nodehash = { map { $_ => 1 } @$nodelist };
1870 my $nodename = PVE
::INotify
::nodename
();
1872 foreach_drive
($conf, sub {
1873 my ($ds, $drive) = @_;
1875 my $volid = $drive->{file
};
1878 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1880 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1881 if ($scfg->{disable
}) {
1883 } elsif (my $avail = $scfg->{nodes
}) {
1884 foreach my $node (keys %$nodehash) {
1885 delete $nodehash->{$node} if !$avail->{$node};
1887 } elsif (!$scfg->{shared
}) {
1888 foreach my $node (keys %$nodehash) {
1889 delete $nodehash->{$node} if $node ne $nodename
1901 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1905 my ($pidfile, $pid) = @_;
1907 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1911 return undef if !$line;
1912 my @param = split(/\0/, $line);
1914 my $cmd = $param[0];
1915 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1917 for (my $i = 0; $i < scalar (@param); $i++) {
1920 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1921 my $p = $param[$i+1];
1922 return 1 if $p && ($p eq $pidfile);
1931 my ($vmid, $nocheck, $node) = @_;
1933 my $filename = config_file
($vmid, $node);
1935 die "unable to find configuration file for VM $vmid - no such machine\n"
1936 if !$nocheck && ! -f
$filename;
1938 my $pidfile = pidfile_name
($vmid);
1940 if (my $fd = IO
::File-
>new("<$pidfile")) {
1945 my $mtime = $st->mtime;
1946 if ($mtime > time()) {
1947 warn "file '$filename' modified in future\n";
1950 if ($line =~ m/^(\d+)$/) {
1952 if (check_cmdline
($pidfile, $pid)) {
1953 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1965 my $vzlist = config_list
();
1967 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1969 while (defined(my $de = $fd->read)) {
1970 next if $de !~ m/^(\d+)\.pid$/;
1972 next if !defined($vzlist->{$vmid});
1973 if (my $pid = check_running
($vmid)) {
1974 $vzlist->{$vmid}->{pid
} = $pid;
1982 my ($storecfg, $conf) = @_;
1984 my $bootdisk = $conf->{bootdisk
};
1985 return undef if !$bootdisk;
1986 return undef if !valid_drivename
($bootdisk);
1988 return undef if !$conf->{$bootdisk};
1990 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1991 return undef if !defined($drive);
1993 return undef if drive_is_cdrom
($drive);
1995 my $volid = $drive->{file
};
1996 return undef if !$volid;
1998 return $drive->{size
};
2001 my $last_proc_pid_stat;
2003 # get VM status information
2004 # This must be fast and should not block ($full == false)
2005 # We only query KVM using QMP if $full == true (this can be slow)
2007 my ($opt_vmid, $full) = @_;
2011 my $storecfg = PVE
::Storage
::config
();
2013 my $list = vzlist
();
2014 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2016 my $cpucount = $cpuinfo->{cpus
} || 1;
2018 foreach my $vmid (keys %$list) {
2019 next if $opt_vmid && ($vmid ne $opt_vmid);
2021 my $cfspath = cfs_config_path
($vmid);
2022 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2025 $d->{pid
} = $list->{$vmid}->{pid
};
2027 # fixme: better status?
2028 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2030 my $size = disksize
($storecfg, $conf);
2031 if (defined($size)) {
2032 $d->{disk
} = 0; # no info available
2033 $d->{maxdisk
} = $size;
2039 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2040 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2042 $d->{name
} = $conf->{name
} || "VM $vmid";
2043 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2045 if ($conf->{balloon
}) {
2046 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2047 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2058 $d->{diskwrite
} = 0;
2060 $d->{template
} = is_template
($conf);
2065 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2066 foreach my $dev (keys %$netdev) {
2067 next if $dev !~ m/^tap([1-9]\d*)i/;
2069 my $d = $res->{$vmid};
2072 $d->{netout
} += $netdev->{$dev}->{receive
};
2073 $d->{netin
} += $netdev->{$dev}->{transmit
};
2076 my $ctime = gettimeofday
;
2078 foreach my $vmid (keys %$list) {
2080 my $d = $res->{$vmid};
2081 my $pid = $d->{pid
};
2084 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2085 next if !$pstat; # not running
2087 my $used = $pstat->{utime} + $pstat->{stime
};
2089 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2091 if ($pstat->{vsize
}) {
2092 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2095 my $old = $last_proc_pid_stat->{$pid};
2097 $last_proc_pid_stat->{$pid} = {
2105 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2107 if ($dtime > 1000) {
2108 my $dutime = $used - $old->{used
};
2110 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2111 $last_proc_pid_stat->{$pid} = {
2117 $d->{cpu
} = $old->{cpu
};
2121 return $res if !$full;
2123 my $qmpclient = PVE
::QMPClient-
>new();
2125 my $ballooncb = sub {
2126 my ($vmid, $resp) = @_;
2128 my $info = $resp->{'return'};
2129 return if !$info->{max_mem
};
2131 my $d = $res->{$vmid};
2133 # use memory assigned to VM
2134 $d->{maxmem
} = $info->{max_mem
};
2135 $d->{balloon
} = $info->{actual
};
2137 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2138 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2139 $d->{freemem
} = $info->{free_mem
};
2144 my $blockstatscb = sub {
2145 my ($vmid, $resp) = @_;
2146 my $data = $resp->{'return'} || [];
2147 my $totalrdbytes = 0;
2148 my $totalwrbytes = 0;
2149 for my $blockstat (@$data) {
2150 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2151 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2153 $res->{$vmid}->{diskread
} = $totalrdbytes;
2154 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2157 my $statuscb = sub {
2158 my ($vmid, $resp) = @_;
2160 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2161 # this fails if ballon driver is not loaded, so this must be
2162 # the last commnand (following command are aborted if this fails).
2163 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2165 my $status = 'unknown';
2166 if (!defined($status = $resp->{'return'}->{status
})) {
2167 warn "unable to get VM status\n";
2171 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2174 foreach my $vmid (keys %$list) {
2175 next if $opt_vmid && ($vmid ne $opt_vmid);
2176 next if !$res->{$vmid}->{pid
}; # not running
2177 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2180 $qmpclient->queue_execute();
2182 foreach my $vmid (keys %$list) {
2183 next if $opt_vmid && ($vmid ne $opt_vmid);
2184 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2191 my ($conf, $func) = @_;
2193 foreach my $ds (keys %$conf) {
2194 next if !valid_drivename
($ds);
2196 my $drive = parse_drive
($ds, $conf->{$ds});
2199 &$func($ds, $drive);
2204 my ($conf, $func) = @_;
2208 my $test_volid = sub {
2209 my ($volid, $is_cdrom) = @_;
2213 $volhash->{$volid} = $is_cdrom || 0;
2216 foreach_drive
($conf, sub {
2217 my ($ds, $drive) = @_;
2218 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2221 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2222 my $snap = $conf->{snapshots
}->{$snapname};
2223 &$test_volid($snap->{vmstate
}, 0);
2224 foreach_drive
($snap, sub {
2225 my ($ds, $drive) = @_;
2226 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2230 foreach my $volid (keys %$volhash) {
2231 &$func($volid, $volhash->{$volid});
2235 sub vga_conf_has_spice
{
2238 return $vga && ($vga eq 'qxl');
2241 sub config_to_command
{
2242 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2245 my $globalFlags = [];
2246 my $machineFlags = [];
2252 my $kvmver = kvm_user_version
();
2253 my $vernum = 0; # unknown
2254 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2255 $vernum = $1*1000000+$2*1000;
2256 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2257 $vernum = $1*1000000+$2*1000+$3;
2260 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2262 my $have_ovz = -f
'/proc/vz/vestat';
2264 push @$cmd, '/usr/bin/kvm';
2266 push @$cmd, '-id', $vmid;
2270 my $qmpsocket = qmp_socket
($vmid);
2271 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2272 push @$cmd, '-mon', "chardev=qmp,mode=control";
2274 my $socket = vnc_socket
($vmid);
2275 push @$cmd, '-vnc', "unix:$socket,x509,password";
2277 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2279 push @$cmd, '-daemonize';
2281 $pciaddr = print_pci_addr
("piix3", $bridges);
2282 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2285 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2286 next if !$conf->{"usb$i"};
2289 # include usb device config
2290 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2292 my $vga = $conf->{vga
};
2294 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2295 $conf->{ostype
} eq 'win7' ||
2296 $conf->{ostype
} eq 'w2k8')) {
2303 # enable absolute mouse coordinates (needed by vnc)
2305 if (defined($conf->{tablet
})) {
2306 $tablet = $conf->{tablet
};
2308 $tablet = $defaults->{tablet
};
2309 $tablet = 0 if vga_conf_has_spice
($vga); # disable for spice because it is not needed
2310 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2313 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2316 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2317 my $d = parse_hostpci
($conf->{"hostpci$i"});
2319 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2320 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2324 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2325 my $d = parse_usb_device
($conf->{"usb$i"});
2327 if ($d->{vendorid
} && $d->{productid
}) {
2328 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2329 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2330 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2331 } elsif ($d->{spice
}) {
2332 # usb redir support for spice
2333 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2334 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2339 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2340 if (my $path = $conf->{"serial$i"}) {
2341 if ($path eq 'socket') {
2342 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2343 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2344 push @$devices, '-device', "isa-serial,chardev=serial$i";
2346 die "no such serial device\n" if ! -c
$path;
2347 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2348 push @$devices, '-device', "isa-serial,chardev=serial$i";
2354 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2355 if (my $path = $conf->{"parallel$i"}) {
2356 die "no such parallel device\n" if ! -c
$path;
2357 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2358 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2359 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2363 my $vmname = $conf->{name
} || "vm$vmid";
2365 push @$cmd, '-name', $vmname;
2368 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2369 $sockets = $conf->{sockets
} if $conf->{sockets
};
2371 my $cores = $conf->{cores
} || 1;
2372 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2374 push @$cmd, '-nodefaults';
2376 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2378 my $bootindex_hash = {};
2380 foreach my $o (split(//, $bootorder)) {
2381 $bootindex_hash->{$o} = $i*100;
2385 push @$cmd, '-boot', "menu=on";
2387 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2389 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2391 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2394 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2396 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2397 my $useLocaltime = $conf->{localtime};
2399 if (my $ost = $conf->{ostype
}) {
2400 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2402 if ($ost =~ m/^w/) { # windows
2403 $useLocaltime = 1 if !defined($conf->{localtime});
2405 # use time drift fix when acpi is enabled
2406 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2407 $tdf = 1 if !defined($conf->{tdf
});
2411 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2413 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2414 push @$cmd, '-no-hpet';
2415 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2416 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2419 if ($ost eq 'win7' || $ost eq 'win8') {
2420 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2424 push @$rtcFlags, 'driftfix=slew' if $tdf;
2427 push @$machineFlags, 'accel=tcg';
2429 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2432 my $machine_type = $forcemachine || $conf->{machine
};
2433 if ($machine_type) {
2434 push @$machineFlags, "type=${machine_type}";
2437 if ($conf->{startdate
}) {
2438 push @$rtcFlags, "base=$conf->{startdate}";
2439 } elsif ($useLocaltime) {
2440 push @$rtcFlags, 'base=localtime';
2443 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2444 $cpu = $conf->{cpu
} if $conf->{cpu
};
2446 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2448 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2450 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2452 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2454 push @$cmd, '-cpu', $cpu;
2456 push @$cmd, '-S' if $conf->{freeze
};
2458 # set keyboard layout
2459 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2460 push @$cmd, '-k', $kb if $kb;
2463 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2464 #push @$cmd, '-soundhw', 'es1370';
2465 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2467 if($conf->{agent
}) {
2468 my $qgasocket = qga_socket
($vmid);
2469 my $pciaddr = print_pci_addr
("qga0", $bridges);
2470 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2471 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2472 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2476 if (vga_conf_has_spice
($vga)) {
2477 my $pciaddr = print_pci_addr
("spice", $bridges);
2479 $spice_port = PVE
::Tools
::next_unused_port
(61000, 61099);
2481 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
2483 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2484 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2485 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2488 # enable balloon by default, unless explicitly disabled
2489 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2490 $pciaddr = print_pci_addr
("balloon0", $bridges);
2491 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2494 if ($conf->{watchdog
}) {
2495 my $wdopts = parse_watchdog
($conf->{watchdog
});
2496 $pciaddr = print_pci_addr
("watchdog", $bridges);
2497 my $watchdog = $wdopts->{model
} || 'i6300esb';
2498 push @$devices, '-device', "$watchdog$pciaddr";
2499 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2503 my $scsicontroller = {};
2504 my $ahcicontroller = {};
2505 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2507 foreach_drive
($conf, sub {
2508 my ($ds, $drive) = @_;
2510 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2511 push @$vollist, $drive->{file
};
2514 $use_virtio = 1 if $ds =~ m/^virtio/;
2516 if (drive_is_cdrom
($drive)) {
2517 if ($bootindex_hash->{d
}) {
2518 $drive->{bootindex
} = $bootindex_hash->{d
};
2519 $bootindex_hash->{d
} += 1;
2522 if ($bootindex_hash->{c
}) {
2523 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2524 $bootindex_hash->{c
} += 1;
2528 if ($drive->{interface
} eq 'scsi') {
2530 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2531 my $controller = int($drive->{index} / $maxdev);
2532 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2533 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2534 $scsicontroller->{$controller}=1;
2537 if ($drive->{interface
} eq 'sata') {
2538 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2539 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2540 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2541 $ahcicontroller->{$controller}=1;
2544 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2545 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2548 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2550 for (my $i = 0; $i < $MAX_NETS; $i++) {
2551 next if !$conf->{"net$i"};
2552 my $d = parse_net
($conf->{"net$i"});
2555 $use_virtio = 1 if $d->{model
} eq 'virtio';
2557 if ($bootindex_hash->{n
}) {
2558 $d->{bootindex
} = $bootindex_hash->{n
};
2559 $bootindex_hash->{n
} += 1;
2562 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2563 push @$devices, '-netdev', $netdevfull;
2565 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2566 push @$devices, '-device', $netdevicefull;
2570 while (my ($k, $v) = each %$bridges) {
2571 $pciaddr = print_pci_addr
("pci.$k");
2572 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2576 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2577 # when the VM uses virtio devices.
2578 if (!$use_virtio && $have_ovz) {
2580 my $cpuunits = defined($conf->{cpuunits
}) ?
2581 $conf->{cpuunits
} : $defaults->{cpuunits
};
2583 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2585 # fixme: cpulimit is currently ignored
2586 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2590 if ($conf->{args
}) {
2591 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2595 push @$cmd, @$devices;
2596 push @$cmd, '-rtc', join(',', @$rtcFlags)
2597 if scalar(@$rtcFlags);
2598 push @$cmd, '-machine', join(',', @$machineFlags)
2599 if scalar(@$machineFlags);
2600 push @$cmd, '-global', join(',', @$globalFlags)
2601 if scalar(@$globalFlags);
2603 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
2608 return "${var_run_tmpdir}/$vmid.vnc";
2614 my $res = vm_mon_cmd
($vmid, 'query-spice');
2616 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
2621 return "${var_run_tmpdir}/$vmid.qmp";
2626 return "${var_run_tmpdir}/$vmid.qga";
2631 return "${var_run_tmpdir}/$vmid.pid";
2634 sub vm_devices_list
{
2637 my $res = vm_mon_cmd
($vmid, 'query-pci');
2640 foreach my $pcibus (@$res) {
2641 foreach my $device (@{$pcibus->{devices
}}) {
2642 next if !$device->{'qdev_id'};
2643 $devices->{$device->{'qdev_id'}} = $device;
2651 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2653 return 1 if !check_running
($vmid);
2655 if ($deviceid eq 'tablet') {
2656 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2657 qemu_deviceadd
($vmid, $devicefull);
2661 return 1 if !$conf->{hotplug
};
2663 my $devices_list = vm_devices_list
($vmid);
2664 return 1 if defined($devices_list->{$deviceid});
2666 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2668 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2669 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2670 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2671 qemu_deviceadd
($vmid, $devicefull);
2672 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2673 qemu_drivedel
($vmid, $deviceid);
2678 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2679 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2680 my $pciaddr = print_pci_addr
($deviceid);
2681 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2682 qemu_deviceadd
($vmid, $devicefull);
2683 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2686 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2687 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2688 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2689 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2690 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2691 if(!qemu_deviceadd
($vmid, $devicefull)) {
2692 qemu_drivedel
($vmid, $deviceid);
2697 if ($deviceid =~ m/^(net)(\d+)$/) {
2698 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2699 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2700 qemu_deviceadd
($vmid, $netdevicefull);
2701 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2702 qemu_netdevdel
($vmid, $deviceid);
2707 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2709 my $pciaddr = print_pci_addr
($deviceid);
2710 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2711 qemu_deviceadd
($vmid, $devicefull);
2712 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2718 sub vm_deviceunplug
{
2719 my ($vmid, $conf, $deviceid) = @_;
2721 return 1 if !check_running
($vmid);
2723 if ($deviceid eq 'tablet') {
2724 qemu_devicedel
($vmid, $deviceid);
2728 return 1 if !$conf->{hotplug
};
2730 my $devices_list = vm_devices_list
($vmid);
2731 return 1 if !defined($devices_list->{$deviceid});
2733 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2735 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2736 qemu_devicedel
($vmid, $deviceid);
2737 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2738 return undef if !qemu_drivedel
($vmid, $deviceid);
2741 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2742 return undef if !qemu_devicedel
($vmid, $deviceid);
2745 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2746 return undef if !qemu_devicedel
($vmid, $deviceid);
2747 return undef if !qemu_drivedel
($vmid, $deviceid);
2750 if ($deviceid =~ m/^(net)(\d+)$/) {
2751 qemu_devicedel
($vmid, $deviceid);
2752 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2753 return undef if !qemu_netdevdel
($vmid, $deviceid);
2759 sub qemu_deviceadd
{
2760 my ($vmid, $devicefull) = @_;
2762 $devicefull = "driver=".$devicefull;
2763 my %options = split(/[=,]/, $devicefull);
2765 vm_mon_cmd
($vmid, "device_add" , %options);
2769 sub qemu_devicedel
{
2770 my($vmid, $deviceid) = @_;
2771 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2776 my($storecfg, $vmid, $device) = @_;
2778 my $drive = print_drive_full
($storecfg, $vmid, $device);
2779 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2780 # If the command succeeds qemu prints: "OK"
2781 if ($ret !~ m/OK/s) {
2782 syslog
("err", "adding drive failed: $ret");
2789 my($vmid, $deviceid) = @_;
2791 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2793 if ($ret =~ m/Device \'.*?\' not found/s) {
2794 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2796 elsif ($ret ne "") {
2797 syslog
("err", "deleting drive $deviceid failed : $ret");
2803 sub qemu_deviceaddverify
{
2804 my ($vmid,$deviceid) = @_;
2806 for (my $i = 0; $i <= 5; $i++) {
2807 my $devices_list = vm_devices_list
($vmid);
2808 return 1 if defined($devices_list->{$deviceid});
2811 syslog
("err", "error on hotplug device $deviceid");
2816 sub qemu_devicedelverify
{
2817 my ($vmid,$deviceid) = @_;
2819 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2820 for (my $i = 0; $i <= 5; $i++) {
2821 my $devices_list = vm_devices_list
($vmid);
2822 return 1 if !defined($devices_list->{$deviceid});
2825 syslog
("err", "error on hot-unplugging device $deviceid");
2829 sub qemu_findorcreatescsihw
{
2830 my ($storecfg, $conf, $vmid, $device) = @_;
2832 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2833 my $controller = int($device->{index} / $maxdev);
2834 my $scsihwid="scsihw$controller";
2835 my $devices_list = vm_devices_list
($vmid);
2837 if(!defined($devices_list->{$scsihwid})) {
2838 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2843 sub qemu_bridgeadd
{
2844 my ($storecfg, $conf, $vmid, $device) = @_;
2847 my $bridgeid = undef;
2848 print_pci_addr
($device, $bridges);
2850 while (my ($k, $v) = each %$bridges) {
2853 return if !$bridgeid || $bridgeid < 1;
2854 my $bridge = "pci.$bridgeid";
2855 my $devices_list = vm_devices_list
($vmid);
2857 if(!defined($devices_list->{$bridge})) {
2858 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2863 sub qemu_netdevadd
{
2864 my ($vmid, $conf, $device, $deviceid) = @_;
2866 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2867 my %options = split(/[=,]/, $netdev);
2869 vm_mon_cmd
($vmid, "netdev_add", %options);
2873 sub qemu_netdevdel
{
2874 my ($vmid, $deviceid) = @_;
2876 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2880 sub qemu_block_set_io_throttle
{
2881 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2883 return if !check_running
($vmid) ;
2885 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));
2889 # old code, only used to shutdown old VM after update
2891 my ($fh, $timeout) = @_;
2893 my $sel = new IO
::Select
;
2900 while (scalar (@ready = $sel->can_read($timeout))) {
2902 if ($count = $fh->sysread($buf, 8192)) {
2903 if ($buf =~ /^(.*)\(qemu\) $/s) {
2910 if (!defined($count)) {
2917 die "monitor read timeout\n" if !scalar(@ready);
2922 # old code, only used to shutdown old VM after update
2923 sub vm_monitor_command
{
2924 my ($vmid, $cmdstr, $nocheck) = @_;
2929 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2931 my $sname = "${var_run_tmpdir}/$vmid.mon";
2933 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2934 die "unable to connect to VM $vmid socket - $!\n";
2938 # hack: migrate sometime blocks the monitor (when migrate_downtime
2940 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2941 $timeout = 60*60; # 1 hour
2945 my $data = __read_avail
($sock, $timeout);
2947 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2948 die "got unexpected qemu monitor banner\n";
2951 my $sel = new IO
::Select
;
2954 if (!scalar(my @ready = $sel->can_write($timeout))) {
2955 die "monitor write error - timeout";
2958 my $fullcmd = "$cmdstr\r";
2960 # syslog('info', "VM $vmid monitor command: $cmdstr");
2963 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2964 die "monitor write error - $!";
2967 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2971 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2972 $timeout = 60*60; # 1 hour
2973 } elsif ($cmdstr =~ m/^(eject|change)/) {
2974 $timeout = 60; # note: cdrom mount command is slow
2976 if ($res = __read_avail
($sock, $timeout)) {
2978 my @lines = split("\r?\n", $res);
2980 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2982 $res = join("\n", @lines);
2990 syslog
("err", "VM $vmid monitor command failed - $err");
2997 sub qemu_block_resize
{
2998 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3000 my $running = check_running
($vmid);
3002 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
3004 return if !$running;
3006 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
3010 sub qemu_volume_snapshot
{
3011 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3013 my $running = check_running
($vmid);
3015 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
3017 return if !$running;
3019 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
3023 sub qemu_volume_snapshot_delete
{
3024 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3026 my $running = check_running
($vmid);
3028 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
3030 return if !$running;
3032 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
3038 #need to impplement call to qemu-ga
3041 sub qga_unfreezefs
{
3044 #need to impplement call to qemu-ga
3048 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
3050 lock_config
($vmid, sub {
3051 my $conf = load_config
($vmid, $migratedfrom);
3053 die "you can't start a vm if it's a template\n" if is_template
($conf);
3055 check_lock
($conf) if !$skiplock;
3057 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
3059 my $defaults = load_defaults
();
3061 # set environment variable useful inside network script
3062 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
3064 my ($cmd, $vollist, $spice_port) = config_to_command
($storecfg, $vmid, $conf, $defaults, $forcemachine);
3066 my $migrate_port = 0;
3069 if ($statefile eq 'tcp') {
3070 my $localip = "localhost";
3071 my $datacenterconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
3072 if ($datacenterconf->{migration_unsecure
}) {
3073 my $nodename = PVE
::INotify
::nodename
();
3074 $localip = PVE
::Cluster
::remote_node_ip
($nodename, 1);
3076 $migrate_port = PVE
::Tools
::next_migrate_port
();
3077 $migrate_uri = "tcp:${localip}:${migrate_port}";
3078 push @$cmd, '-incoming', $migrate_uri;
3081 push @$cmd, '-loadstate', $statefile;
3088 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3089 my $d = parse_hostpci
($conf->{"hostpci$i"});
3091 my $info = pci_device_info
("0000:$d->{pciid}");
3092 die "IOMMU not present\n" if !check_iommu_support
();
3093 die "no pci device info for device '$d->{pciid}'\n" if !$info;
3094 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
3095 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
3098 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
3100 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
3103 die "start failed: $err" if $err;
3105 print "migration listens on $migrate_uri\n" if $migrate_uri;
3107 if ($statefile && $statefile ne 'tcp') {
3108 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
3112 if ($migratedfrom) {
3113 my $capabilities = {};
3114 $capabilities->{capability
} = "xbzrle";
3115 $capabilities->{state} = JSON
::true
;
3116 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
3120 print "spice listens on port $spice_port\n";
3121 if ($spice_ticket) {
3122 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "set_password", protocol
=> 'spice', password
=> $spice_ticket);
3123 PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, "expire_password", protocol
=> 'spice', time => "+30");
3129 if (!$statefile && (!defined($conf->{balloon
}) || $conf->{balloon
})) {
3130 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
3131 if $conf->{balloon
};
3132 vm_mon_cmd_nocheck
($vmid, 'qom-set',
3133 path
=> "machine/peripheral/balloon0",
3134 property
=> "guest-stats-polling-interval",
3142 my ($vmid, $execute, %params) = @_;
3144 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3145 vm_qmp_command
($vmid, $cmd);
3148 sub vm_mon_cmd_nocheck
{
3149 my ($vmid, $execute, %params) = @_;
3151 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3152 vm_qmp_command
($vmid, $cmd, 1);
3155 sub vm_qmp_command
{
3156 my ($vmid, $cmd, $nocheck) = @_;
3161 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3162 $timeout = $cmd->{arguments
}->{timeout
};
3163 delete $cmd->{arguments
}->{timeout
};
3167 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3168 my $sname = qmp_socket
($vmid);
3170 my $qmpclient = PVE
::QMPClient-
>new();
3172 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3173 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3174 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3175 if scalar(%{$cmd->{arguments
}});
3176 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3178 die "unable to open monitor socket\n";
3182 syslog
("err", "VM $vmid qmp command failed - $err");
3189 sub vm_human_monitor_command
{
3190 my ($vmid, $cmdline) = @_;
3195 execute
=> 'human-monitor-command',
3196 arguments
=> { 'command-line' => $cmdline},
3199 return vm_qmp_command
($vmid, $cmd);
3202 sub vm_commandline
{
3203 my ($storecfg, $vmid) = @_;
3205 my $conf = load_config
($vmid);
3207 my $defaults = load_defaults
();
3209 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3211 return join(' ', @$cmd);
3215 my ($vmid, $skiplock) = @_;
3217 lock_config
($vmid, sub {
3219 my $conf = load_config
($vmid);
3221 check_lock
($conf) if !$skiplock;
3223 vm_mon_cmd
($vmid, "system_reset");
3227 sub get_vm_volumes
{
3231 foreach_volid
($conf, sub {
3232 my ($volid, $is_cdrom) = @_;
3234 return if $volid =~ m
|^/|;
3236 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3239 push @$vollist, $volid;
3245 sub vm_stop_cleanup
{
3246 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3249 fairsched_rmnod
($vmid); # try to destroy group
3252 my $vollist = get_vm_volumes
($conf);
3253 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3256 foreach my $ext (qw(mon qmp pid vnc qga)) {
3257 unlink "/var/run/qemu-server/${vmid}.$ext";
3260 warn $@ if $@; # avoid errors - just warn
3263 # Note: use $nockeck to skip tests if VM configuration file exists.
3264 # We need that when migration VMs to other nodes (files already moved)
3265 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3267 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3269 $force = 1 if !defined($force) && !$shutdown;
3272 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3273 kill 15, $pid if $pid;
3274 my $conf = load_config
($vmid, $migratedfrom);
3275 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3279 lock_config
($vmid, sub {
3281 my $pid = check_running
($vmid, $nocheck);
3286 $conf = load_config
($vmid);
3287 check_lock
($conf) if !$skiplock;
3288 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3289 my $opts = parse_startup
($conf->{startup
});
3290 $timeout = $opts->{down
} if $opts->{down
};
3294 $timeout = 60 if !defined($timeout);
3298 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3301 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3308 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3313 if ($count >= $timeout) {
3315 warn "VM still running - terminating now with SIGTERM\n";
3318 die "VM quit/powerdown failed - got timeout\n";
3321 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3326 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3329 die "VM quit/powerdown failed\n";
3337 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3342 if ($count >= $timeout) {
3343 warn "VM still running - terminating now with SIGKILL\n";
3348 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3353 my ($vmid, $skiplock) = @_;
3355 lock_config
($vmid, sub {
3357 my $conf = load_config
($vmid);
3359 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3361 vm_mon_cmd
($vmid, "stop");
3366 my ($vmid, $skiplock) = @_;
3368 lock_config
($vmid, sub {
3370 my $conf = load_config
($vmid);
3372 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3374 vm_mon_cmd
($vmid, "cont");
3379 my ($vmid, $skiplock, $key) = @_;
3381 lock_config
($vmid, sub {
3383 my $conf = load_config
($vmid);
3385 # there is no qmp command, so we use the human monitor command
3386 vm_human_monitor_command
($vmid, "sendkey $key");
3391 my ($storecfg, $vmid, $skiplock) = @_;
3393 lock_config
($vmid, sub {
3395 my $conf = load_config
($vmid);
3397 check_lock
($conf) if !$skiplock;
3399 if (!check_running
($vmid)) {
3400 fairsched_rmnod
($vmid); # try to destroy group
3401 destroy_vm
($storecfg, $vmid);
3403 die "VM $vmid is running - destroy failed\n";
3411 my ($filename, $buf) = @_;
3413 my $fh = IO
::File-
>new($filename, "w");
3414 return undef if !$fh;
3416 my $res = print $fh $buf;
3423 sub pci_device_info
{
3428 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3429 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3431 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3432 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3434 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3435 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3437 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3438 return undef if !defined($product) || $product !~ s/^0x//;
3443 product
=> $product,
3449 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3458 my $name = $dev->{name
};
3460 my $fn = "$pcisysfs/devices/$name/reset";
3462 return file_write
($fn, "1");
3465 sub pci_dev_bind_to_stub
{
3468 my $name = $dev->{name
};
3470 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3471 return 1 if -d
$testdir;
3473 my $data = "$dev->{vendor} $dev->{product}";
3474 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3476 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3477 if (!file_write
($fn, $name)) {
3478 return undef if -f
$fn;
3481 $fn = "$pcisysfs/drivers/pci-stub/bind";
3482 if (! -d
$testdir) {
3483 return undef if !file_write
($fn, $name);
3489 sub print_pci_addr
{
3490 my ($id, $bridges) = @_;
3494 piix3
=> { bus
=> 0, addr
=> 1 },
3495 #addr2 : first videocard
3496 balloon0
=> { bus
=> 0, addr
=> 3 },
3497 watchdog
=> { bus
=> 0, addr
=> 4 },
3498 scsihw0
=> { bus
=> 0, addr
=> 5 },
3499 scsihw1
=> { bus
=> 0, addr
=> 6 },
3500 ahci0
=> { bus
=> 0, addr
=> 7 },
3501 qga0
=> { bus
=> 0, addr
=> 8 },
3502 spice
=> { bus
=> 0, addr
=> 9 },
3503 virtio0
=> { bus
=> 0, addr
=> 10 },
3504 virtio1
=> { bus
=> 0, addr
=> 11 },
3505 virtio2
=> { bus
=> 0, addr
=> 12 },
3506 virtio3
=> { bus
=> 0, addr
=> 13 },
3507 virtio4
=> { bus
=> 0, addr
=> 14 },
3508 virtio5
=> { bus
=> 0, addr
=> 15 },
3509 hostpci0
=> { bus
=> 0, addr
=> 16 },
3510 hostpci1
=> { bus
=> 0, addr
=> 17 },
3511 net0
=> { bus
=> 0, addr
=> 18 },
3512 net1
=> { bus
=> 0, addr
=> 19 },
3513 net2
=> { bus
=> 0, addr
=> 20 },
3514 net3
=> { bus
=> 0, addr
=> 21 },
3515 net4
=> { bus
=> 0, addr
=> 22 },
3516 net5
=> { bus
=> 0, addr
=> 23 },
3517 #addr29 : usb-host (pve-usb.cfg)
3518 'pci.1' => { bus
=> 0, addr
=> 30 },
3519 'pci.2' => { bus
=> 0, addr
=> 31 },
3520 'net6' => { bus
=> 1, addr
=> 1 },
3521 'net7' => { bus
=> 1, addr
=> 2 },
3522 'net8' => { bus
=> 1, addr
=> 3 },
3523 'net9' => { bus
=> 1, addr
=> 4 },
3524 'net10' => { bus
=> 1, addr
=> 5 },
3525 'net11' => { bus
=> 1, addr
=> 6 },
3526 'net12' => { bus
=> 1, addr
=> 7 },
3527 'net13' => { bus
=> 1, addr
=> 8 },
3528 'net14' => { bus
=> 1, addr
=> 9 },
3529 'net15' => { bus
=> 1, addr
=> 10 },
3530 'net16' => { bus
=> 1, addr
=> 11 },
3531 'net17' => { bus
=> 1, addr
=> 12 },
3532 'net18' => { bus
=> 1, addr
=> 13 },
3533 'net19' => { bus
=> 1, addr
=> 14 },
3534 'net20' => { bus
=> 1, addr
=> 15 },
3535 'net21' => { bus
=> 1, addr
=> 16 },
3536 'net22' => { bus
=> 1, addr
=> 17 },
3537 'net23' => { bus
=> 1, addr
=> 18 },
3538 'net24' => { bus
=> 1, addr
=> 19 },
3539 'net25' => { bus
=> 1, addr
=> 20 },
3540 'net26' => { bus
=> 1, addr
=> 21 },
3541 'net27' => { bus
=> 1, addr
=> 22 },
3542 'net28' => { bus
=> 1, addr
=> 23 },
3543 'net29' => { bus
=> 1, addr
=> 24 },
3544 'net30' => { bus
=> 1, addr
=> 25 },
3545 'net31' => { bus
=> 1, addr
=> 26 },
3546 'virtio6' => { bus
=> 2, addr
=> 1 },
3547 'virtio7' => { bus
=> 2, addr
=> 2 },
3548 'virtio8' => { bus
=> 2, addr
=> 3 },
3549 'virtio9' => { bus
=> 2, addr
=> 4 },
3550 'virtio10' => { bus
=> 2, addr
=> 5 },
3551 'virtio11' => { bus
=> 2, addr
=> 6 },
3552 'virtio12' => { bus
=> 2, addr
=> 7 },
3553 'virtio13' => { bus
=> 2, addr
=> 8 },
3554 'virtio14' => { bus
=> 2, addr
=> 9 },
3555 'virtio15' => { bus
=> 2, addr
=> 10 },
3558 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3559 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3560 my $bus = $devices->{$id}->{bus
};
3561 $res = ",bus=pci.$bus,addr=$addr";
3562 $bridges->{$bus} = 1 if $bridges;
3568 # vzdump restore implementaion
3570 sub tar_archive_read_firstfile
{
3571 my $archive = shift;
3573 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3575 # try to detect archive type first
3576 my $pid = open (TMP
, "tar tf '$archive'|") ||
3577 die "unable to open file '$archive'\n";
3578 my $firstfile = <TMP
>;
3582 die "ERROR: archive contaions no data\n" if !$firstfile;
3588 sub tar_restore_cleanup
{
3589 my ($storecfg, $statfile) = @_;
3591 print STDERR
"starting cleanup\n";
3593 if (my $fd = IO
::File-
>new($statfile, "r")) {
3594 while (defined(my $line = <$fd>)) {
3595 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3598 if ($volid =~ m
|^/|) {
3599 unlink $volid || die 'unlink failed\n';
3601 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3603 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3605 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3607 print STDERR
"unable to parse line in statfile - $line";
3614 sub restore_archive
{
3615 my ($archive, $vmid, $user, $opts) = @_;
3617 my $format = $opts->{format
};
3620 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3621 $format = 'tar' if !$format;
3623 } elsif ($archive =~ m/\.tar$/) {
3624 $format = 'tar' if !$format;
3625 } elsif ($archive =~ m/.tar.lzo$/) {
3626 $format = 'tar' if !$format;
3628 } elsif ($archive =~ m/\.vma$/) {
3629 $format = 'vma' if !$format;
3630 } elsif ($archive =~ m/\.vma\.gz$/) {
3631 $format = 'vma' if !$format;
3633 } elsif ($archive =~ m/\.vma\.lzo$/) {
3634 $format = 'vma' if !$format;
3637 $format = 'vma' if !$format; # default
3640 # try to detect archive format
3641 if ($format eq 'tar') {
3642 return restore_tar_archive
($archive, $vmid, $user, $opts);
3644 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3648 sub restore_update_config_line
{
3649 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3651 return if $line =~ m/^\#qmdump\#/;
3652 return if $line =~ m/^\#vzdump\#/;
3653 return if $line =~ m/^lock:/;
3654 return if $line =~ m/^unused\d+:/;
3655 return if $line =~ m/^parent:/;
3656 return if $line =~ m/^template:/; # restored VM is never a template
3658 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3659 # try to convert old 1.X settings
3660 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3661 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3662 my ($model, $macaddr) = split(/\=/, $devconfig);
3663 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3666 bridge
=> "vmbr$ind",
3667 macaddr
=> $macaddr,
3669 my $netstr = print_net
($net);
3671 print $outfd "net$cookie->{netcount}: $netstr\n";
3672 $cookie->{netcount
}++;
3674 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3675 my ($id, $netstr) = ($1, $2);
3676 my $net = parse_net
($netstr);
3677 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3678 $netstr = print_net
($net);
3679 print $outfd "$id: $netstr\n";
3680 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3683 if ($line =~ m/backup=no/) {
3684 print $outfd "#$line";
3685 } elsif ($virtdev && $map->{$virtdev}) {
3686 my $di = parse_drive
($virtdev, $value);
3687 delete $di->{format
}; # format can change on restore
3688 $di->{file
} = $map->{$virtdev};
3689 $value = print_drive
($vmid, $di);
3690 print $outfd "$virtdev: $value\n";
3700 my ($cfg, $vmid) = @_;
3702 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3704 my $volid_hash = {};
3705 foreach my $storeid (keys %$info) {
3706 foreach my $item (@{$info->{$storeid}}) {
3707 next if !($item->{volid
} && $item->{size
});
3708 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
3709 $volid_hash->{$item->{volid
}} = $item;
3716 sub get_used_paths
{
3717 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
3721 my $scan_config = sub {
3722 my ($cref, $snapname) = @_;
3724 foreach my $key (keys %$cref) {
3725 my $value = $cref->{$key};
3726 if (valid_drivename
($key)) {
3727 next if $skip_drive && $key eq $skip_drive;
3728 my $drive = parse_drive
($key, $value);
3729 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
3730 if ($drive->{file
} =~ m!^/!) {
3731 $used_path->{$drive->{file
}}++; # = 1;
3733 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
3735 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
3737 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
3738 $used_path->{$path}++; # = 1;
3744 &$scan_config($conf);
3748 if ($scan_snapshots) {
3749 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3750 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
3757 sub update_disksize
{
3758 my ($vmid, $conf, $volid_hash) = @_;
3764 # Note: it is allowed to define multiple storages with same path (alias), so
3765 # we need to check both 'volid' and real 'path' (two different volid can point
3766 # to the same path).
3771 foreach my $opt (keys %$conf) {
3772 if (valid_drivename
($opt)) {
3773 my $drive = parse_drive
($opt, $conf->{$opt});
3774 my $volid = $drive->{file
};
3777 $used->{$volid} = 1;
3778 if ($volid_hash->{$volid} &&
3779 (my $path = $volid_hash->{$volid}->{path
})) {
3780 $usedpath->{$path} = 1;
3783 next if drive_is_cdrom
($drive);
3784 next if !$volid_hash->{$volid};
3786 $drive->{size
} = $volid_hash->{$volid}->{size
};
3787 my $new = print_drive
($vmid, $drive);
3788 if ($new ne $conf->{$opt}) {
3790 $conf->{$opt} = $new;
3795 # remove 'unusedX' entry if volume is used
3796 foreach my $opt (keys %$conf) {
3797 next if $opt !~ m/^unused\d+$/;
3798 my $volid = $conf->{$opt};
3799 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
3800 if ($used->{$volid} || ($path && $usedpath->{$path})) {
3802 delete $conf->{$opt};
3806 foreach my $volid (sort keys %$volid_hash) {
3807 next if $volid =~ m/vm-$vmid-state-/;
3808 next if $used->{$volid};
3809 my $path = $volid_hash->{$volid}->{path
};
3810 next if !$path; # just to be sure
3811 next if $usedpath->{$path};
3813 add_unused_volume
($conf, $volid);
3814 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
3821 my ($vmid, $nolock) = @_;
3823 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3825 my $volid_hash = scan_volids
($cfg, $vmid);
3827 my $updatefn = sub {
3830 my $conf = load_config
($vmid);
3835 foreach my $volid (keys %$volid_hash) {
3836 my $info = $volid_hash->{$volid};
3837 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
3840 my $changes = update_disksize
($vmid, $conf, $vm_volids);
3842 update_config_nolock
($vmid, $conf, 1) if $changes;
3845 if (defined($vmid)) {
3849 lock_config
($vmid, $updatefn, $vmid);
3852 my $vmlist = config_list
();
3853 foreach my $vmid (keys %$vmlist) {
3857 lock_config
($vmid, $updatefn, $vmid);
3863 sub restore_vma_archive
{
3864 my ($archive, $vmid, $user, $opts, $comp) = @_;
3866 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3867 my $readfrom = $archive;
3872 my $qarchive = PVE
::Tools
::shellquote
($archive);
3873 if ($comp eq 'gzip') {
3874 $uncomp = "zcat $qarchive|";
3875 } elsif ($comp eq 'lzop') {
3876 $uncomp = "lzop -d -c $qarchive|";
3878 die "unknown compression method '$comp'\n";
3883 my $tmpdir = "/var/tmp/vzdumptmp$$";
3886 # disable interrupts (always do cleanups)
3887 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3888 warn "got interrupt - ignored\n";
3891 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3892 POSIX
::mkfifo
($mapfifo, 0600);
3895 my $openfifo = sub {
3896 open($fifofh, '>', $mapfifo) || die $!;
3899 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3906 my $rpcenv = PVE
::RPCEnvironment
::get
();
3908 my $conffile = config_file
($vmid);
3909 my $tmpfn = "$conffile.$$.tmp";
3911 # Note: $oldconf is undef if VM does not exists
3912 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3914 my $print_devmap = sub {
3915 my $virtdev_hash = {};
3917 my $cfgfn = "$tmpdir/qemu-server.conf";
3919 # we can read the config - that is already extracted
3920 my $fh = IO
::File-
>new($cfgfn, "r") ||
3921 "unable to read qemu-server.conf - $!\n";
3923 while (defined(my $line = <$fh>)) {
3924 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3925 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3926 die "archive does not contain data for drive '$virtdev'\n"
3927 if !$devinfo->{$devname};
3928 if (defined($opts->{storage
})) {
3929 $storeid = $opts->{storage
} || 'local';
3930 } elsif (!$storeid) {
3933 $format = 'raw' if !$format;
3934 $devinfo->{$devname}->{devname
} = $devname;
3935 $devinfo->{$devname}->{virtdev
} = $virtdev;
3936 $devinfo->{$devname}->{format
} = $format;
3937 $devinfo->{$devname}->{storeid
} = $storeid;
3939 # check permission on storage
3940 my $pool = $opts->{pool
}; # todo: do we need that?
3941 if ($user ne 'root@pam') {
3942 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3945 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3949 foreach my $devname (keys %$devinfo) {
3950 die "found no device mapping information for device '$devname'\n"
3951 if !$devinfo->{$devname}->{virtdev
};
3954 my $cfg = cfs_read_file
('storage.cfg');
3956 # create empty/temp config
3958 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3959 foreach_drive
($oldconf, sub {
3960 my ($ds, $drive) = @_;
3962 return if drive_is_cdrom
($drive);
3964 my $volid = $drive->{file
};
3966 return if !$volid || $volid =~ m
|^/|;
3968 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3969 return if !$path || !$owner || ($owner != $vmid);
3971 # Note: only delete disk we want to restore
3972 # other volumes will become unused
3973 if ($virtdev_hash->{$ds}) {
3974 PVE
::Storage
::vdisk_free
($cfg, $volid);
3980 foreach my $virtdev (sort keys %$virtdev_hash) {
3981 my $d = $virtdev_hash->{$virtdev};
3982 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3983 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3985 # test if requested format is supported
3986 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
3987 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
3988 $d->{format
} = $defFormat if !$supported;
3990 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3991 $d->{format
}, undef, $alloc_size);
3992 print STDERR
"new volume ID is '$volid'\n";
3993 $d->{volid
} = $volid;
3994 my $path = PVE
::Storage
::path
($cfg, $volid);
3996 my $write_zeros = 1;
3997 # fixme: what other storages types initialize volumes with zero?
3998 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
3999 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
4003 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4005 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4006 $map->{$virtdev} = $volid;
4009 $fh->seek(0, 0) || die "seek failed - $!\n";
4011 my $outfd = new IO
::File
($tmpfn, "w") ||
4012 die "unable to write config for VM $vmid\n";
4014 my $cookie = { netcount
=> 0 };
4015 while (defined(my $line = <$fh>)) {
4016 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4025 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4026 die "interrupted by signal\n";
4028 local $SIG{ALRM
} = sub { die "got timeout\n"; };
4030 $oldtimeout = alarm($timeout);
4037 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4038 my ($dev_id, $size, $devname) = ($1, $2, $3);
4039 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
4040 } elsif ($line =~ m/^CTIME: /) {
4042 print $fifofh "done\n";
4043 my $tmp = $oldtimeout || 0;
4044 $oldtimeout = undef;
4050 print "restore vma archive: $cmd\n";
4051 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
4055 alarm($oldtimeout) if $oldtimeout;
4063 my $cfg = cfs_read_file
('storage.cfg');
4064 foreach my $devname (keys %$devinfo) {
4065 my $volid = $devinfo->{$devname}->{volid
};
4068 if ($volid =~ m
|^/|) {
4069 unlink $volid || die 'unlink failed\n';
4071 PVE
::Storage
::vdisk_free
($cfg, $volid);
4073 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4075 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4082 rename($tmpfn, $conffile) ||
4083 die "unable to commit configuration file '$conffile'\n";
4085 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4087 eval { rescan
($vmid, 1); };
4091 sub restore_tar_archive
{
4092 my ($archive, $vmid, $user, $opts) = @_;
4094 if ($archive ne '-') {
4095 my $firstfile = tar_archive_read_firstfile
($archive);
4096 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4097 if $firstfile ne 'qemu-server.conf';
4100 my $storecfg = cfs_read_file
('storage.cfg');
4102 # destroy existing data - keep empty config
4103 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
4104 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
4106 my $tocmd = "/usr/lib/qemu-server/qmextract";
4108 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
4109 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
4110 $tocmd .= ' --prealloc' if $opts->{prealloc
};
4111 $tocmd .= ' --info' if $opts->{info
};
4113 # tar option "xf" does not autodetect compression when read from STDIN,
4114 # so we pipe to zcat
4115 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
4116 PVE
::Tools
::shellquote
("--to-command=$tocmd");
4118 my $tmpdir = "/var/tmp/vzdumptmp$$";
4121 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
4122 local $ENV{VZDUMP_VMID
} = $vmid;
4123 local $ENV{VZDUMP_USER
} = $user;
4125 my $conffile = config_file
($vmid);
4126 my $tmpfn = "$conffile.$$.tmp";
4128 # disable interrupts (always do cleanups)
4129 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
4130 print STDERR
"got interrupt - ignored\n";
4135 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
4136 die "interrupted by signal\n";
4139 if ($archive eq '-') {
4140 print "extracting archive from STDIN\n";
4141 run_command
($cmd, input
=> "<&STDIN");
4143 print "extracting archive '$archive'\n";
4147 return if $opts->{info
};
4151 my $statfile = "$tmpdir/qmrestore.stat";
4152 if (my $fd = IO
::File-
>new($statfile, "r")) {
4153 while (defined (my $line = <$fd>)) {
4154 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4155 $map->{$1} = $2 if $1;
4157 print STDERR
"unable to parse line in statfile - $line\n";
4163 my $confsrc = "$tmpdir/qemu-server.conf";
4165 my $srcfd = new IO
::File
($confsrc, "r") ||
4166 die "unable to open file '$confsrc'\n";
4168 my $outfd = new IO
::File
($tmpfn, "w") ||
4169 die "unable to write config for VM $vmid\n";
4171 my $cookie = { netcount
=> 0 };
4172 while (defined (my $line = <$srcfd>)) {
4173 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
4185 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
4192 rename $tmpfn, $conffile ||
4193 die "unable to commit configuration file '$conffile'\n";
4195 PVE
::Cluster
::cfs_update
(); # make sure we read new file
4197 eval { rescan
($vmid, 1); };
4202 # Internal snapshots
4204 # NOTE: Snapshot create/delete involves several non-atomic
4205 # action, and can take a long time.
4206 # So we try to avoid locking the file and use 'lock' variable
4207 # inside the config file instead.
4209 my $snapshot_copy_config = sub {
4210 my ($source, $dest) = @_;
4212 foreach my $k (keys %$source) {
4213 next if $k eq 'snapshots';
4214 next if $k eq 'snapstate';
4215 next if $k eq 'snaptime';
4216 next if $k eq 'vmstate';
4217 next if $k eq 'lock';
4218 next if $k eq 'digest';
4219 next if $k eq 'description';
4220 next if $k =~ m/^unused\d+$/;
4222 $dest->{$k} = $source->{$k};
4226 my $snapshot_apply_config = sub {
4227 my ($conf, $snap) = @_;
4229 # copy snapshot list
4231 snapshots
=> $conf->{snapshots
},
4234 # keep description and list of unused disks
4235 foreach my $k (keys %$conf) {
4236 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4237 $newconf->{$k} = $conf->{$k};
4240 &$snapshot_copy_config($snap, $newconf);
4245 sub foreach_writable_storage
{
4246 my ($conf, $func) = @_;
4250 foreach my $ds (keys %$conf) {
4251 next if !valid_drivename
($ds);
4253 my $drive = parse_drive
($ds, $conf->{$ds});
4255 next if drive_is_cdrom
($drive);
4257 my $volid = $drive->{file
};
4259 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4260 $sidhash->{$sid} = $sid if $sid;
4263 foreach my $sid (sort keys %$sidhash) {
4268 my $alloc_vmstate_volid = sub {
4269 my ($storecfg, $vmid, $conf, $snapname) = @_;
4271 # Note: we try to be smart when selecting a $target storage
4275 # search shared storage first
4276 foreach_writable_storage
($conf, sub {
4278 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4279 return if !$scfg->{shared
};
4281 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4285 # now search local storage
4286 foreach_writable_storage
($conf, sub {
4288 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4289 return if $scfg->{shared
};
4291 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4295 $target = 'local' if !$target;
4297 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4298 # we abort live save after $conf->{memory}, so we need at max twice that space
4299 my $size = $conf->{memory
}*2 + $driver_state_size;
4301 my $name = "vm-$vmid-state-$snapname";
4302 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4303 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4304 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4309 my $snapshot_prepare = sub {
4310 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4314 my $updatefn = sub {
4316 my $conf = load_config
($vmid);
4318 die "you can't take a snapshot if it's a template\n"
4319 if is_template
($conf);
4323 $conf->{lock} = 'snapshot';
4325 die "snapshot name '$snapname' already used\n"
4326 if defined($conf->{snapshots
}->{$snapname});
4328 my $storecfg = PVE
::Storage
::config
();
4329 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4331 $snap = $conf->{snapshots
}->{$snapname} = {};
4333 if ($save_vmstate && check_running
($vmid)) {
4334 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4337 &$snapshot_copy_config($conf, $snap);
4339 $snap->{snapstate
} = "prepare";
4340 $snap->{snaptime
} = time();
4341 $snap->{description
} = $comment if $comment;
4343 # always overwrite machine if we save vmstate. This makes sure we
4344 # can restore it later using correct machine type
4345 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
4347 update_config_nolock
($vmid, $conf, 1);
4350 lock_config
($vmid, $updatefn);
4355 my $snapshot_commit = sub {
4356 my ($vmid, $snapname) = @_;
4358 my $updatefn = sub {
4360 my $conf = load_config
($vmid);
4362 die "missing snapshot lock\n"
4363 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4365 my $snap = $conf->{snapshots
}->{$snapname};
4367 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4369 die "wrong snapshot state\n"
4370 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4372 delete $snap->{snapstate
};
4373 delete $conf->{lock};
4375 my $newconf = &$snapshot_apply_config($conf, $snap);
4377 $newconf->{parent
} = $snapname;
4379 update_config_nolock
($vmid, $newconf, 1);
4382 lock_config
($vmid, $updatefn);
4385 sub snapshot_rollback
{
4386 my ($vmid, $snapname) = @_;
4392 my $storecfg = PVE
::Storage
::config
();
4394 my $updatefn = sub {
4396 my $conf = load_config
($vmid);
4398 die "you can't rollback if vm is a template\n" if is_template
($conf);
4400 $snap = $conf->{snapshots
}->{$snapname};
4402 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4404 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4405 if $snap->{snapstate
};
4409 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4412 die "unable to rollback vm $vmid: vm is running\n"
4413 if check_running
($vmid);
4416 $conf->{lock} = 'rollback';
4418 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4419 delete $conf->{lock};
4425 my $has_machine_config = defined($conf->{machine
});
4427 # copy snapshot config to current config
4428 $conf = &$snapshot_apply_config($conf, $snap);
4429 $conf->{parent
} = $snapname;
4431 # Note: old code did not store 'machine', so we try to be smart
4432 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4433 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
4434 # we remove the 'machine' configuration if not explicitly specified
4435 # in the original config.
4436 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
4439 update_config_nolock
($vmid, $conf, 1);
4441 if (!$prepare && $snap->{vmstate
}) {
4442 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4443 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
4447 lock_config
($vmid, $updatefn);
4449 foreach_drive
($snap, sub {
4450 my ($ds, $drive) = @_;
4452 return if drive_is_cdrom
($drive);
4454 my $volid = $drive->{file
};
4455 my $device = "drive-$ds";
4457 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4461 lock_config
($vmid, $updatefn);
4464 my $savevm_wait = sub {
4468 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4469 if (!$stat->{status
}) {
4470 die "savevm not active\n";
4471 } elsif ($stat->{status
} eq 'active') {
4474 } elsif ($stat->{status
} eq 'completed') {
4477 die "query-savevm returned status '$stat->{status}'\n";
4482 sub snapshot_create
{
4483 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4485 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4487 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4491 my $running = check_running
($vmid);
4494 # create internal snapshots of all drives
4496 my $storecfg = PVE
::Storage
::config
();
4499 if ($snap->{vmstate
}) {
4500 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4501 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4502 &$savevm_wait($vmid);
4504 vm_mon_cmd
($vmid, "savevm-start");
4508 qga_freezefs
($vmid) if $running && $freezefs;
4510 foreach_drive
($snap, sub {
4511 my ($ds, $drive) = @_;
4513 return if drive_is_cdrom
($drive);
4515 my $volid = $drive->{file
};
4516 my $device = "drive-$ds";
4518 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4519 $drivehash->{$ds} = 1;
4524 eval { qga_unfreezefs
($vmid) if $running && $freezefs; };
4527 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4531 warn "snapshot create failed: starting cleanup\n";
4532 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4537 &$snapshot_commit($vmid, $snapname);
4540 # Note: $drivehash is only set when called from snapshot_create.
4541 sub snapshot_delete
{
4542 my ($vmid, $snapname, $force, $drivehash) = @_;
4549 my $unlink_parent = sub {
4550 my ($confref, $new_parent) = @_;
4552 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4554 $confref->{parent
} = $new_parent;
4556 delete $confref->{parent
};
4561 my $updatefn = sub {
4562 my ($remove_drive) = @_;
4564 my $conf = load_config
($vmid);
4568 die "you can't delete a snapshot if vm is a template\n"
4569 if is_template
($conf);
4572 $snap = $conf->{snapshots
}->{$snapname};
4574 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4576 # remove parent refs
4577 &$unlink_parent($conf, $snap->{parent
});
4578 foreach my $sn (keys %{$conf->{snapshots
}}) {
4579 next if $sn eq $snapname;
4580 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4583 if ($remove_drive) {
4584 if ($remove_drive eq 'vmstate') {
4585 delete $snap->{$remove_drive};
4587 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4588 my $volid = $drive->{file
};
4589 delete $snap->{$remove_drive};
4590 add_unused_volume
($conf, $volid);
4595 $snap->{snapstate
} = 'delete';
4597 delete $conf->{snapshots
}->{$snapname};
4598 delete $conf->{lock} if $drivehash;
4599 foreach my $volid (@$unused) {
4600 add_unused_volume
($conf, $volid);
4604 update_config_nolock
($vmid, $conf, 1);
4607 lock_config
($vmid, $updatefn);
4609 # now remove vmstate file
4611 my $storecfg = PVE
::Storage
::config
();
4613 if ($snap->{vmstate
}) {
4614 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4616 die $err if !$force;
4619 # save changes (remove vmstate from snapshot)
4620 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4623 # now remove all internal snapshots
4624 foreach_drive
($snap, sub {
4625 my ($ds, $drive) = @_;
4627 return if drive_is_cdrom
($drive);
4629 my $volid = $drive->{file
};
4630 my $device = "drive-$ds";
4632 if (!$drivehash || $drivehash->{$ds}) {
4633 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4635 die $err if !$force;
4640 # save changes (remove drive fron snapshot)
4641 lock_config
($vmid, $updatefn, $ds) if !$force;
4642 push @$unused, $volid;
4645 # now cleanup config
4647 lock_config
($vmid, $updatefn);
4651 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4654 foreach_drive
($conf, sub {
4655 my ($ds, $drive) = @_;
4657 return if drive_is_cdrom
($drive);
4658 my $volid = $drive->{file
};
4659 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4662 return $err ?
0 : 1;
4665 sub template_create
{
4666 my ($vmid, $conf, $disk) = @_;
4668 my $storecfg = PVE
::Storage
::config
();
4670 foreach_drive
($conf, sub {
4671 my ($ds, $drive) = @_;
4673 return if drive_is_cdrom
($drive);
4674 return if $disk && $ds ne $disk;
4676 my $volid = $drive->{file
};
4677 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4679 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4680 $drive->{file
} = $voliddst;
4681 $conf->{$ds} = print_drive
($vmid, $drive);
4682 update_config_nolock
($vmid, $conf, 1);
4689 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
4692 sub qemu_img_convert
{
4693 my ($src_volid, $dst_volid, $size, $snapname) = @_;
4695 my $storecfg = PVE
::Storage
::config
();
4696 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
4697 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4699 if ($src_storeid && $dst_storeid) {
4700 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
4701 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4703 my $src_format = qemu_img_format
($src_scfg, $src_volname);
4704 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
4706 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
4707 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4710 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C';
4711 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
4712 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
4716 if($line =~ m/\((\S+)\/100\
%\)/){
4718 my $transferred = int($size * $percent / 100);
4719 my $remaining = $size - $transferred;
4721 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
4726 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
4728 die "copy failed: $err" if $err;
4732 sub qemu_img_format
{
4733 my ($scfg, $volname) = @_;
4735 if ($scfg->{path
} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
4737 } elsif ($scfg->{type
} eq 'iscsi') {
4738 return "host_device";
4744 sub qemu_drive_mirror
{
4745 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
4751 my $storecfg = PVE
::Storage
::config
();
4752 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
4755 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
4758 if ($dst_volname =~ m/\.(raw|qcow2)$/){
4762 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
4765 #fixme : sometime drive-mirror timeout, but works fine after.
4766 # (I have see the problem with big volume > 200GB), so we need to eval
4767 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4768 sync
=> "full", target
=> $dst_path, format
=> $format); };
4770 eval { vm_mon_cmd
($vmid, "drive-mirror", timeout
=> 10, device
=> "drive-$drive", mode
=> "existing",
4771 sync
=> "full", target
=> $dst_path); };
4776 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
4777 my $stat = @$stats[0];
4778 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
4779 die "error job is not mirroring" if $stat->{type
} ne "mirror";
4781 my $transferred = $stat->{offset
};
4782 my $total = $stat->{len
};
4783 my $remaining = $total - $transferred;
4784 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
4786 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
4788 last if ($stat->{len
} == $stat->{offset
});
4789 if ($old_len == $stat->{offset
}) {
4790 if ($maxwait && $count > $maxwait) {
4791 # if writes to disk occurs the disk needs to be freezed
4792 # to be able to complete the migration
4793 vm_suspend
($vmid,1);
4797 $count++ unless $frozen;
4803 $old_len = $stat->{offset
};
4807 if ($vmiddst == $vmid) {
4808 # switch the disk if source and destination are on the same guest
4809 vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive");
4813 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive"); };
4814 die "mirroring error: $err";
4817 if ($vmiddst != $vmid) {
4818 # if we clone a disk for a new target vm, we don't switch the disk
4819 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
4825 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
4826 $newvmid, $storage, $format, $full, $newvollist) = @_;
4831 print "create linked clone of drive $drivename ($drive->{file})\n";
4832 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid);
4833 push @$newvollist, $newvolid;
4835 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
4836 $storeid = $storage if $storage;
4838 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
4840 $format = $drive->{format
} || $defFormat;
4843 # test if requested format is supported - else use default
4844 my $supported = grep { $_ eq $format } @$validFormats;
4845 $format = $defFormat if !$supported;
4847 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
4849 print "create full clone of drive $drivename ($drive->{file})\n";
4850 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
4851 push @$newvollist, $newvolid;
4853 if (!$running || $snapname) {
4854 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
4856 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
4860 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
4863 $disk->{format
} = undef;
4864 $disk->{file
} = $newvolid;
4865 $disk->{size
} = $size;
4870 # this only works if VM is running
4871 sub get_current_qemu_machine
{
4874 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
4875 my $res = PVE
::QemuServer
::vm_qmp_command
($vmid, $cmd);
4877 my ($current, $default);
4878 foreach my $e (@$res) {
4879 $default = $e->{name
} if $e->{'is-default'};
4880 $current = $e->{name
} if $e->{'is-current'};
4883 # fallback to the default machine if current is not supported by qemu
4884 return $current || $default || 'pc';
4887 sub read_x509_subject_spice
{
4888 my ($filename) = @_;
4891 my $bio = Net
::SSLeay
::BIO_new_file
($filename, 'r');
4892 my $x509 = Net
::SSLeay
::PEM_read_bio_X509
($bio);
4893 Net
::SSLeay
::BIO_free
($bio);
4894 my $nameobj = Net
::SSLeay
::X509_get_subject_name
($x509);
4895 my $subject = Net
::SSLeay
::X509_NAME_oneline
($nameobj);
4896 Net
::SSLeay
::X509_free
($x509);
4898 # remote-viewer wants comma as seperator (not '/')
4900 $subject =~ s!/(\w+=)!,$1!g;