]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
add pci multifunction support
[qemu-server.git] / PVE / QemuServer.pm
CommitLineData
1e3baf05
DM
1package PVE::QemuServer;
2
3use strict;
990fc5e2 4use warnings;
1e3baf05
DM
5use POSIX;
6use IO::Handle;
7use IO::Select;
8use IO::File;
9use IO::Dir;
10use IO::Socket::UNIX;
11use File::Basename;
12use File::Path;
13use File::stat;
14use Getopt::Long;
fc1ddcdc 15use Digest::SHA;
1e3baf05
DM
16use Fcntl ':flock';
17use Cwd 'abs_path';
18use IPC::Open3;
c971c4f2 19use JSON;
1e3baf05
DM
20use Fcntl;
21use PVE::SafeSyslog;
22use Storable qw(dclone);
23use PVE::Exception qw(raise raise_param_exc);
24use PVE::Storage;
4543ecf0 25use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
b7ba6b79 26use PVE::JSONSchema qw(get_standard_option);
1e3baf05
DM
27use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
28use PVE::INotify;
29use PVE::ProcFSTools;
26f11676 30use PVE::QMPClient;
91bd6c90 31use PVE::RPCEnvironment;
6b64503e 32use Time::HiRes qw(gettimeofday);
1e3baf05 33
7f0b5beb 34my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 35
19672434 36# Note about locking: we use flock on the config file protect
1e3baf05
DM
37# against concurent actions.
38# Aditionaly, we have a 'lock' setting in the config file. This
22c377f0 39# can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
1e3baf05
DM
40# allowed when such lock is set. But you can ignore this kind of
41# lock with the --skiplock flag.
42
97d62eb7 43cfs_register_file('/qemu-server/',
1858638f
DM
44 \&parse_vm_config,
45 \&write_vm_config);
1e3baf05 46
3ea94c60
DM
47PVE::JSONSchema::register_standard_option('skiplock', {
48 description => "Ignore locks - only root is allowed to use this option.",
afdb31d5 49 type => 'boolean',
3ea94c60
DM
50 optional => 1,
51});
52
53PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
54 description => "Some command save/restore state from this location.",
55 type => 'string',
56 maxLength => 128,
57 optional => 1,
58});
59
8abd398b
DM
60PVE::JSONSchema::register_standard_option('pve-snapshot-name', {
61 description => "The name of the snapshot.",
62 type => 'string', format => 'pve-configid',
63 maxLength => 40,
64});
65
1e3baf05
DM
66#no warnings 'redefine';
67
68unless(defined(&_VZSYSCALLS_H_)) {
69 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_);
70 require 'sys/syscall.ph';
71 if(defined(&__x86_64__)) {
72 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus);
73 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod);
74 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod);
75 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt);
76 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr);
77 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate);
78 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid);
79 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit);
80 }
81 elsif(defined( &__i386__) ) {
82 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod);
83 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod);
84 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt);
85 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr);
86 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate);
87 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus);
88 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid);
89 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit);
90 } else {
91 die("no fairsched syscall for this arch");
92 }
93 require 'asm/ioctl.ph';
94 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION);
95}
96
97sub fairsched_mknod {
98 my ($parent, $weight, $desired) = @_;
99
6b64503e 100 return syscall(&__NR_fairsched_mknod, int($parent), int($weight), int($desired));
1e3baf05
DM
101}
102
103sub fairsched_rmnod {
104 my ($id) = @_;
105
6b64503e 106 return syscall(&__NR_fairsched_rmnod, int($id));
1e3baf05
DM
107}
108
109sub fairsched_mvpr {
110 my ($pid, $newid) = @_;
111
6b64503e 112 return syscall(&__NR_fairsched_mvpr, int($pid), int($newid));
1e3baf05
DM
113}
114
115sub fairsched_vcpus {
116 my ($id, $vcpus) = @_;
117
6b64503e 118 return syscall(&__NR_fairsched_vcpus, int($id), int($vcpus));
1e3baf05
DM
119}
120
121sub fairsched_rate {
122 my ($id, $op, $rate) = @_;
123
6b64503e 124 return syscall(&__NR_fairsched_rate, int($id), int($op), int($rate));
1e3baf05
DM
125}
126
127use constant FAIRSCHED_SET_RATE => 0;
128use constant FAIRSCHED_DROP_RATE => 1;
129use constant FAIRSCHED_GET_RATE => 2;
130
131sub fairsched_cpulimit {
132 my ($id, $limit) = @_;
133
6b64503e 134 my $cpulim1024 = int($limit * 1024 / 100);
1e3baf05
DM
135 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
136
6b64503e 137 return fairsched_rate($id, $op, $cpulim1024);
1e3baf05
DM
138}
139
140my $nodename = PVE::INotify::nodename();
141
142mkdir "/etc/pve/nodes/$nodename";
143my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
144mkdir $confdir;
145
146my $var_run_tmpdir = "/var/run/qemu-server";
147mkdir $var_run_tmpdir;
148
149my $lock_dir = "/var/lock/qemu-server";
150mkdir $lock_dir;
151
152my $pcisysfs = "/sys/bus/pci";
153
1e3baf05
DM
154my $confdesc = {
155 onboot => {
156 optional => 1,
157 type => 'boolean',
158 description => "Specifies whether a VM will be started during system bootup.",
159 default => 0,
160 },
161 autostart => {
162 optional => 1,
163 type => 'boolean',
164 description => "Automatic restart after crash (currently ignored).",
165 default => 0,
166 },
2ff09f52
DA
167 hotplug => {
168 optional => 1,
e8b9c17c 169 type => 'boolean',
6c52b679 170 description => "Allow hotplug for disk and network device",
2dbe827e 171 default => 0,
2ff09f52 172 },
1e3baf05
DM
173 reboot => {
174 optional => 1,
175 type => 'boolean',
176 description => "Allow reboot. If set to '0' the VM exit on reboot.",
177 default => 1,
178 },
179 lock => {
180 optional => 1,
181 type => 'string',
182 description => "Lock/unlock the VM.",
22c377f0 183 enum => [qw(migrate backup snapshot rollback)],
1e3baf05
DM
184 },
185 cpulimit => {
186 optional => 1,
187 type => 'integer',
188 description => "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
189 minimum => 0,
190 default => 0,
191 },
192 cpuunits => {
193 optional => 1,
194 type => 'integer',
195 description => "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
196 minimum => 0,
197 maximum => 500000,
198 default => 1000,
199 },
200 memory => {
201 optional => 1,
202 type => 'integer',
7878afeb 203 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
204 minimum => 16,
205 default => 512,
206 },
13a48620
DA
207 balloon => {
208 optional => 1,
209 type => 'integer',
8b1accf7
DM
210 description => "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
211 minimum => 0,
212 },
213 shares => {
214 optional => 1,
215 type => 'integer',
216 description => "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
217 minimum => 0,
218 maximum => 50000,
219 default => 1000,
13a48620 220 },
1e3baf05
DM
221 keyboard => {
222 optional => 1,
223 type => 'string',
224 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
e95fe75f 225 enum => PVE::Tools::kvmkeymaplist(),
1e3baf05
DM
226 default => 'en-us',
227 },
228 name => {
229 optional => 1,
7fabe17d 230 type => 'string', format => 'dns-name',
1e3baf05
DM
231 description => "Set a name for the VM. Only used on the configuration web interface.",
232 },
cdd20088
AD
233 scsihw => {
234 optional => 1,
235 type => 'string',
236 description => "scsi controller model",
5b952ff5 237 enum => [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)],
cdd20088
AD
238 default => 'lsi',
239 },
1e3baf05
DM
240 description => {
241 optional => 1,
242 type => 'string',
0581fe4f 243 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
1e3baf05
DM
244 },
245 ostype => {
246 optional => 1,
247 type => 'string',
6b9d84cf 248 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
1e3baf05
DM
249 description => <<EODESC,
250Used to enable special optimization/features for specific
251operating systems:
252
253other => unspecified OS
254wxp => Microsoft Windows XP
255w2k => Microsoft Windows 2000
256w2k3 => Microsoft Windows 2003
257w2k8 => Microsoft Windows 2008
258wvista => Microsoft Windows Vista
259win7 => Microsoft Windows 7
a70ebde3 260win8 => Microsoft Windows 8/2012
1e3baf05
DM
261l24 => Linux 2.4 Kernel
262l26 => Linux 2.6/3.X Kernel
6b9d84cf 263solaris => solaris/opensolaris/openindiania kernel
1e3baf05 264
6b9d84cf 265other|l24|l26|solaris ... no special behaviour
a70ebde3 266wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
1e3baf05
DM
267EODESC
268 },
269 boot => {
270 optional => 1,
271 type => 'string',
272 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
273 pattern => '[acdn]{1,4}',
32baffb4 274 default => 'cdn',
1e3baf05
DM
275 },
276 bootdisk => {
277 optional => 1,
278 type => 'string', format => 'pve-qm-bootdisk',
279 description => "Enable booting from specified disk.",
03e480fc 280 pattern => '(ide|sata|scsi|virtio)\d+',
1e3baf05
DM
281 },
282 smp => {
283 optional => 1,
284 type => 'integer',
285 description => "The number of CPUs. Please use option -sockets instead.",
286 minimum => 1,
287 default => 1,
288 },
289 sockets => {
290 optional => 1,
291 type => 'integer',
292 description => "The number of CPU sockets.",
293 minimum => 1,
294 default => 1,
295 },
296 cores => {
297 optional => 1,
298 type => 'integer',
299 description => "The number of cores per socket.",
300 minimum => 1,
301 default => 1,
302 },
3bd18e48
AD
303 maxcpus => {
304 optional => 1,
305 type => 'integer',
306 description => "Maximum cpus for hotplug.",
307 minimum => 1,
308 default => 1,
309 },
1e3baf05
DM
310 acpi => {
311 optional => 1,
312 type => 'boolean',
313 description => "Enable/disable ACPI.",
314 default => 1,
315 },
bc84dcca 316 agent => {
ab6a046f
AD
317 optional => 1,
318 type => 'boolean',
319 description => "Enable/disable Qemu GuestAgent.",
be79c214 320 default => 0,
ab6a046f 321 },
1e3baf05
DM
322 kvm => {
323 optional => 1,
324 type => 'boolean',
325 description => "Enable/disable KVM hardware virtualization.",
326 default => 1,
327 },
328 tdf => {
329 optional => 1,
330 type => 'boolean',
8c559505
DM
331 description => "Enable/disable time drift fix.",
332 default => 0,
1e3baf05 333 },
19672434 334 localtime => {
1e3baf05
DM
335 optional => 1,
336 type => 'boolean',
337 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
338 },
339 freeze => {
340 optional => 1,
341 type => 'boolean',
342 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
343 },
344 vga => {
345 optional => 1,
346 type => 'string',
ef5e2be2 347 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.",
2fa3151e 348 enum => [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
1e3baf05 349 },
0ea9541d
DM
350 watchdog => {
351 optional => 1,
352 type => 'string', format => 'pve-qm-watchdog',
353 typetext => '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
354 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)",
355 },
1e3baf05
DM
356 startdate => {
357 optional => 1,
19672434 358 type => 'string',
1e3baf05
DM
359 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
360 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'.",
361 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
362 default => 'now',
363 },
59411c4e
DM
364 startup => {
365 optional => 1,
366 type => 'string', format => 'pve-qm-startup',
367 typetext => '[[order=]\d+] [,up=\d+] [,down=\d+] ',
368 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.",
369 },
68eda3ab
AD
370 template => {
371 optional => 1,
372 type => 'boolean',
373 description => "Enable/disable Template.",
374 default => 0,
375 },
1e3baf05
DM
376 args => {
377 optional => 1,
378 type => 'string',
379 description => <<EODESCR,
380Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
381
382args: -no-reboot -no-hpet
383EODESCR
384 },
385 tablet => {
386 optional => 1,
387 type => 'boolean',
388 default => 1,
5acbfe9e 389 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).",
1e3baf05
DM
390 },
391 migrate_speed => {
392 optional => 1,
393 type => 'integer',
394 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
395 minimum => 0,
396 default => 0,
397 },
398 migrate_downtime => {
399 optional => 1,
04432191 400 type => 'number',
1e3baf05
DM
401 description => "Set maximum tolerated downtime (in seconds) for migrations.",
402 minimum => 0,
04432191 403 default => 0.1,
1e3baf05
DM
404 },
405 cdrom => {
406 optional => 1,
407 type => 'string', format => 'pve-qm-drive',
408 typetext => 'volume',
409 description => "This is an alias for option -ide2",
410 },
411 cpu => {
412 optional => 1,
413 description => "Emulated CPU type.",
414 type => 'string',
98a0dc5e 415 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) ],
eac6899d 416 default => 'kvm64',
1e3baf05 417 },
b7ba6b79
DM
418 parent => get_standard_option('pve-snapshot-name', {
419 optional => 1,
420 description => "Parent snapshot name. This is used internally, and should not be modified.",
421 }),
982c7f12
DM
422 snaptime => {
423 optional => 1,
424 description => "Timestamp for snapshots.",
425 type => 'integer',
426 minimum => 0,
427 },
18bfb361
DM
428 vmstate => {
429 optional => 1,
430 type => 'string', format => 'pve-volume-id',
431 description => "Reference to a volume which stores the VM state. This is used internally for snapshots.",
432 },
3bafc510
DM
433 machine => {
434 description => "Specific the Qemu machine type.",
435 type => 'string',
436 pattern => '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
437 maxLength => 40,
438 optional => 1,
439 },
1e3baf05
DM
440};
441
442# what about other qemu settings ?
443#cpu => 'string',
444#machine => 'string',
445#fda => 'file',
446#fdb => 'file',
447#mtdblock => 'file',
448#sd => 'file',
449#pflash => 'file',
450#snapshot => 'bool',
451#bootp => 'file',
452##tftp => 'dir',
453##smb => 'dir',
454#kernel => 'file',
455#append => 'string',
456#initrd => 'file',
457##soundhw => 'string',
458
459while (my ($k, $v) = each %$confdesc) {
460 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
461}
462
463my $MAX_IDE_DISKS = 4;
f62db2a4 464my $MAX_SCSI_DISKS = 14;
a2650619 465my $MAX_VIRTIO_DISKS = 16;
cdb0931f 466my $MAX_SATA_DISKS = 6;
1e3baf05 467my $MAX_USB_DEVICES = 5;
5bdcf937 468my $MAX_NETS = 32;
1e3baf05 469my $MAX_UNUSED_DISKS = 8;
040b06b7 470my $MAX_HOSTPCI_DEVICES = 2;
bae179aa 471my $MAX_SERIAL_PORTS = 4;
1989a89c 472my $MAX_PARALLEL_PORTS = 3;
1e3baf05
DM
473
474my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
e4c6e0b8 475 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3'];
6b64503e 476my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05 477
1e3baf05
DM
478my $netdesc = {
479 optional => 1,
480 type => 'string', format => 'pve-qm-net',
a9410357 481 typetext => "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>][,tag=<vlanid>][,firewall=0|1]",
1e3baf05 482 description => <<EODESCR,
19672434 483Specify network devices.
1e3baf05
DM
484
485MODEL is one of: $nic_model_list_txt
486
19672434 487XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
1e3baf05
DM
488automatically generated if not specified.
489
490The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
491
492Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
493
494If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
495
49610.0.2.2 Gateway
49710.0.2.3 DNS Server
49810.0.2.4 SMB Server
499
500The DHCP server assign addresses to the guest starting from 10.0.2.15.
501
502EODESCR
503};
504PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
505
506for (my $i = 0; $i < $MAX_NETS; $i++) {
507 $confdesc->{"net$i"} = $netdesc;
508}
509
510my $drivename_hash;
19672434 511
1e3baf05
DM
512my $idedesc = {
513 optional => 1,
514 type => 'string', format => 'pve-qm-drive',
8d87f8aa 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] [,discard=ignore|on]',
3c770faa 516 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
1e3baf05
DM
517};
518PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
519
520my $scsidesc = {
521 optional => 1,
522 type => 'string', format => 'pve-qm-drive',
8d87f8aa 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] [,discard=ignore|on]',
3c770faa 524 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
1e3baf05
DM
525};
526PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
527
cdb0931f
DA
528my $satadesc = {
529 optional => 1,
530 type => 'string', format => 'pve-qm-drive',
8d87f8aa 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] [,discard=ignore|on]',
3c770faa 532 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
cdb0931f
DA
533};
534PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
535
1e3baf05
DM
536my $virtiodesc = {
537 optional => 1,
538 type => 'string', format => 'pve-qm-drive',
8d87f8aa 539 typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
3c770faa 540 description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
1e3baf05
DM
541};
542PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
543
544my $usbdesc = {
545 optional => 1,
546 type => 'string', format => 'pve-qm-usb-device',
80401dd8 547 typetext => 'host=HOSTUSBDEVICE|spice',
1e3baf05 548 description => <<EODESCR,
2fe1a152 549Configure an USB device (n is 0 to 4). This can be used to
1e3baf05
DM
550pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
551
19672434 552'bus-port(.port)*' (decimal numbers) or
1e3baf05
DM
553'vendor_id:product_id' (hexadeciaml numbers)
554
19672434 555You can use the 'lsusb -t' command to list existing usb devices.
1e3baf05
DM
556
557Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
558
80401dd8
DM
559The value 'spice' can be used to add a usb redirection devices for spice.
560
1e3baf05
DM
561EODESCR
562};
563PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
564
040b06b7
DA
565my $hostpcidesc = {
566 optional => 1,
567 type => 'string', format => 'pve-qm-hostpci',
2e3b7e2a 568 typetext => "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
040b06b7
DA
569 description => <<EODESCR,
570Map host pci devices. HOSTPCIDEVICE syntax is:
571
572'bus:dev.func' (hexadecimal numbers)
573
574You can us the 'lspci' command to list existing pci devices.
575
0cea6a01
DM
576The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
577
040b06b7
DA
578Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
579
580Experimental: user reported problems with this option.
581EODESCR
582};
583PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
584
bae179aa
DA
585my $serialdesc = {
586 optional => 1,
ca0cef26 587 type => 'string',
9f9d2fb2 588 pattern => '(/dev/ttyS\d+|socket)',
bae179aa 589 description => <<EODESCR,
9f9d2fb2 590Create 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).
bae179aa
DA
591
592Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
593
594Experimental: user reported problems with this option.
595EODESCR
596};
bae179aa 597
1989a89c
DA
598my $paralleldesc= {
599 optional => 1,
ca0cef26 600 type => 'string',
9ecc8431 601 pattern => '/dev/parport\d+|/dev/usb/lp\d+',
1989a89c 602 description => <<EODESCR,
19672434 603Map host parallel devices (n is 0 to 2).
1989a89c
DA
604
605Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
606
607Experimental: user reported problems with this option.
608EODESCR
609};
1989a89c
DA
610
611for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
612 $confdesc->{"parallel$i"} = $paralleldesc;
613}
614
bae179aa
DA
615for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
616 $confdesc->{"serial$i"} = $serialdesc;
617}
618
040b06b7
DA
619for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
620 $confdesc->{"hostpci$i"} = $hostpcidesc;
621}
1e3baf05
DM
622
623for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
624 $drivename_hash->{"ide$i"} = 1;
625 $confdesc->{"ide$i"} = $idedesc;
626}
627
cdb0931f
DA
628for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
629 $drivename_hash->{"sata$i"} = 1;
630 $confdesc->{"sata$i"} = $satadesc;
631}
632
1e3baf05
DM
633for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
634 $drivename_hash->{"scsi$i"} = 1;
635 $confdesc->{"scsi$i"} = $scsidesc ;
636}
637
638for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
639 $drivename_hash->{"virtio$i"} = 1;
640 $confdesc->{"virtio$i"} = $virtiodesc;
641}
642
643for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
644 $confdesc->{"usb$i"} = $usbdesc;
645}
646
647my $unuseddesc = {
648 optional => 1,
649 type => 'string', format => 'pve-volume-id',
650 description => "Reference to unused volumes.",
651};
652
653for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
654 $confdesc->{"unused$i"} = $unuseddesc;
655}
656
657my $kvm_api_version = 0;
658
659sub kvm_version {
660
661 return $kvm_api_version if $kvm_api_version;
662
6b64503e 663 my $fh = IO::File->new("</dev/kvm") ||
1e3baf05
DM
664 return 0;
665
6b64503e 666 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
1e3baf05
DM
667 $kvm_api_version = $v;
668 }
669
670 $fh->close();
671
672 return $kvm_api_version;
673}
674
675my $kvm_user_version;
676
677sub kvm_user_version {
678
679 return $kvm_user_version if $kvm_user_version;
680
681 $kvm_user_version = 'unknown';
682
683 my $tmp = `kvm -help 2>/dev/null`;
19672434 684
fa7ae705 685 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
1e3baf05
DM
686 $kvm_user_version = $2;
687 }
688
689 return $kvm_user_version;
690
691}
692
693my $kernel_has_vhost_net = -c '/dev/vhost-net';
694
695sub disknames {
696 # order is important - used to autoselect boot disk
19672434 697 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05 698 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
cdb0931f
DA
699 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
700 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1e3baf05
DM
701}
702
703sub valid_drivename {
704 my $dev = shift;
705
6b64503e 706 return defined($drivename_hash->{$dev});
1e3baf05
DM
707}
708
709sub option_exists {
710 my $key = shift;
711 return defined($confdesc->{$key});
19672434 712}
1e3baf05
DM
713
714sub nic_models {
715 return $nic_model_list;
716}
717
718sub os_list_description {
719
720 return {
721 other => 'Other',
722 wxp => 'Windows XP',
723 w2k => 'Windows 2000',
724 w2k3 =>, 'Windows 2003',
725 w2k8 => 'Windows 2008',
726 wvista => 'Windows Vista',
727 win7 => 'Windows 7',
a70ebde3 728 win8 => 'Windows 8/2012',
1e3baf05
DM
729 l24 => 'Linux 2.4',
730 l26 => 'Linux 2.6',
19672434 731 };
1e3baf05
DM
732}
733
1e3baf05
DM
734my $cdrom_path;
735
736sub get_cdrom_path {
737
738 return $cdrom_path if $cdrom_path;
739
740 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
741 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
742 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
743}
744
745sub get_iso_path {
746 my ($storecfg, $vmid, $cdrom) = @_;
747
748 if ($cdrom eq 'cdrom') {
749 return get_cdrom_path();
750 } elsif ($cdrom eq 'none') {
751 return '';
752 } elsif ($cdrom =~ m|^/|) {
753 return $cdrom;
754 } else {
6b64503e 755 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
756 }
757}
758
759# try to convert old style file names to volume IDs
760sub filename_to_volume_id {
761 my ($vmid, $file, $media) = @_;
762
763 if (!($file eq 'none' || $file eq 'cdrom' ||
764 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
19672434 765
1e3baf05 766 return undef if $file =~ m|/|;
19672434 767
1e3baf05
DM
768 if ($media && $media eq 'cdrom') {
769 $file = "local:iso/$file";
770 } else {
771 $file = "local:$vmid/$file";
772 }
773 }
774
775 return $file;
776}
777
778sub verify_media_type {
779 my ($opt, $vtype, $media) = @_;
780
781 return if !$media;
782
783 my $etype;
784 if ($media eq 'disk') {
a125592c 785 $etype = 'images';
1e3baf05
DM
786 } elsif ($media eq 'cdrom') {
787 $etype = 'iso';
788 } else {
789 die "internal error";
790 }
791
792 return if ($vtype eq $etype);
19672434 793
1e3baf05
DM
794 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
795}
796
797sub cleanup_drive_path {
798 my ($opt, $storecfg, $drive) = @_;
799
800 # try to convert filesystem paths to volume IDs
801
802 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
803 ($drive->{file} !~ m|^/dev/.+|) &&
804 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
19672434 805 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
806 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
807 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
808 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
809 verify_media_type($opt, $vtype, $drive->{media});
810 $drive->{file} = $volid;
811 }
812
813 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
814}
815
816sub create_conf_nolock {
817 my ($vmid, $settings) = @_;
818
6b64503e 819 my $filename = config_file($vmid);
1e3baf05
DM
820
821 die "configuration file '$filename' already exists\n" if -f $filename;
19672434 822
1e3baf05
DM
823 my $defaults = load_defaults();
824
825 $settings->{name} = "vm$vmid" if !$settings->{name};
826 $settings->{memory} = $defaults->{memory} if !$settings->{memory};
827
828 my $data = '';
829 foreach my $opt (keys %$settings) {
830 next if !$confdesc->{$opt};
831
832 my $value = $settings->{$opt};
833 next if !$value;
834
835 $data .= "$opt: $value\n";
836 }
837
838 PVE::Tools::file_set_contents($filename, $data);
839}
840
f36ed4f4
DM
841my $parse_size = sub {
842 my ($value) = @_;
843
9bf371a6 844 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
f36ed4f4
DM
845 my ($size, $unit) = ($1, $3);
846 if ($unit) {
847 if ($unit eq 'K') {
848 $size = $size * 1024;
849 } elsif ($unit eq 'M') {
850 $size = $size * 1024 * 1024;
851 } elsif ($unit eq 'G') {
852 $size = $size * 1024 * 1024 * 1024;
853 }
854 }
855 return int($size);
856};
857
858my $format_size = sub {
859 my ($size) = @_;
860
861 $size = int($size);
862
863 my $kb = int($size/1024);
864 return $size if $kb*1024 != $size;
865
866 my $mb = int($kb/1024);
867 return "${kb}K" if $mb*1024 != $kb;
868
869 my $gb = int($mb/1024);
870 return "${mb}M" if $gb*1024 != $mb;
871
872 return "${gb}G";
873};
874
1e3baf05
DM
875# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
876# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
036e0e2b 877# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
8d87f8aa 878# [,aio=native|threads][,discard=ignore|on]
1e3baf05
DM
879
880sub parse_drive {
881 my ($key, $data) = @_;
882
883 my $res = {};
19672434 884
1e3baf05
DM
885 # $key may be undefined - used to verify JSON parameters
886 if (!defined($key)) {
887 $res->{interface} = 'unknown'; # should not harm when used to verify parameters
888 $res->{index} = 0;
889 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
890 $res->{interface} = $1;
891 $res->{index} = $2;
892 } else {
893 return undef;
894 }
895
896 foreach my $p (split (/,/, $data)) {
897 next if $p =~ m/^\s*$/;
898
74edd76b 899 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
1e3baf05
DM
900 my ($k, $v) = ($1, $2);
901
902 $k = 'file' if $k eq 'volume';
903
904 return undef if defined $res->{$k};
19672434 905
9bf371a6
DM
906 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
907 return undef if !$v || $v !~ m/^\d+/;
908 $k = "m$k";
909 $v = sprintf("%.3f", $v / (1024*1024));
910 }
1e3baf05
DM
911 $res->{$k} = $v;
912 } else {
913 if (!$res->{file} && $p !~ m/=/) {
914 $res->{file} = $p;
915 } else {
916 return undef;
917 }
918 }
919 }
920
921 return undef if !$res->{file};
922
bdf3f362
AD
923 if($res->{file} =~ m/\.(raw|cow|qcow|qcow2|vmdk|cloop)$/){
924 $res->{format} = $1;
925 }
926
19672434 927 return undef if $res->{cache} &&
e482cec3 928 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
1e3baf05
DM
929 return undef if $res->{snapshot} && $res->{snapshot} !~ m/^(on|off)$/;
930 return undef if $res->{cyls} && $res->{cyls} !~ m/^\d+$/;
931 return undef if $res->{heads} && $res->{heads} !~ m/^\d+$/;
932 return undef if $res->{secs} && $res->{secs} !~ m/^\d+$/;
933 return undef if $res->{media} && $res->{media} !~ m/^(disk|cdrom)$/;
934 return undef if $res->{trans} && $res->{trans} !~ m/^(none|lba|auto)$/;
935 return undef if $res->{format} && $res->{format} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
936 return undef if $res->{rerror} && $res->{rerror} !~ m/^(ignore|report|stop)$/;
937 return undef if $res->{werror} && $res->{werror} !~ m/^(enospc|ignore|report|stop)$/;
938 return undef if $res->{backup} && $res->{backup} !~ m/^(yes|no)$/;
939 return undef if $res->{aio} && $res->{aio} !~ m/^(native|threads)$/;
8d87f8aa 940 return undef if $res->{discard} && $res->{discard} !~ m/^(ignore|on)$/;
be190583 941
9bf371a6
DM
942 return undef if $res->{mbps_rd} && $res->{mbps};
943 return undef if $res->{mbps_wr} && $res->{mbps};
944
945 return undef if $res->{mbps} && $res->{mbps} !~ m/^\d+(\.\d+)?$/;
74edd76b 946 return undef if $res->{mbps_max} && $res->{mbps_max} !~ m/^\d+(\.\d+)?$/;
9bf371a6 947 return undef if $res->{mbps_rd} && $res->{mbps_rd} !~ m/^\d+(\.\d+)?$/;
74edd76b 948 return undef if $res->{mbps_rd_max} && $res->{mbps_rd_max} !~ m/^\d+(\.\d+)?$/;
9bf371a6 949 return undef if $res->{mbps_wr} && $res->{mbps_wr} !~ m/^\d+(\.\d+)?$/;
74edd76b 950 return undef if $res->{mbps_wr_max} && $res->{mbps_wr_max} !~ m/^\d+(\.\d+)?$/;
9bf371a6 951
affd2f88
AD
952 return undef if $res->{iops_rd} && $res->{iops};
953 return undef if $res->{iops_wr} && $res->{iops};
74edd76b
AD
954
955
affd2f88 956 return undef if $res->{iops} && $res->{iops} !~ m/^\d+$/;
74edd76b 957 return undef if $res->{iops_max} && $res->{iops_max} !~ m/^\d+$/;
affd2f88 958 return undef if $res->{iops_rd} && $res->{iops_rd} !~ m/^\d+$/;
74edd76b 959 return undef if $res->{iops_rd_max} && $res->{iops_rd_max} !~ m/^\d+$/;
affd2f88 960 return undef if $res->{iops_wr} && $res->{iops_wr} !~ m/^\d+$/;
74edd76b 961 return undef if $res->{iops_wr_max} && $res->{iops_wr_max} !~ m/^\d+$/;
affd2f88
AD
962
963
24afaca0 964 if ($res->{size}) {
be190583 965 return undef if !defined($res->{size} = &$parse_size($res->{size}));
24afaca0
DM
966 }
967
1e3baf05
DM
968 if ($res->{media} && ($res->{media} eq 'cdrom')) {
969 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
19672434 970 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
971 return undef if $res->{interface} eq 'virtio';
972 }
973
974 # rerror does not work with scsi drives
975 if ($res->{rerror}) {
976 return undef if $res->{interface} eq 'scsi';
977 }
978
979 return $res;
980}
981
74edd76b 982my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
1e3baf05
DM
983
984sub print_drive {
985 my ($vmid, $drive) = @_;
986
987 my $opts = '';
74edd76b 988 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') {
1e3baf05
DM
989 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
990 }
991
24afaca0
DM
992 if ($drive->{size}) {
993 $opts .= ",size=" . &$format_size($drive->{size});
994 }
995
1e3baf05
DM
996 return "$drive->{file}$opts";
997}
998
28ef82d3
DM
999sub scsi_inquiry {
1000 my($fh, $noerr) = @_;
1001
1002 my $SG_IO = 0x2285;
1003 my $SG_GET_VERSION_NUM = 0x2282;
1004
1005 my $versionbuf = "\x00" x 8;
1006 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1007 if (!$ret) {
1008 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1009 return undef;
1010 }
97d62eb7 1011 my $version = unpack("I", $versionbuf);
28ef82d3
DM
1012 if ($version < 30000) {
1013 die "scsi generic interface too old\n" if !$noerr;
1014 return undef;
1015 }
97d62eb7 1016
28ef82d3
DM
1017 my $buf = "\x00" x 36;
1018 my $sensebuf = "\x00" x 8;
f334aa3e 1019 my $cmd = pack("C x3 C x1", 0x12, 36);
97d62eb7 1020
28ef82d3
DM
1021 # see /usr/include/scsi/sg.h
1022 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";
1023
97d62eb7
DM
1024 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1025 length($sensebuf), 0, length($buf), $buf,
28ef82d3
DM
1026 $cmd, $sensebuf, 6000);
1027
1028 $ret = ioctl($fh, $SG_IO, $packet);
1029 if (!$ret) {
1030 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1031 return undef;
1032 }
97d62eb7 1033
28ef82d3
DM
1034 my @res = unpack($sg_io_hdr_t, $packet);
1035 if ($res[17] || $res[18]) {
1036 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1037 return undef;
1038 }
1039
1040 my $res = {};
09984754 1041 (my $byte0, my $byte1, $res->{vendor},
28ef82d3
DM
1042 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
1043
09984754
DM
1044 $res->{removable} = $byte1 & 128 ? 1 : 0;
1045 $res->{type} = $byte0 & 31;
1046
28ef82d3
DM
1047 return $res;
1048}
1049
1050sub path_is_scsi {
1051 my ($path) = @_;
1052
1053 my $fh = IO::File->new("+<$path") || return undef;
1054 my $res = scsi_inquiry($fh, 1);
1055 close($fh);
1056
1057 return $res;
1058}
1059
db656e5f
DM
1060sub machine_type_is_q35 {
1061 my ($conf) = @_;
1062
1063 return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
1064}
1065
1066sub print_tabletdevice_full {
1067 my ($conf) = @_;
1068
1069 my $q35 = machine_type_is_q35($conf);
1070
1071 # we use uhci for old VMs because tablet driver was buggy in older qemu
1072 my $usbbus = $q35 ? "ehci" : "uhci";
1073
1074 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1075}
1076
ca916ecc 1077sub print_drivedevice_full {
5bdcf937 1078 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
ca916ecc
DA
1079
1080 my $device = '';
1081 my $maxdev = 0;
19672434 1082
ca916ecc 1083 if ($drive->{interface} eq 'virtio') {
5bdcf937 1084 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges);
2ed36a41
DM
1085 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1086 } elsif ($drive->{interface} eq 'scsi') {
5b952ff5 1087 $maxdev = ($conf->{scsihw} && ($conf->{scsihw} !~ m/^lsi/)) ? 256 : 7;
2ed36a41
DM
1088 my $controller = int($drive->{index} / $maxdev);
1089 my $unit = $drive->{index} % $maxdev;
1090 my $devicetype = 'hd';
231f2e13
DA
1091 my $path = '';
1092 if (drive_is_cdrom($drive)) {
1093 $devicetype = 'cd';
29b19529 1094 } else {
231f2e13
DA
1095 if ($drive->{file} =~ m|^/|) {
1096 $path = $drive->{file};
1097 } else {
1098 $path = PVE::Storage::path($storecfg, $drive->{file});
1099 }
d454d040
AD
1100
1101 if($path =~ m/^iscsi\:\/\//){
29b19529
DM
1102 $devicetype = 'generic';
1103 } else {
09984754
DM
1104 if (my $info = path_is_scsi($path)) {
1105 if ($info->{type} == 0) {
1106 $devicetype = 'block';
1107 } elsif ($info->{type} == 1) { # tape
1108 $devicetype = 'generic';
1109 }
1110 }
d454d040 1111 }
231f2e13 1112 }
ca916ecc 1113
5b952ff5
DM
1114 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)){
1115 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
cdd20088
AD
1116 } else {
1117 $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}";
1118 }
1119
2ed36a41
DM
1120 } elsif ($drive->{interface} eq 'ide'){
1121 $maxdev = 2;
1122 my $controller = int($drive->{index} / $maxdev);
1123 my $unit = $drive->{index} % $maxdev;
1124 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
1125
7ebe888a 1126 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
cdb0931f
DA
1127 } elsif ($drive->{interface} eq 'sata'){
1128 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1129 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1130 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
1131 } elsif ($drive->{interface} eq 'usb') {
1132 die "implement me";
1133 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1134 } else {
1135 die "unsupported interface type";
ca916ecc
DA
1136 }
1137
3b408e82
DM
1138 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1139
ca916ecc
DA
1140 return $device;
1141}
1142
15b21acc 1143sub get_initiator_name {
46f58b5f 1144 my $initiator;
15b21acc 1145
46f58b5f
DM
1146 my $fh = IO::File->new('/etc/iscsi/initiatorname.iscsi') || return undef;
1147 while (defined(my $line = <$fh>)) {
1148 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
15b21acc
MR
1149 $initiator = $1;
1150 last;
1151 }
46f58b5f
DM
1152 $fh->close();
1153
15b21acc
MR
1154 return $initiator;
1155}
1156
1e3baf05
DM
1157sub print_drive_full {
1158 my ($storecfg, $vmid, $drive) = @_;
1159
1160 my $opts = '';
1161 foreach my $o (@qemu_drive_options) {
3b408e82 1162 next if $o eq 'bootindex';
1e3baf05 1163 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
19672434 1164 }
1e3baf05 1165
9bf371a6
DM
1166 foreach my $o (qw(bps bps_rd bps_wr)) {
1167 my $v = $drive->{"m$o"};
1168 $opts .= ",$o=" . int($v*1024*1024) if $v;
1169 }
1170
1e3baf05 1171 # use linux-aio by default (qemu default is threads)
19672434 1172 $opts .= ",aio=native" if !$drive->{aio};
1e3baf05
DM
1173
1174 my $path;
1175 my $volid = $drive->{file};
6b64503e
DM
1176 if (drive_is_cdrom($drive)) {
1177 $path = get_iso_path($storecfg, $vmid, $volid);
1e3baf05
DM
1178 } else {
1179 if ($volid =~ m|^/|) {
1180 $path = $volid;
1181 } else {
6b64503e 1182 $path = PVE::Storage::path($storecfg, $volid);
1e3baf05
DM
1183 }
1184 }
1185
ef86170e 1186 $opts .= ",cache=none" if !$drive->{cache} && !drive_is_cdrom($drive);
11490cf2 1187
1e3baf05
DM
1188 my $pathinfo = $path ? "file=$path," : '';
1189
3ebfcc86 1190 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
1191}
1192
cc4d6182 1193sub print_netdevice_full {
5bdcf937 1194 my ($vmid, $conf, $net, $netid, $bridges) = @_;
cc4d6182
DA
1195
1196 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
1197
1198 my $device = $net->{model};
1199 if ($net->{model} eq 'virtio') {
1200 $device = 'virtio-net-pci';
1201 };
1202
1203 # qemu > 0.15 always try to boot from network - we disable that by
1204 # not loading the pxe rom file
1205 my $extra = ($bootorder !~ m/n/) ? "romfile=," : '';
5bdcf937 1206 my $pciaddr = print_pci_addr("$netid", $bridges);
cc4d6182 1207 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
a9410357
AD
1208 if ($net->{queues} && $net->{queues} > 1 && $net->{model} eq 'virtio'){
1209 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1210 my $vectors = $net->{queues} * 2 + 2;
1211 $tmpstr .= ",vectors=$vectors,mq=on";
1212 }
cc4d6182
DA
1213 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
1214 return $tmpstr;
1215}
1216
1217sub print_netdev_full {
1218 my ($vmid, $conf, $net, $netid) = @_;
1219
1220 my $i = '';
1221 if ($netid =~ m/^net(\d+)$/) {
1222 $i = int($1);
1223 }
1224
1225 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
1226
1227 my $ifname = "tap${vmid}i$i";
1228
1229 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1230 die "interface name '$ifname' is too long (max 15 character)\n"
1231 if length($ifname) >= 16;
1232
1233 my $vhostparam = '';
1234 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
1235
1236 my $vmname = $conf->{name} || "vm$vmid";
1237
a9410357
AD
1238 my $netdev = "";
1239
cc4d6182 1240 if ($net->{bridge}) {
a9410357 1241 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
cc4d6182 1242 } else {
a9410357 1243 $netdev = "type=user,id=$netid,hostname=$vmname";
cc4d6182 1244 }
a9410357
AD
1245
1246 $netdev .= ",queues=$net->{queues}" if ($net->{queues} && $net->{model} eq 'virtio');
1247
1248 return $netdev;
cc4d6182 1249}
1e3baf05
DM
1250
1251sub drive_is_cdrom {
1252 my ($drive) = @_;
1253
1254 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
1255
1256}
1257
040b06b7
DA
1258sub parse_hostpci {
1259 my ($value) = @_;
1260
1261 return undef if !$value;
1262
0cea6a01
DM
1263
1264 my @list = split(/,/, $value);
1265 my $found;
1266
040b06b7 1267 my $res = {};
0cea6a01 1268 foreach my $kv (@list) {
040b06b7 1269
4543ecf0 1270 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
0cea6a01 1271 $found = 1;
4543ecf0
AD
1272 if(defined($4)){
1273 push @{$res->{pciid}}, { id => $2 , function => $4};
1274
1275 }else{
1276 my $pcidevices = lspci($2);
1277 $res->{pciid} = $pcidevices->{$2};
1278 }
0cea6a01
DM
1279 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1280 $res->{driver} = $1;
1281 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1282 $res->{rombar} = $1;
2e3b7e2a
AD
1283 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1284 $res->{'x-vga'} = $1;
1285 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1286 $res->{pcie} = 1 if $1 == 1;
0cea6a01
DM
1287 } else {
1288 warn "unknown hostpci setting '$kv'\n";
1289 }
040b06b7
DA
1290 }
1291
0cea6a01
DM
1292 return undef if !$found;
1293
040b06b7
DA
1294 return $res;
1295}
1296
1e3baf05
DM
1297# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1298sub parse_net {
1299 my ($data) = @_;
1300
1301 my $res = {};
1302
6b64503e 1303 foreach my $kvp (split(/,/, $data)) {
1e3baf05 1304
e4c6e0b8 1305 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
6b64503e 1306 my $model = lc($1);
92f0fedc 1307 my $mac = defined($3) ? uc($3) : PVE::Tools::random_ether_addr();
1e3baf05
DM
1308 $res->{model} = $model;
1309 $res->{macaddr} = $mac;
1310 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1311 $res->{bridge} = $1;
a9410357
AD
1312 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1313 $res->{queues} = $1;
1e3baf05
DM
1314 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1315 $res->{rate} = $1;
5070f384
DA
1316 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1317 $res->{tag} = $1;
2dd4aa4c
AD
1318 } elsif ($kvp =~ m/^firewall=(\d+)$/) {
1319 $res->{firewall} = $1;
1e3baf05
DM
1320 } else {
1321 return undef;
1322 }
19672434 1323
1e3baf05
DM
1324 }
1325
1326 return undef if !$res->{model};
1327
1328 return $res;
1329}
1330
1331sub print_net {
1332 my $net = shift;
1333
1334 my $res = "$net->{model}";
1335 $res .= "=$net->{macaddr}" if $net->{macaddr};
1336 $res .= ",bridge=$net->{bridge}" if $net->{bridge};
1337 $res .= ",rate=$net->{rate}" if $net->{rate};
18744ba3 1338 $res .= ",tag=$net->{tag}" if $net->{tag};
28138e9a 1339 $res .= ",firewall=$net->{firewall}" if $net->{firewall};
1e3baf05
DM
1340
1341 return $res;
1342}
1343
1344sub add_random_macs {
1345 my ($settings) = @_;
1346
1347 foreach my $opt (keys %$settings) {
1348 next if $opt !~ m/^net(\d+)$/;
1349 my $net = parse_net($settings->{$opt});
1350 next if !$net;
1351 $settings->{$opt} = print_net($net);
1352 }
1353}
1354
1355sub add_unused_volume {
1858638f 1356 my ($config, $volid) = @_;
1e3baf05
DM
1357
1358 my $key;
1359 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1360 my $test = "unused$ind";
1361 if (my $vid = $config->{$test}) {
1362 return if $vid eq $volid; # do not add duplicates
1363 } else {
1364 $key = $test;
19672434 1365 }
1e3baf05
DM
1366 }
1367
1368 die "To many unused volume - please delete them first.\n" if !$key;
97d62eb7 1369
1858638f 1370 $config->{$key} = $volid;
1e3baf05 1371
1858638f 1372 return $key;
1e3baf05
DM
1373}
1374
1e3baf05
DM
1375PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1376sub verify_bootdisk {
1377 my ($value, $noerr) = @_;
1378
19672434 1379 return $value if valid_drivename($value);
1e3baf05
DM
1380
1381 return undef if $noerr;
1382
1383 die "invalid boot disk '$value'\n";
1384}
1385
1386PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
1387sub verify_net {
1388 my ($value, $noerr) = @_;
1389
1390 return $value if parse_net($value);
1391
1392 return undef if $noerr;
19672434 1393
1e3baf05
DM
1394 die "unable to parse network options\n";
1395}
1396
1397PVE::JSONSchema::register_format('pve-qm-drive', \&verify_drive);
1398sub verify_drive {
1399 my ($value, $noerr) = @_;
1400
6b64503e 1401 return $value if parse_drive(undef, $value);
1e3baf05
DM
1402
1403 return undef if $noerr;
19672434 1404
1e3baf05
DM
1405 die "unable to parse drive options\n";
1406}
1407
1408PVE::JSONSchema::register_format('pve-qm-hostpci', \&verify_hostpci);
1409sub verify_hostpci {
1410 my ($value, $noerr) = @_;
1411
040b06b7
DA
1412 return $value if parse_hostpci($value);
1413
1414 return undef if $noerr;
1415
1416 die "unable to parse pci id\n";
1e3baf05
DM
1417}
1418
0ea9541d
DM
1419PVE::JSONSchema::register_format('pve-qm-watchdog', \&verify_watchdog);
1420sub verify_watchdog {
1421 my ($value, $noerr) = @_;
1422
1423 return $value if parse_watchdog($value);
1424
1425 return undef if $noerr;
19672434 1426
0ea9541d
DM
1427 die "unable to parse watchdog options\n";
1428}
1429
1430sub parse_watchdog {
1431 my ($value) = @_;
1432
1433 return undef if !$value;
1434
1435 my $res = {};
1436
6b64503e 1437 foreach my $p (split(/,/, $value)) {
0ea9541d
DM
1438 next if $p =~ m/^\s*$/;
1439
1440 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1441 $res->{model} = $2;
1442 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1443 $res->{action} = $2;
1444 } else {
1445 return undef;
1446 }
1447 }
1448
1449 return $res;
1450}
1451
59411c4e
DM
1452PVE::JSONSchema::register_format('pve-qm-startup', \&verify_startup);
1453sub verify_startup {
1454 my ($value, $noerr) = @_;
1455
1456 return $value if parse_startup($value);
1457
1458 return undef if $noerr;
1459
1460 die "unable to parse startup options\n";
1461}
1462
1463sub parse_startup {
1464 my ($value) = @_;
1465
1466 return undef if !$value;
1467
1468 my $res = {};
1469
1470 foreach my $p (split(/,/, $value)) {
1471 next if $p =~ m/^\s*$/;
1472
1473 if ($p =~ m/^(order=)?(\d+)$/) {
1474 $res->{order} = $2;
1475 } elsif ($p =~ m/^up=(\d+)$/) {
1476 $res->{up} = $1;
1477 } elsif ($p =~ m/^down=(\d+)$/) {
1478 $res->{down} = $1;
1479 } else {
1480 return undef;
1481 }
1482 }
1483
1484 return $res;
1485}
1486
1e3baf05
DM
1487sub parse_usb_device {
1488 my ($value) = @_;
1489
1490 return undef if !$value;
1491
6b64503e 1492 my @dl = split(/,/, $value);
1e3baf05
DM
1493 my $found;
1494
1495 my $res = {};
1496 foreach my $v (@dl) {
036e0e2b 1497 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1e3baf05 1498 $found = 1;
036e0e2b
DM
1499 $res->{vendorid} = $2;
1500 $res->{productid} = $4;
1e3baf05
DM
1501 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1502 $found = 1;
1503 $res->{hostbus} = $1;
1504 $res->{hostport} = $2;
80401dd8
DM
1505 } elsif ($v =~ m/^spice$/) {
1506 $found = 1;
1507 $res->{spice} = 1;
1e3baf05
DM
1508 } else {
1509 return undef;
1510 }
1511 }
1512 return undef if !$found;
1513
1514 return $res;
1515}
19672434 1516
1e3baf05
DM
1517PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
1518sub verify_usb_device {
1519 my ($value, $noerr) = @_;
1520
1521 return $value if parse_usb_device($value);
1522
1523 return undef if $noerr;
19672434 1524
1e3baf05
DM
1525 die "unable to parse usb device\n";
1526}
1527
1e3baf05
DM
1528# add JSON properties for create and set function
1529sub json_config_properties {
1530 my $prop = shift;
1531
1532 foreach my $opt (keys %$confdesc) {
18bfb361 1533 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1e3baf05
DM
1534 $prop->{$opt} = $confdesc->{$opt};
1535 }
1536
1537 return $prop;
1538}
1539
1540sub check_type {
1541 my ($key, $value) = @_;
1542
1543 die "unknown setting '$key'\n" if !$confdesc->{$key};
1544
1545 my $type = $confdesc->{$key}->{type};
1546
6b64503e 1547 if (!defined($value)) {
1e3baf05
DM
1548 die "got undefined value\n";
1549 }
1550
1551 if ($value =~ m/[\n\r]/) {
1552 die "property contains a line feed\n";
1553 }
1554
1555 if ($type eq 'boolean') {
19672434
DM
1556 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1557 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1558 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
1559 } elsif ($type eq 'integer') {
1560 return int($1) if $value =~ m/^(\d+)$/;
1561 die "type check ('integer') failed - got '$value'\n";
04432191
AD
1562 } elsif ($type eq 'number') {
1563 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1564 die "type check ('number') failed - got '$value'\n";
1e3baf05
DM
1565 } elsif ($type eq 'string') {
1566 if (my $fmt = $confdesc->{$key}->{format}) {
1567 if ($fmt eq 'pve-qm-drive') {
1568 # special case - we need to pass $key to parse_drive()
6b64503e 1569 my $drive = parse_drive($key, $value);
1e3baf05
DM
1570 return $value if $drive;
1571 die "unable to parse drive options\n";
1572 }
1573 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
1574 return $value;
1575 }
1e3baf05 1576 $value =~ s/^\"(.*)\"$/$1/;
19672434 1577 return $value;
1e3baf05
DM
1578 } else {
1579 die "internal error"
1580 }
1581}
1582
191435c6
DM
1583sub lock_config_full {
1584 my ($vmid, $timeout, $code, @param) = @_;
1e3baf05 1585
6b64503e 1586 my $filename = config_file_lock($vmid);
1e3baf05 1587
191435c6 1588 my $res = lock_file($filename, $timeout, $code, @param);
1e3baf05
DM
1589
1590 die $@ if $@;
5fdbe4f0
DM
1591
1592 return $res;
1e3baf05
DM
1593}
1594
4e4f83fe
DM
1595sub lock_config_mode {
1596 my ($vmid, $timeout, $shared, $code, @param) = @_;
6116f729
DM
1597
1598 my $filename = config_file_lock($vmid);
1599
4e4f83fe 1600 my $res = lock_file_full($filename, $timeout, $shared, $code, @param);
6116f729
DM
1601
1602 die $@ if $@;
1603
1604 return $res;
1605}
1606
191435c6
DM
1607sub lock_config {
1608 my ($vmid, $code, @param) = @_;
1609
1610 return lock_config_full($vmid, 10, $code, @param);
1611}
1612
1e3baf05 1613sub cfs_config_path {
a78ccf26 1614 my ($vmid, $node) = @_;
1e3baf05 1615
a78ccf26
DM
1616 $node = $nodename if !$node;
1617 return "nodes/$node/qemu-server/$vmid.conf";
1e3baf05
DM
1618}
1619
040b06b7
DA
1620sub check_iommu_support{
1621 #fixme : need to check IOMMU support
1622 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1623
1624 my $iommu=1;
1625 return $iommu;
1626
1627}
1628
1e3baf05 1629sub config_file {
a78ccf26 1630 my ($vmid, $node) = @_;
1e3baf05 1631
a78ccf26 1632 my $cfspath = cfs_config_path($vmid, $node);
1e3baf05
DM
1633 return "/etc/pve/$cfspath";
1634}
1635
1636sub config_file_lock {
1637 my ($vmid) = @_;
1638
1639 return "$lock_dir/lock-$vmid.conf";
1640}
1641
1642sub touch_config {
1643 my ($vmid) = @_;
1644
6b64503e 1645 my $conf = config_file($vmid);
1e3baf05
DM
1646 utime undef, undef, $conf;
1647}
1648
1e3baf05 1649sub destroy_vm {
a6af7b3e 1650 my ($storecfg, $vmid, $keep_empty_config) = @_;
1e3baf05 1651
6b64503e 1652 my $conffile = config_file($vmid);
1e3baf05 1653
6b64503e 1654 my $conf = load_config($vmid);
1e3baf05 1655
6b64503e 1656 check_lock($conf);
1e3baf05 1657
19672434 1658 # only remove disks owned by this VM
1e3baf05
DM
1659 foreach_drive($conf, sub {
1660 my ($ds, $drive) = @_;
1661
6b64503e 1662 return if drive_is_cdrom($drive);
1e3baf05
DM
1663
1664 my $volid = $drive->{file};
ed221350 1665
ff1a2432 1666 return if !$volid || $volid =~ m|^/|;
1e3baf05 1667
6b64503e 1668 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 1669 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 1670
6b64503e 1671 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 1672 });
19672434 1673
a6af7b3e 1674 if ($keep_empty_config) {
9c502e26 1675 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
1676 } else {
1677 unlink $conffile;
1678 }
1e3baf05
DM
1679
1680 # also remove unused disk
1681 eval {
6b64503e 1682 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
1683
1684 eval {
6b64503e 1685 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 1686 my ($volid, $sid, $volname, $d) = @_;
6b64503e 1687 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
1688 });
1689 };
1690 warn $@ if $@;
1691
1692 };
1693 warn $@ if $@;
1694}
1695
1e3baf05 1696sub load_config {
7e8dcf2c 1697 my ($vmid, $node) = @_;
1e3baf05 1698
7e8dcf2c 1699 my $cfspath = cfs_config_path($vmid, $node);
1e3baf05
DM
1700
1701 my $conf = PVE::Cluster::cfs_read_file($cfspath);
1702
1703 die "no such VM ('$vmid')\n" if !defined($conf);
1704
1705 return $conf;
19672434 1706}
1e3baf05
DM
1707
1708sub parse_vm_config {
1709 my ($filename, $raw) = @_;
1710
1711 return undef if !defined($raw);
1712
554ac7e7 1713 my $res = {
fc1ddcdc 1714 digest => Digest::SHA::sha1_hex($raw),
0d18dcfc 1715 snapshots => {},
554ac7e7 1716 };
1e3baf05 1717
19672434 1718 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
1719 || die "got strange filename '$filename'";
1720
1721 my $vmid = $1;
1722
0d18dcfc 1723 my $conf = $res;
0581fe4f
DM
1724 my $descr = '';
1725
0d18dcfc
DM
1726 my @lines = split(/\n/, $raw);
1727 foreach my $line (@lines) {
1e3baf05 1728 next if $line =~ m/^\s*$/;
be190583 1729
0d18dcfc
DM
1730 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1731 my $snapname = $1;
1732 $conf->{description} = $descr if $descr;
782f4f75 1733 $descr = '';
be190583 1734 $conf = $res->{snapshots}->{$snapname} = {};
0d18dcfc
DM
1735 next;
1736 }
1e3baf05 1737
0581fe4f
DM
1738 if ($line =~ m/^\#(.*)\s*$/) {
1739 $descr .= PVE::Tools::decode_text($1) . "\n";
1740 next;
1741 }
1742
1e3baf05 1743 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
0581fe4f 1744 $descr .= PVE::Tools::decode_text($2);
0d18dcfc
DM
1745 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1746 $conf->{snapstate} = $1;
1e3baf05
DM
1747 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1748 my $key = $1;
1749 my $value = $2;
0d18dcfc 1750 $conf->{$key} = $value;
1e3baf05
DM
1751 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1752 my $key = $1;
1753 my $value = $2;
1754 eval { $value = check_type($key, $value); };
1755 if ($@) {
1756 warn "vm $vmid - unable to parse value of '$key' - $@";
1757 } else {
1758 my $fmt = $confdesc->{$key}->{format};
1759 if ($fmt && $fmt eq 'pve-qm-drive') {
1760 my $v = parse_drive($key, $value);
1761 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
1762 $v->{file} = $volid;
6b64503e 1763 $value = print_drive($vmid, $v);
1e3baf05
DM
1764 } else {
1765 warn "vm $vmid - unable to parse value of '$key'\n";
1766 next;
1767 }
1768 }
1769
1770 if ($key eq 'cdrom') {
0d18dcfc 1771 $conf->{ide2} = $value;
1e3baf05 1772 } else {
0d18dcfc 1773 $conf->{$key} = $value;
1e3baf05
DM
1774 }
1775 }
1776 }
1777 }
1778
0d18dcfc 1779 $conf->{description} = $descr if $descr;
0581fe4f 1780
0d18dcfc 1781 delete $res->{snapstate}; # just to be sure
1e3baf05
DM
1782
1783 return $res;
1784}
1785
1858638f
DM
1786sub write_vm_config {
1787 my ($filename, $conf) = @_;
1e3baf05 1788
0d18dcfc
DM
1789 delete $conf->{snapstate}; # just to be sure
1790
1858638f
DM
1791 if ($conf->{cdrom}) {
1792 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
1793 $conf->{ide2} = $conf->{cdrom};
1794 delete $conf->{cdrom};
1795 }
1e3baf05
DM
1796
1797 # we do not use 'smp' any longer
1858638f
DM
1798 if ($conf->{sockets}) {
1799 delete $conf->{smp};
1800 } elsif ($conf->{smp}) {
1801 $conf->{sockets} = $conf->{smp};
1802 delete $conf->{cores};
1803 delete $conf->{smp};
1e3baf05
DM
1804 }
1805
264e519f 1806 if ($conf->{maxcpus} && $conf->{sockets}) {
3bd18e48
AD
1807 delete $conf->{sockets};
1808 }
264e519f 1809
ee2f90b1 1810 my $used_volids = {};
0d18dcfc 1811
ee2f90b1 1812 my $cleanup_config = sub {
a8e2f942 1813 my ($cref, $snapname) = @_;
1858638f 1814
ee2f90b1
DM
1815 foreach my $key (keys %$cref) {
1816 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1817 $key eq 'snapstate';
1818 my $value = $cref->{$key};
1819 eval { $value = check_type($key, $value); };
1820 die "unable to parse value of '$key' - $@" if $@;
1858638f 1821
ee2f90b1
DM
1822 $cref->{$key} = $value;
1823
a8e2f942 1824 if (!$snapname && valid_drivename($key)) {
ed221350 1825 my $drive = parse_drive($key, $value);
ee2f90b1
DM
1826 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1827 }
1e3baf05 1828 }
ee2f90b1
DM
1829 };
1830
1831 &$cleanup_config($conf);
1832 foreach my $snapname (keys %{$conf->{snapshots}}) {
a8e2f942 1833 &$cleanup_config($conf->{snapshots}->{$snapname}, $snapname);
1e3baf05
DM
1834 }
1835
1858638f
DM
1836 # remove 'unusedX' settings if we re-add a volume
1837 foreach my $key (keys %$conf) {
1838 my $value = $conf->{$key};
ee2f90b1 1839 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1858638f 1840 delete $conf->{$key};
1e3baf05 1841 }
1858638f 1842 }
be190583 1843
0d18dcfc
DM
1844 my $generate_raw_config = sub {
1845 my ($conf) = @_;
0581fe4f 1846
0d18dcfc
DM
1847 my $raw = '';
1848
1849 # add description as comment to top of file
1850 my $descr = $conf->{description} || '';
1851 foreach my $cl (split(/\n/, $descr)) {
1852 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
1853 }
1854
1855 foreach my $key (sort keys %$conf) {
1856 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1857 $raw .= "$key: $conf->{$key}\n";
1858 }
1859 return $raw;
1860 };
0581fe4f 1861
0d18dcfc
DM
1862 my $raw = &$generate_raw_config($conf);
1863 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
1864 $raw .= "\n[$snapname]\n";
1865 $raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
1858638f 1866 }
1e3baf05 1867
1858638f
DM
1868 return $raw;
1869}
1e3baf05 1870
1858638f
DM
1871sub update_config_nolock {
1872 my ($vmid, $conf, $skiplock) = @_;
1e3baf05 1873
1858638f 1874 check_lock($conf) if !$skiplock;
97d62eb7 1875
1858638f 1876 my $cfspath = cfs_config_path($vmid);
1e3baf05 1877
1858638f
DM
1878 PVE::Cluster::cfs_write_file($cfspath, $conf);
1879}
1e3baf05 1880
1858638f
DM
1881sub update_config {
1882 my ($vmid, $conf, $skiplock) = @_;
1e3baf05 1883
1858638f 1884 lock_config($vmid, &update_config_nolock, $conf, $skiplock);
1e3baf05
DM
1885}
1886
19672434 1887sub load_defaults {
1e3baf05
DM
1888
1889 my $res = {};
1890
1891 # we use static defaults from our JSON schema configuration
1892 foreach my $key (keys %$confdesc) {
1893 if (defined(my $default = $confdesc->{$key}->{default})) {
1894 $res->{$key} = $default;
1895 }
1896 }
19672434 1897
1e3baf05
DM
1898 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
1899 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
1900
1901 return $res;
1902}
1903
1904sub config_list {
1905 my $vmlist = PVE::Cluster::get_vmlist();
1906 my $res = {};
1907 return $res if !$vmlist || !$vmlist->{ids};
1908 my $ids = $vmlist->{ids};
1909
1e3baf05
DM
1910 foreach my $vmid (keys %$ids) {
1911 my $d = $ids->{$vmid};
1912 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 1913 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
1914 $res->{$vmid}->{exists} = 1;
1915 }
1916 return $res;
1917}
1918
64e13401
DM
1919# test if VM uses local resources (to prevent migration)
1920sub check_local_resources {
1921 my ($conf, $noerr) = @_;
1922
1923 my $loc_res = 0;
19672434 1924
e0ab7331
DM
1925 $loc_res = 1 if $conf->{hostusb}; # old syntax
1926 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 1927
0d29ab3b 1928 foreach my $k (keys %$conf) {
49ca581d 1929 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2fe1a152 1930 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
1931 }
1932
1933 die "VM uses local resources\n" if $loc_res && !$noerr;
1934
1935 return $loc_res;
1936}
1937
719893a9 1938# check if used storages are available on all nodes (use by migrate)
47152e2e
DM
1939sub check_storage_availability {
1940 my ($storecfg, $conf, $node) = @_;
1941
1942 foreach_drive($conf, sub {
1943 my ($ds, $drive) = @_;
1944
1945 my $volid = $drive->{file};
1946 return if !$volid;
1947
1948 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1949 return if !$sid;
1950
1951 # check if storage is available on both nodes
1952 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
1953 PVE::Storage::storage_check_node($storecfg, $sid, $node);
1954 });
1955}
1956
719893a9
DM
1957# list nodes where all VM images are available (used by has_feature API)
1958sub shared_nodes {
1959 my ($conf, $storecfg) = @_;
1960
1961 my $nodelist = PVE::Cluster::get_nodelist();
1962 my $nodehash = { map { $_ => 1 } @$nodelist };
1963 my $nodename = PVE::INotify::nodename();
be190583 1964
719893a9
DM
1965 foreach_drive($conf, sub {
1966 my ($ds, $drive) = @_;
1967
1968 my $volid = $drive->{file};
1969 return if !$volid;
1970
1971 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1972 if ($storeid) {
1973 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
1974 if ($scfg->{disable}) {
1975 $nodehash = {};
1976 } elsif (my $avail = $scfg->{nodes}) {
1977 foreach my $node (keys %$nodehash) {
1978 delete $nodehash->{$node} if !$avail->{$node};
1979 }
1980 } elsif (!$scfg->{shared}) {
1981 foreach my $node (keys %$nodehash) {
1982 delete $nodehash->{$node} if $node ne $nodename
1983 }
1984 }
1985 }
1986 });
1987
1988 return $nodehash
1989}
1990
1e3baf05
DM
1991sub check_lock {
1992 my ($conf) = @_;
1993
1994 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1995}
1996
1997sub check_cmdline {
1998 my ($pidfile, $pid) = @_;
1999
6b64503e
DM
2000 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
2001 if (defined($fh)) {
1e3baf05
DM
2002 my $line = <$fh>;
2003 $fh->close;
2004 return undef if !$line;
6b64503e 2005 my @param = split(/\0/, $line);
1e3baf05
DM
2006
2007 my $cmd = $param[0];
06094efd 2008 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m|qemu-system-x86_64$|);
1e3baf05
DM
2009
2010 for (my $i = 0; $i < scalar (@param); $i++) {
2011 my $p = $param[$i];
2012 next if !$p;
2013 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2014 my $p = $param[$i+1];
2015 return 1 if $p && ($p eq $pidfile);
2016 return undef;
2017 }
2018 }
2019 }
2020 return undef;
2021}
2022
2023sub check_running {
7e8dcf2c 2024 my ($vmid, $nocheck, $node) = @_;
1e3baf05 2025
7e8dcf2c 2026 my $filename = config_file($vmid, $node);
1e3baf05
DM
2027
2028 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 2029 if !$nocheck && ! -f $filename;
1e3baf05 2030
e6c3b671 2031 my $pidfile = pidfile_name($vmid);
1e3baf05 2032
e6c3b671
DM
2033 if (my $fd = IO::File->new("<$pidfile")) {
2034 my $st = stat($fd);
1e3baf05 2035 my $line = <$fd>;
6b64503e 2036 close($fd);
1e3baf05
DM
2037
2038 my $mtime = $st->mtime;
2039 if ($mtime > time()) {
2040 warn "file '$filename' modified in future\n";
2041 }
2042
2043 if ($line =~ m/^(\d+)$/) {
2044 my $pid = $1;
e6c3b671
DM
2045 if (check_cmdline($pidfile, $pid)) {
2046 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
2047 return $pid;
2048 }
2049 }
1e3baf05
DM
2050 }
2051 }
2052
2053 return undef;
2054}
2055
2056sub vzlist {
19672434 2057
1e3baf05
DM
2058 my $vzlist = config_list();
2059
6b64503e 2060 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 2061
19672434 2062 while (defined(my $de = $fd->read)) {
1e3baf05
DM
2063 next if $de !~ m/^(\d+)\.pid$/;
2064 my $vmid = $1;
6b64503e
DM
2065 next if !defined($vzlist->{$vmid});
2066 if (my $pid = check_running($vmid)) {
1e3baf05
DM
2067 $vzlist->{$vmid}->{pid} = $pid;
2068 }
2069 }
2070
2071 return $vzlist;
2072}
2073
1e3baf05
DM
2074sub disksize {
2075 my ($storecfg, $conf) = @_;
2076
2077 my $bootdisk = $conf->{bootdisk};
2078 return undef if !$bootdisk;
2079 return undef if !valid_drivename($bootdisk);
2080
2081 return undef if !$conf->{$bootdisk};
2082
2083 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
2084 return undef if !defined($drive);
2085
2086 return undef if drive_is_cdrom($drive);
2087
2088 my $volid = $drive->{file};
2089 return undef if !$volid;
2090
24afaca0 2091 return $drive->{size};
1e3baf05
DM
2092}
2093
2094my $last_proc_pid_stat;
2095
03a33f30
DM
2096# get VM status information
2097# This must be fast and should not block ($full == false)
2098# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 2099sub vmstatus {
03a33f30 2100 my ($opt_vmid, $full) = @_;
1e3baf05
DM
2101
2102 my $res = {};
2103
19672434 2104 my $storecfg = PVE::Storage::config();
1e3baf05
DM
2105
2106 my $list = vzlist();
694fcad4 2107 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 2108
ae4915a2
DM
2109 my $cpucount = $cpuinfo->{cpus} || 1;
2110
1e3baf05
DM
2111 foreach my $vmid (keys %$list) {
2112 next if $opt_vmid && ($vmid ne $opt_vmid);
2113
2114 my $cfspath = cfs_config_path($vmid);
2115 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
2116
2117 my $d = {};
2118 $d->{pid} = $list->{$vmid}->{pid};
2119
2120 # fixme: better status?
2121 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
2122
af990afe
DM
2123 my $size = disksize($storecfg, $conf);
2124 if (defined($size)) {
2125 $d->{disk} = 0; # no info available
1e3baf05
DM
2126 $d->{maxdisk} = $size;
2127 } else {
2128 $d->{disk} = 0;
2129 $d->{maxdisk} = 0;
2130 }
2131
2132 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
ae4915a2
DM
2133 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
2134
1e3baf05 2135 $d->{name} = $conf->{name} || "VM $vmid";
19672434 2136 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1e3baf05 2137
8b1accf7 2138 if ($conf->{balloon}) {
4bdb0514 2139 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
074e01c8 2140 $d->{shares} = defined($conf->{shares}) ? $conf->{shares} : 1000;
8b1accf7
DM
2141 }
2142
1e3baf05
DM
2143 $d->{uptime} = 0;
2144 $d->{cpu} = 0;
1e3baf05
DM
2145 $d->{mem} = 0;
2146
2147 $d->{netout} = 0;
2148 $d->{netin} = 0;
2149
2150 $d->{diskread} = 0;
2151 $d->{diskwrite} = 0;
2152
4d8c851b
AD
2153 $d->{template} = is_template($conf);
2154
1e3baf05
DM
2155 $res->{$vmid} = $d;
2156 }
2157
2158 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
2159 foreach my $dev (keys %$netdev) {
2160 next if $dev !~ m/^tap([1-9]\d*)i/;
2161 my $vmid = $1;
2162 my $d = $res->{$vmid};
2163 next if !$d;
19672434 2164
1e3baf05
DM
2165 $d->{netout} += $netdev->{$dev}->{receive};
2166 $d->{netin} += $netdev->{$dev}->{transmit};
2167 }
2168
1e3baf05
DM
2169 my $ctime = gettimeofday;
2170
2171 foreach my $vmid (keys %$list) {
2172
2173 my $d = $res->{$vmid};
2174 my $pid = $d->{pid};
2175 next if !$pid;
2176
694fcad4
DM
2177 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
2178 next if !$pstat; # not running
19672434 2179
694fcad4 2180 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 2181
694fcad4 2182 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 2183
694fcad4 2184 if ($pstat->{vsize}) {
6b64503e 2185 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
2186 }
2187
2188 my $old = $last_proc_pid_stat->{$pid};
2189 if (!$old) {
19672434
DM
2190 $last_proc_pid_stat->{$pid} = {
2191 time => $ctime,
1e3baf05
DM
2192 used => $used,
2193 cpu => 0,
1e3baf05
DM
2194 };
2195 next;
2196 }
2197
7f0b5beb 2198 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
2199
2200 if ($dtime > 1000) {
2201 my $dutime = $used - $old->{used};
2202
ae4915a2 2203 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 2204 $last_proc_pid_stat->{$pid} = {
19672434 2205 time => $ctime,
1e3baf05
DM
2206 used => $used,
2207 cpu => $d->{cpu},
1e3baf05
DM
2208 };
2209 } else {
2210 $d->{cpu} = $old->{cpu};
1e3baf05
DM
2211 }
2212 }
2213
f5eb281a 2214 return $res if !$full;
03a33f30
DM
2215
2216 my $qmpclient = PVE::QMPClient->new();
2217
64e7fcf2
DM
2218 my $ballooncb = sub {
2219 my ($vmid, $resp) = @_;
2220
2221 my $info = $resp->{'return'};
2222 return if !$info->{max_mem};
be190583 2223
64e7fcf2
DM
2224 my $d = $res->{$vmid};
2225
2226 # use memory assigned to VM
2227 $d->{maxmem} = $info->{max_mem};
2228 $d->{balloon} = $info->{actual};
be190583 2229
64e7fcf2
DM
2230 if (defined($info->{total_mem}) && defined($info->{free_mem})) {
2231 $d->{mem} = $info->{total_mem} - $info->{free_mem};
2232 $d->{freemem} = $info->{free_mem};
2233 }
2234
2235 };
2236
03a33f30
DM
2237 my $blockstatscb = sub {
2238 my ($vmid, $resp) = @_;
2239 my $data = $resp->{'return'} || [];
2240 my $totalrdbytes = 0;
2241 my $totalwrbytes = 0;
2242 for my $blockstat (@$data) {
2243 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
2244 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
2245 }
2246 $res->{$vmid}->{diskread} = $totalrdbytes;
2247 $res->{$vmid}->{diskwrite} = $totalwrbytes;
2248 };
2249
2250 my $statuscb = sub {
2251 my ($vmid, $resp) = @_;
64e7fcf2 2252
03a33f30 2253 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
64e7fcf2
DM
2254 # this fails if ballon driver is not loaded, so this must be
2255 # the last commnand (following command are aborted if this fails).
2256 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
03a33f30
DM
2257
2258 my $status = 'unknown';
2259 if (!defined($status = $resp->{'return'}->{status})) {
2260 warn "unable to get VM status\n";
2261 return;
2262 }
2263
2264 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
2265 };
2266
2267 foreach my $vmid (keys %$list) {
2268 next if $opt_vmid && ($vmid ne $opt_vmid);
2269 next if !$res->{$vmid}->{pid}; # not running
2270 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2271 }
2272
2273 $qmpclient->queue_execute();
2274
2275 foreach my $vmid (keys %$list) {
2276 next if $opt_vmid && ($vmid ne $opt_vmid);
2277 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
2278 }
2279
1e3baf05
DM
2280 return $res;
2281}
2282
2283sub foreach_drive {
2284 my ($conf, $func) = @_;
2285
2286 foreach my $ds (keys %$conf) {
2287 next if !valid_drivename($ds);
2288
6b64503e 2289 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
2290 next if !$drive;
2291
2292 &$func($ds, $drive);
2293 }
2294}
2295
d5769dc2
DM
2296sub foreach_volid {
2297 my ($conf, $func) = @_;
be190583 2298
d5769dc2
DM
2299 my $volhash = {};
2300
2301 my $test_volid = sub {
2302 my ($volid, $is_cdrom) = @_;
2303
2304 return if !$volid;
be190583 2305
d5769dc2
DM
2306 $volhash->{$volid} = $is_cdrom || 0;
2307 };
2308
ed221350 2309 foreach_drive($conf, sub {
d5769dc2
DM
2310 my ($ds, $drive) = @_;
2311 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2312 });
2313
2314 foreach my $snapname (keys %{$conf->{snapshots}}) {
2315 my $snap = $conf->{snapshots}->{$snapname};
2316 &$test_volid($snap->{vmstate}, 0);
ed221350 2317 foreach_drive($snap, sub {
d5769dc2
DM
2318 my ($ds, $drive) = @_;
2319 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2320 });
2321 }
2322
2323 foreach my $volid (keys %$volhash) {
be190583 2324 &$func($volid, $volhash->{$volid});
d5769dc2
DM
2325 }
2326}
2327
86b8228b
DM
2328sub vga_conf_has_spice {
2329 my ($vga) = @_;
2330
590e698c
DM
2331 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2332
2333 return $1 || 1;
86b8228b
DM
2334}
2335
1e3baf05 2336sub config_to_command {
952958bc 2337 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
1e3baf05
DM
2338
2339 my $cmd = [];
8c559505
DM
2340 my $globalFlags = [];
2341 my $machineFlags = [];
2342 my $rtcFlags = [];
519ed28c 2343 my $cpuFlags = [];
5bdcf937 2344 my $devices = [];
b78ebef7 2345 my $pciaddr = '';
5bdcf937 2346 my $bridges = {};
1e3baf05
DM
2347 my $kvmver = kvm_user_version();
2348 my $vernum = 0; # unknown
a3c52213
DM
2349 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2350 $vernum = $1*1000000+$2*1000;
2351 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
2352 $vernum = $1*1000000+$2*1000+$3;
2353 }
2354
a3c52213 2355 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
2356
2357 my $have_ovz = -f '/proc/vz/vestat';
2358
db656e5f
DM
2359 my $q35 = machine_type_is_q35($conf);
2360
1e3baf05
DM
2361 push @$cmd, '/usr/bin/kvm';
2362
2363 push @$cmd, '-id', $vmid;
2364
2365 my $use_virtio = 0;
2366
c971c4f2
AD
2367 my $qmpsocket = qmp_socket($vmid);
2368 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2369 push @$cmd, '-mon', "chardev=qmp,mode=control";
2370
7b7c6d1b 2371 my $socket = vnc_socket($vmid);
1e3baf05
DM
2372 push @$cmd, '-vnc', "unix:$socket,x509,password";
2373
6b64503e 2374 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 2375
1e3baf05
DM
2376 push @$cmd, '-daemonize';
2377
db656e5f
DM
2378 if ($q35) {
2379 # the q35 chipset support native usb2, so we enable usb controller
2380 # by default for this machine type
f8e83f05 2381 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
db656e5f 2382 } else {
f8e83f05
AD
2383 $pciaddr = print_pci_addr("piix3", $bridges);
2384 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
24f0d39a 2385
f8e83f05 2386 my $use_usb2 = 0;
db656e5f
DM
2387 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2388 next if !$conf->{"usb$i"};
2389 $use_usb2 = 1;
2390 }
2391 # include usb device config
2392 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
fcc573ab 2393 }
19672434 2394
5acbfe9e 2395 my $vga = $conf->{vga};
2fa3151e 2396
590e698c
DM
2397 my $qxlnum = vga_conf_has_spice($vga);
2398 $vga = 'qxl' if $qxlnum;
2fa3151e 2399
5acbfe9e 2400 if (!$vga) {
264e519f
DM
2401 if ($conf->{ostype} && ($conf->{ostype} eq 'win8' ||
2402 $conf->{ostype} eq 'win7' ||
5acbfe9e
DM
2403 $conf->{ostype} eq 'w2k8')) {
2404 $vga = 'std';
2405 } else {
2406 $vga = 'cirrus';
2407 }
2408 }
2409
1e3baf05 2410 # enable absolute mouse coordinates (needed by vnc)
5acbfe9e
DM
2411 my $tablet;
2412 if (defined($conf->{tablet})) {
2413 $tablet = $conf->{tablet};
2414 } else {
2415 $tablet = $defaults->{tablet};
590e698c 2416 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
ef5e2be2 2417 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
5acbfe9e
DM
2418 }
2419
db656e5f 2420 push @$devices, '-device', print_tabletdevice_full($conf) if $tablet;
1e3baf05
DM
2421
2422 # host pci devices
040b06b7 2423 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2e3b7e2a
AD
2424 my $d = parse_hostpci($conf->{"hostpci$i"});
2425 next if !$d;
2426
2427 my $pcie = $d->{pcie};
2428 if($pcie){
2429 die "q35 machine model is not enabled" if !$q35;
2430 $pciaddr = print_pcie_addr("hostpci$i");
2431 }else{
2432 $pciaddr = print_pci_addr("hostpci$i", $bridges);
2433 }
2434
2435 my $rombar = $d->{rombar} && $d->{rombar} eq 'off' ? ",rombar=0" : "";
2436 my $driver = $d->{driver} && $d->{driver} eq 'vfio' ? "vfio-pci" : "pci-assign";
2437 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ? ",x-vga=on" : "";
2438 $driver = "vfio-pci" if $xvga ne '';
4543ecf0
AD
2439 my $pcidevices = $d->{pciid};
2440 my $multifunction = 1 if @$pcidevices > 1;
2e3b7e2a 2441
4543ecf0
AD
2442 my $j=0;
2443 foreach my $pcidevice (@$pcidevices) {
2e3b7e2a 2444
4543ecf0
AD
2445 my $id = "hostpci$i";
2446 $id .= ".$j" if $multifunction;
2447 my $addr = $pciaddr;
2448 $addr .= ".$j" if $multifunction;
2449 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2450
2451 if($j == 0){
2452 $devicestr .= "$rombar$xvga";
2453 $devicestr .= ",multifunction=on" if $multifunction;
2454 }
2455
2456 push @$devices, '-device', $devicestr;
2457 $j++;
2458 }
1e3baf05
DM
2459 }
2460
2461 # usb devices
2462 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2463 my $d = parse_usb_device($conf->{"usb$i"});
2464 next if !$d;
2465 if ($d->{vendorid} && $d->{productid}) {
5bdcf937 2466 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
1e3baf05 2467 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
5bdcf937 2468 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
80401dd8
DM
2469 } elsif ($d->{spice}) {
2470 # usb redir support for spice
2471 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2472 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
1e3baf05
DM
2473 }
2474 }
2475
1e3baf05 2476 # serial devices
bae179aa 2477 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 2478 if (my $path = $conf->{"serial$i"}) {
9f9d2fb2
DM
2479 if ($path eq 'socket') {
2480 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2481 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2482 push @$devices, '-device', "isa-serial,chardev=serial$i";
2483 } else {
2484 die "no such serial device\n" if ! -c $path;
2485 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2486 push @$devices, '-device', "isa-serial,chardev=serial$i";
2487 }
34978be3 2488 }
1e3baf05
DM
2489 }
2490
2491 # parallel devices
1989a89c 2492 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 2493 if (my $path = $conf->{"parallel$i"}) {
19672434 2494 die "no such parallel device\n" if ! -c $path;
32e69805 2495 my $devtype = $path =~ m!^/dev/usb/lp! ? 'tty' : 'parport';
4c5dbaf6 2496 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
5bdcf937 2497 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
34978be3 2498 }
1e3baf05
DM
2499 }
2500
2501 my $vmname = $conf->{name} || "vm$vmid";
2502
2503 push @$cmd, '-name', $vmname;
19672434 2504
1e3baf05
DM
2505 my $sockets = 1;
2506 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2507 $sockets = $conf->{sockets} if $conf->{sockets};
2508
2509 my $cores = $conf->{cores} || 1;
3bd18e48
AD
2510 my $maxcpus = $conf->{maxcpus} if $conf->{maxcpus};
2511
264e519f 2512 if ($maxcpus) {
3bd18e48 2513 push @$cmd, '-smp', "cpus=$cores,maxcpus=$maxcpus";
264e519f 2514 } else {
3bd18e48
AD
2515 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2516 }
1e3baf05 2517
1e3baf05
DM
2518 push @$cmd, '-nodefaults';
2519
32baffb4 2520 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 2521
0888fdce
DM
2522 my $bootindex_hash = {};
2523 my $i = 1;
2524 foreach my $o (split(//, $bootorder)) {
2525 $bootindex_hash->{$o} = $i*100;
2526 $i++;
afdb31d5 2527 }
3b408e82
DM
2528
2529 push @$cmd, '-boot', "menu=on";
1e3baf05 2530
6b64503e 2531 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 2532
6b64503e 2533 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05 2534
ef5e2be2 2535 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
1e3baf05
DM
2536
2537 # time drift fix
6b64503e 2538 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05 2539
6b64503e 2540 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
8c559505 2541 my $useLocaltime = $conf->{localtime};
1e3baf05
DM
2542
2543 if (my $ost = $conf->{ostype}) {
6b9d84cf 2544 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
1e3baf05
DM
2545
2546 if ($ost =~ m/^w/) { # windows
8c559505 2547 $useLocaltime = 1 if !defined($conf->{localtime});
1e3baf05 2548
8c559505 2549 # use time drift fix when acpi is enabled
6b64503e 2550 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
8c559505 2551 $tdf = 1 if !defined($conf->{tdf});
1e3baf05
DM
2552 }
2553 }
2554
be190583 2555 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
a70ebde3 2556 $ost eq 'wvista') {
8c559505 2557 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
b7e0c8bf 2558 push @$cmd, '-no-hpet';
462e8d19
AD
2559 #push @$cpuFlags , 'hv_vapic" if !$nokvm; #fixme, my win2008R2 hang at boot with this
2560 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2561 }
2562
2563 if ($ost eq 'win7' || $ost eq 'win8') {
2564 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
b7e0c8bf 2565 }
1e3baf05
DM
2566 }
2567
8c559505
DM
2568 push @$rtcFlags, 'driftfix=slew' if $tdf;
2569
7f0b5beb 2570 if ($nokvm) {
8c559505 2571 push @$machineFlags, 'accel=tcg';
7f0b5beb
DM
2572 } else {
2573 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2574 }
1e3baf05 2575
952958bc
DM
2576 my $machine_type = $forcemachine || $conf->{machine};
2577 if ($machine_type) {
2578 push @$machineFlags, "type=${machine_type}";
3bafc510
DM
2579 }
2580
8c559505
DM
2581 if ($conf->{startdate}) {
2582 push @$rtcFlags, "base=$conf->{startdate}";
2583 } elsif ($useLocaltime) {
2584 push @$rtcFlags, 'base=localtime';
2585 }
1e3baf05 2586
519ed28c
AD
2587 my $cpu = $nokvm ? "qemu64" : "kvm64";
2588 $cpu = $conf->{cpu} if $conf->{cpu};
2589
4dc339e7
AD
2590 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2591
6b9d84cf
AD
2592 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype} ne 'solaris';
2593
2594 push @$cpuFlags , '-x2apic' if $conf->{ostype} eq 'solaris';
519ed28c 2595
2e1a5389
AD
2596 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2597
be190583 2598 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
519ed28c 2599
c0efd8cd
DM
2600 # Note: enforce needs kernel 3.10, so we do not use it for now
2601 # push @$cmd, '-cpu', "$cpu,enforce";
2602 push @$cmd, '-cpu', $cpu;
519ed28c 2603
1e3baf05
DM
2604 push @$cmd, '-S' if $conf->{freeze};
2605
2606 # set keyboard layout
2607 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2608 push @$cmd, '-k', $kb if $kb;
2609
2610 # enable sound
2611 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2612 #push @$cmd, '-soundhw', 'es1370';
2613 #push @$cmd, '-soundhw', $soundhw if $soundhw;
ab6a046f 2614
bc84dcca 2615 if($conf->{agent}) {
ab6a046f
AD
2616 my $qgasocket = qga_socket($vmid);
2617 my $pciaddr = print_pci_addr("qga0", $bridges);
2618 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2619 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2620 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2621 }
2622
1d794448 2623 my $spice_port;
2fa3151e 2624
590e698c
DM
2625 if ($qxlnum) {
2626 if ($qxlnum > 1) {
2627 if ($conf->{ostype} && $conf->{ostype} =~ m/^w/){
2628 for(my $i = 1; $i < $qxlnum; $i++){
2629 my $pciaddr = print_pci_addr("vga$i", $bridges);
2630 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
2631 }
2632 } else {
2633 # assume other OS works like Linux
2634 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
2635 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2fa3151e
AD
2636 }
2637 }
2638
1011b570 2639 my $pciaddr = print_pci_addr("spice", $bridges);
95a4b4a9 2640
cd339d1f 2641 $spice_port = PVE::Tools::next_spice_port();
943340a6 2642
1d794448 2643 push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
1011b570 2644
1011b570
DM
2645 push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
2646 push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
2647 push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
2648 }
2649
8d9ae0d2
DM
2650 # enable balloon by default, unless explicitly disabled
2651 if (!defined($conf->{balloon}) || $conf->{balloon}) {
2652 $pciaddr = print_pci_addr("balloon0", $bridges);
2653 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2654 }
1e3baf05 2655
0ea9541d
DM
2656 if ($conf->{watchdog}) {
2657 my $wdopts = parse_watchdog($conf->{watchdog});
5bdcf937 2658 $pciaddr = print_pci_addr("watchdog", $bridges);
0a40e8ea 2659 my $watchdog = $wdopts->{model} || 'i6300esb';
5bdcf937
AD
2660 push @$devices, '-device', "$watchdog$pciaddr";
2661 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
0ea9541d
DM
2662 }
2663
1e3baf05 2664 my $vollist = [];
941e0c42 2665 my $scsicontroller = {};
26ee04b6 2666 my $ahcicontroller = {};
cdd20088 2667 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
1e3baf05 2668
5881b913
DM
2669 # Add iscsi initiator name if available
2670 if (my $initiator = get_initiator_name()) {
2671 push @$devices, '-iscsi', "initiator-name=$initiator";
2672 }
2673
1e3baf05
DM
2674 foreach_drive($conf, sub {
2675 my ($ds, $drive) = @_;
2676
ff1a2432 2677 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 2678 push @$vollist, $drive->{file};
ff1a2432 2679 }
afdb31d5 2680
1e3baf05 2681 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
2682
2683 if (drive_is_cdrom ($drive)) {
2684 if ($bootindex_hash->{d}) {
2685 $drive->{bootindex} = $bootindex_hash->{d};
2686 $bootindex_hash->{d} += 1;
2687 }
2688 } else {
2689 if ($bootindex_hash->{c}) {
2690 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2691 $bootindex_hash->{c} += 1;
2692 }
2693 }
2694
941e0c42 2695 if ($drive->{interface} eq 'scsi') {
cdd20088 2696
5b952ff5 2697 my $maxdev = ($scsihw !~ m/^lsi/) ? 256 : 7;
cdd20088 2698 my $controller = int($drive->{index} / $maxdev);
5bdcf937
AD
2699 $pciaddr = print_pci_addr("scsihw$controller", $bridges);
2700 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
cdd20088 2701 $scsicontroller->{$controller}=1;
941e0c42 2702 }
3b408e82 2703
26ee04b6
DA
2704 if ($drive->{interface} eq 'sata') {
2705 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
5bdcf937
AD
2706 $pciaddr = print_pci_addr("ahci$controller", $bridges);
2707 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
26ee04b6
DA
2708 $ahcicontroller->{$controller}=1;
2709 }
46f58b5f 2710
15b21acc
MR
2711 my $drive_cmd = print_drive_full($storecfg, $vmid, $drive);
2712 push @$devices, '-drive',$drive_cmd;
46f58b5f 2713 push @$devices, '-device', print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges);
1e3baf05
DM
2714 });
2715
2716 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
19672434 2717
cc4d6182 2718 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 2719 next if !$conf->{"net$i"};
cc4d6182
DA
2720 my $d = parse_net($conf->{"net$i"});
2721 next if !$d;
1e3baf05 2722
cc4d6182 2723 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 2724
cc4d6182
DA
2725 if ($bootindex_hash->{n}) {
2726 $d->{bootindex} = $bootindex_hash->{n};
2727 $bootindex_hash->{n} += 1;
2728 }
1e3baf05 2729
cc4d6182 2730 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
5bdcf937
AD
2731 push @$devices, '-netdev', $netdevfull;
2732
2733 my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i",$bridges);
2734 push @$devices, '-device', $netdevicefull;
2735 }
1e3baf05 2736
db656e5f
DM
2737 if (!$q35) {
2738 # add pci bridges
f8e83f05
AD
2739 while (my ($k, $v) = each %$bridges) {
2740 $pciaddr = print_pci_addr("pci.$k");
2741 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2742 }
19672434
DM
2743 }
2744
1e3baf05
DM
2745 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2746 # when the VM uses virtio devices.
19672434
DM
2747 if (!$use_virtio && $have_ovz) {
2748
6b64503e 2749 my $cpuunits = defined($conf->{cpuunits}) ?
1e3baf05
DM
2750 $conf->{cpuunits} : $defaults->{cpuunits};
2751
2752 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2753
2754 # fixme: cpulimit is currently ignored
2755 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2756 }
2757
2758 # add custom args
2759 if ($conf->{args}) {
3ada46c9 2760 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
2761 push @$cmd, @$aa;
2762 }
2763
5bdcf937 2764 push @$cmd, @$devices;
be190583 2765 push @$cmd, '-rtc', join(',', @$rtcFlags)
8c559505 2766 if scalar(@$rtcFlags);
be190583 2767 push @$cmd, '-machine', join(',', @$machineFlags)
8c559505
DM
2768 if scalar(@$machineFlags);
2769 push @$cmd, '-global', join(',', @$globalFlags)
2770 if scalar(@$globalFlags);
2771
1d794448 2772 return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
1e3baf05 2773}
19672434 2774
1e3baf05
DM
2775sub vnc_socket {
2776 my ($vmid) = @_;
2777 return "${var_run_tmpdir}/$vmid.vnc";
2778}
2779
943340a6 2780sub spice_port {
1011b570 2781 my ($vmid) = @_;
943340a6 2782
1d794448 2783 my $res = vm_mon_cmd($vmid, 'query-spice');
943340a6
DM
2784
2785 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
1011b570
DM
2786}
2787
c971c4f2
AD
2788sub qmp_socket {
2789 my ($vmid) = @_;
2790 return "${var_run_tmpdir}/$vmid.qmp";
2791}
2792
ab6a046f
AD
2793sub qga_socket {
2794 my ($vmid) = @_;
2795 return "${var_run_tmpdir}/$vmid.qga";
2796}
2797
1e3baf05
DM
2798sub pidfile_name {
2799 my ($vmid) = @_;
2800 return "${var_run_tmpdir}/$vmid.pid";
2801}
2802
86fdcfb2
DA
2803sub vm_devices_list {
2804 my ($vmid) = @_;
2805
ceea9078
DM
2806 my $res = vm_mon_cmd($vmid, 'query-pci');
2807
2808 my $devices = {};
2809 foreach my $pcibus (@$res) {
2810 foreach my $device (@{$pcibus->{devices}}) {
2811 next if !$device->{'qdev_id'};
2812 $devices->{$device->{'qdev_id'}} = $device;
1dc4f496
DM
2813 }
2814 }
86fdcfb2 2815
1dc4f496 2816 return $devices;
86fdcfb2
DA
2817}
2818
ec21aa11 2819sub vm_deviceplug {
f19d1c47 2820 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
ae57f6b3 2821
cd6ecb89 2822 return 1 if !check_running($vmid);
db656e5f
DM
2823
2824 my $q35 = machine_type_is_q35($conf);
2825
cd6ecb89 2826 if ($deviceid eq 'tablet') {
db656e5f 2827 qemu_deviceadd($vmid, print_tabletdevice_full($conf));
cd6ecb89
AD
2828 return 1;
2829 }
2830
2dbe827e 2831 return 1 if !$conf->{hotplug};
afdb31d5 2832
95d6343b
DA
2833 my $devices_list = vm_devices_list($vmid);
2834 return 1 if defined($devices_list->{$deviceid});
2835
40f28a9f
AD
2836 qemu_bridgeadd($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2837
5e5dcb73
DA
2838 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2839 return undef if !qemu_driveadd($storecfg, $vmid, $device);
cdd20088 2840 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
5e5dcb73
DA
2841 qemu_deviceadd($vmid, $devicefull);
2842 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2843 qemu_drivedel($vmid, $deviceid);
2844 return undef;
2845 }
f19d1c47 2846 }
cfc817c7 2847
cdd20088
AD
2848 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2849 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
cfc817c7 2850 my $pciaddr = print_pci_addr($deviceid);
cdd20088 2851 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
cfc817c7
DA
2852 qemu_deviceadd($vmid, $devicefull);
2853 return undef if(!qemu_deviceaddverify($vmid, $deviceid));
2854 }
2855
a4f091a0 2856 if ($deviceid =~ m/^(scsi)(\d+)$/) {
5b952ff5 2857 return 1 if ($conf->{scsihw} && ($conf->{scsihw} !~ m/^lsi/)); #virtio-scsi not yet support hotplug
cdd20088 2858 return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
a4f091a0 2859 return undef if !qemu_driveadd($storecfg, $vmid, $device);
cdd20088 2860 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
a4f091a0
DA
2861 if(!qemu_deviceadd($vmid, $devicefull)) {
2862 qemu_drivedel($vmid, $deviceid);
2863 return undef;
2864 }
2865 }
2866
2630d2a9
DA
2867 if ($deviceid =~ m/^(net)(\d+)$/) {
2868 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
2869 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
2870 qemu_deviceadd($vmid, $netdevicefull);
2871 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2872 qemu_netdevdel($vmid, $deviceid);
2873 return undef;
2874 }
2875 }
2876
f8e83f05
AD
2877
2878 if (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
40f28a9f
AD
2879 my $bridgeid = $2;
2880 my $pciaddr = print_pci_addr($deviceid);
2881 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2882 qemu_deviceadd($vmid, $devicefull);
2883 return undef if !qemu_deviceaddverify($vmid, $deviceid);
2884 }
2885
5e5dcb73 2886 return 1;
a4dea331
DA
2887}
2888
ec21aa11 2889sub vm_deviceunplug {
f19d1c47 2890 my ($vmid, $conf, $deviceid) = @_;
873c2d69 2891
cd6ecb89
AD
2892 return 1 if !check_running ($vmid);
2893
2894 if ($deviceid eq 'tablet') {
2895 qemu_devicedel($vmid, $deviceid);
2896 return 1;
2897 }
2898
2dbe827e 2899 return 1 if !$conf->{hotplug};
873c2d69 2900
95d6343b
DA
2901 my $devices_list = vm_devices_list($vmid);
2902 return 1 if !defined($devices_list->{$deviceid});
2903
ae57f6b3 2904 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
f19d1c47 2905
5e5dcb73 2906 if ($deviceid =~ m/^(virtio)(\d+)$/) {
5e5dcb73
DA
2907 qemu_devicedel($vmid, $deviceid);
2908 return undef if !qemu_devicedelverify($vmid, $deviceid);
1f219ef5 2909 return undef if !qemu_drivedel($vmid, $deviceid);
5e5dcb73 2910 }
cfc817c7
DA
2911
2912 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2913 return undef if !qemu_devicedel($vmid, $deviceid);
2914 }
2915
a4f091a0
DA
2916 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2917 return undef if !qemu_devicedel($vmid, $deviceid);
2918 return undef if !qemu_drivedel($vmid, $deviceid);
2919 }
2920
2630d2a9 2921 if ($deviceid =~ m/^(net)(\d+)$/) {
2630d2a9
DA
2922 qemu_devicedel($vmid, $deviceid);
2923 return undef if !qemu_devicedelverify($vmid, $deviceid);
750886f8 2924 return undef if !qemu_netdevdel($vmid, $deviceid);
2630d2a9
DA
2925 }
2926
5e5dcb73
DA
2927 return 1;
2928}
2929
2930sub qemu_deviceadd {
2931 my ($vmid, $devicefull) = @_;
873c2d69 2932
d695b5b7
AD
2933 $devicefull = "driver=".$devicefull;
2934 my %options = split(/[=,]/, $devicefull);
f19d1c47 2935
d695b5b7
AD
2936 vm_mon_cmd($vmid, "device_add" , %options);
2937 return 1;
5e5dcb73 2938}
afdb31d5 2939
5e5dcb73
DA
2940sub qemu_devicedel {
2941 my($vmid, $deviceid) = @_;
5a77d8c1
AD
2942 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
2943 return 1;
5e5dcb73
DA
2944}
2945
2946sub qemu_driveadd {
2947 my($storecfg, $vmid, $device) = @_;
2948
2949 my $drive = print_drive_full($storecfg, $vmid, $device);
7b7c6d1b 2950 my $ret = vm_human_monitor_command($vmid, "drive_add auto $drive");
5e5dcb73
DA
2951 # If the command succeeds qemu prints: "OK"
2952 if ($ret !~ m/OK/s) {
2953 syslog("err", "adding drive failed: $ret");
2954 return undef;
f19d1c47 2955 }
5e5dcb73
DA
2956 return 1;
2957}
afdb31d5 2958
5e5dcb73
DA
2959sub qemu_drivedel {
2960 my($vmid, $deviceid) = @_;
873c2d69 2961
7b7c6d1b 2962 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73
DA
2963 $ret =~ s/^\s+//;
2964 if ($ret =~ m/Device \'.*?\' not found/s) {
afdb31d5 2965 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
5e5dcb73
DA
2966 }
2967 elsif ($ret ne "") {
2968 syslog("err", "deleting drive $deviceid failed : $ret");
2969 return undef;
873c2d69 2970 }
5e5dcb73
DA
2971 return 1;
2972}
f19d1c47 2973
5e5dcb73
DA
2974sub qemu_deviceaddverify {
2975 my ($vmid,$deviceid) = @_;
873c2d69 2976
5e5dcb73
DA
2977 for (my $i = 0; $i <= 5; $i++) {
2978 my $devices_list = vm_devices_list($vmid);
2979 return 1 if defined($devices_list->{$deviceid});
2980 sleep 1;
afdb31d5 2981 }
5e5dcb73
DA
2982 syslog("err", "error on hotplug device $deviceid");
2983 return undef;
2984}
afdb31d5 2985
5e5dcb73
DA
2986
2987sub qemu_devicedelverify {
2988 my ($vmid,$deviceid) = @_;
2989
2990 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2991 for (my $i = 0; $i <= 5; $i++) {
2992 my $devices_list = vm_devices_list($vmid);
2993 return 1 if !defined($devices_list->{$deviceid});
2994 sleep 1;
afdb31d5 2995 }
5e5dcb73
DA
2996 syslog("err", "error on hot-unplugging device $deviceid");
2997 return undef;
873c2d69
DA
2998}
2999
cdd20088 3000sub qemu_findorcreatescsihw {
cfc817c7
DA
3001 my ($storecfg, $conf, $vmid, $device) = @_;
3002
5b952ff5 3003 my $maxdev = ($conf->{scsihw} && ($conf->{scsihw} !~ m/^lsi/)) ? 256 : 7;
cfc817c7 3004 my $controller = int($device->{index} / $maxdev);
cdd20088 3005 my $scsihwid="scsihw$controller";
cfc817c7
DA
3006 my $devices_list = vm_devices_list($vmid);
3007
cdd20088
AD
3008 if(!defined($devices_list->{$scsihwid})) {
3009 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $scsihwid);
cfc817c7
DA
3010 }
3011 return 1;
3012}
3013
40f28a9f
AD
3014sub qemu_bridgeadd {
3015 my ($storecfg, $conf, $vmid, $device) = @_;
3016
3017 my $bridges = {};
3018 my $bridgeid = undef;
3019 print_pci_addr($device, $bridges);
3020
3021 while (my ($k, $v) = each %$bridges) {
3022 $bridgeid = $k;
3023 }
0e616534 3024 return if !$bridgeid || $bridgeid < 1;
40f28a9f
AD
3025 my $bridge = "pci.$bridgeid";
3026 my $devices_list = vm_devices_list($vmid);
3027
3028 if(!defined($devices_list->{$bridge})) {
3029 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3030 }
3031 return 1;
3032}
3033
2630d2a9
DA
3034sub qemu_netdevadd {
3035 my ($vmid, $conf, $device, $deviceid) = @_;
3036
3037 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
73aa03b8 3038 my %options = split(/[=,]/, $netdev);
2630d2a9 3039
73aa03b8
AD
3040 vm_mon_cmd($vmid, "netdev_add", %options);
3041 return 1;
2630d2a9
DA
3042}
3043
3044sub qemu_netdevdel {
3045 my ($vmid, $deviceid) = @_;
3046
89c1e0f4
AD
3047 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
3048 return 1;
2630d2a9
DA
3049}
3050
838776ab
AD
3051sub qemu_cpu_hotplug {
3052 my ($vmid, $conf, $cores) = @_;
3053
3054 die "new cores config is not defined" if !$cores;
264e519f
DM
3055 die "you can't add more cores than maxcpus"
3056 if $conf->{maxcpus} && ($cores > $conf->{maxcpus});
838776ab
AD
3057 return if !check_running($vmid);
3058
3059 my $currentcores = $conf->{cores} if $conf->{cores};
3060 die "current cores is not defined" if !$currentcores;
3061 die "maxcpus is not defined" if !$conf->{maxcpus};
264e519f
DM
3062 raise_param_exc({ 'cores' => "online cpu unplug is not yet possible" })
3063 if($cores < $currentcores);
838776ab
AD
3064
3065 my $currentrunningcores = vm_mon_cmd($vmid, "query-cpus");
264e519f
DM
3066 raise_param_exc({ 'cores' => "cores number if running vm is different than configuration" })
3067 if scalar (@{$currentrunningcores}) != $currentcores;
838776ab 3068
264e519f 3069 for(my $i = $currentcores; $i < $cores; $i++) {
838776ab
AD
3070 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3071 }
3072}
3073
affd2f88
AD
3074sub qemu_block_set_io_throttle {
3075 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3076
f3f323a3
AD
3077 return if !check_running($vmid) ;
3078
f3f323a3
AD
3079 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));
3080
affd2f88
AD
3081}
3082
f5eb281a 3083# old code, only used to shutdown old VM after update
dab36e1e
DM
3084sub __read_avail {
3085 my ($fh, $timeout) = @_;
3086
3087 my $sel = new IO::Select;
3088 $sel->add($fh);
3089
3090 my $res = '';
3091 my $buf;
3092
3093 my @ready;
3094 while (scalar (@ready = $sel->can_read($timeout))) {
3095 my $count;
3096 if ($count = $fh->sysread($buf, 8192)) {
3097 if ($buf =~ /^(.*)\(qemu\) $/s) {
3098 $res .= $1;
3099 last;
3100 } else {
3101 $res .= $buf;
3102 }
3103 } else {
3104 if (!defined($count)) {
3105 die "$!\n";
3106 }
3107 last;
3108 }
3109 }
3110
3111 die "monitor read timeout\n" if !scalar(@ready);
f5eb281a 3112
dab36e1e
DM
3113 return $res;
3114}
3115
f5eb281a 3116# old code, only used to shutdown old VM after update
dab36e1e
DM
3117sub vm_monitor_command {
3118 my ($vmid, $cmdstr, $nocheck) = @_;
f5eb281a 3119
dab36e1e
DM
3120 my $res;
3121
3122 eval {
3123 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3124
3125 my $sname = "${var_run_tmpdir}/$vmid.mon";
3126
3127 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3128 die "unable to connect to VM $vmid socket - $!\n";
3129
3130 my $timeout = 3;
3131
3132 # hack: migrate sometime blocks the monitor (when migrate_downtime
3133 # is set)
3134 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3135 $timeout = 60*60; # 1 hour
3136 }
3137
3138 # read banner;
3139 my $data = __read_avail($sock, $timeout);
3140
3141 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3142 die "got unexpected qemu monitor banner\n";
3143 }
3144
3145 my $sel = new IO::Select;
3146 $sel->add($sock);
3147
3148 if (!scalar(my @ready = $sel->can_write($timeout))) {
3149 die "monitor write error - timeout";
3150 }
3151
3152 my $fullcmd = "$cmdstr\r";
3153
3154 # syslog('info', "VM $vmid monitor command: $cmdstr");
3155
3156 my $b;
3157 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3158 die "monitor write error - $!";
3159 }
3160
3161 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3162
3163 $timeout = 20;
3164
3165 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3166 $timeout = 60*60; # 1 hour
3167 } elsif ($cmdstr =~ m/^(eject|change)/) {
3168 $timeout = 60; # note: cdrom mount command is slow
3169 }
3170 if ($res = __read_avail($sock, $timeout)) {
3171
3172 my @lines = split("\r?\n", $res);
f5eb281a 3173
dab36e1e 3174 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
f5eb281a 3175
dab36e1e
DM
3176 $res = join("\n", @lines);
3177 $res .= "\n";
3178 }
3179 };
3180
3181 my $err = $@;
3182
3183 if ($err) {
3184 syslog("err", "VM $vmid monitor command failed - $err");
3185 die $err;
3186 }
f5eb281a 3187
dab36e1e
DM
3188 return $res;
3189}
3190
c1175c92
AD
3191sub qemu_block_resize {
3192 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3193
ed221350 3194 my $running = check_running($vmid);
c1175c92
AD
3195
3196 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3197
3198 return if !$running;
3199
3200 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3201
3202}
3203
1ab0057c
AD
3204sub qemu_volume_snapshot {
3205 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3206
ed221350 3207 my $running = check_running($vmid);
1ab0057c
AD
3208
3209 return if !PVE::Storage::volume_snapshot($storecfg, $volid, $snap, $running);
3210
3211 return if !$running;
3212
3213 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3214
3215}
3216
fc46aff9
AD
3217sub qemu_volume_snapshot_delete {
3218 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3219
ed221350 3220 my $running = check_running($vmid);
fc46aff9
AD
3221
3222 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3223
3224 return if !$running;
3225
18bfb361 3226 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
fc46aff9
AD
3227}
3228
3d5149c9
AD
3229sub qga_freezefs {
3230 my ($vmid) = @_;
3231
3232 #need to impplement call to qemu-ga
3233}
3234
e8f3f18e
AD
3235sub qga_unfreezefs {
3236 my ($vmid) = @_;
3237
3238 #need to impplement call to qemu-ga
3239}
3240
264e519f
DM
3241sub set_migration_caps {
3242 my ($vmid) = @_;
a89fded1 3243
8b8345f3 3244 my $cap_ref = [];
a89fded1
AD
3245
3246 my $enabled_cap = {
8b8345f3
DM
3247 "auto-converge" => 1,
3248 "xbzrle" => 0,
3249 "x-rdma-pin-all" => 0,
3250 "zero-blocks" => 0,
a89fded1
AD
3251 };
3252
8b8345f3 3253 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
a89fded1 3254
8b8345f3 3255 for my $supported_capability (@$supported_capabilities) {
b463a3ce
SP
3256 push @$cap_ref, {
3257 capability => $supported_capability->{capability},
22430fa2
DM
3258 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3259 };
a89fded1
AD
3260 }
3261
8b8345f3
DM
3262 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3263}
a89fded1 3264
1e3baf05 3265sub vm_start {
1d794448 3266 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
1e3baf05 3267
6b64503e 3268 lock_config($vmid, sub {
7e8dcf2c 3269 my $conf = load_config($vmid, $migratedfrom);
1e3baf05 3270
8b43bc11 3271 die "you can't start a vm if it's a template\n" if is_template($conf);
3dcb98d5 3272
6b64503e 3273 check_lock($conf) if !$skiplock;
1e3baf05 3274
7e8dcf2c 3275 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
1e3baf05 3276
6c47d546
DM
3277 my $defaults = load_defaults();
3278
3279 # set environment variable useful inside network script
3280 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
3281
1d794448 3282 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 3283
1e3baf05 3284 my $migrate_port = 0;
5bc1e039 3285 my $migrate_uri;
1e3baf05
DM
3286 if ($statefile) {
3287 if ($statefile eq 'tcp') {
5bc1e039
SP
3288 my $localip = "localhost";
3289 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
3290 if ($datacenterconf->{migration_unsecure}) {
3291 my $nodename = PVE::INotify::nodename();
3292 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
3293 }
f9a971e0 3294 $migrate_port = PVE::Tools::next_migrate_port();
5bc1e039 3295 $migrate_uri = "tcp:${localip}:${migrate_port}";
6c47d546
DM
3296 push @$cmd, '-incoming', $migrate_uri;
3297 push @$cmd, '-S';
1e3baf05 3298 } else {
6c47d546 3299 push @$cmd, '-loadstate', $statefile;
1e3baf05 3300 }
91bd6c90
DM
3301 } elsif ($paused) {
3302 push @$cmd, '-S';
1e3baf05
DM
3303 }
3304
1e3baf05 3305 # host pci devices
040b06b7
DA
3306 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3307 my $d = parse_hostpci($conf->{"hostpci$i"});
3308 next if !$d;
3309 my $info = pci_device_info("0000:$d->{pciid}");
3310 die "IOMMU not present\n" if !check_iommu_support();
3311 die "no pci device info for device '$d->{pciid}'\n" if !$info;
000fc0a2
SP
3312
3313 if ($d->{driver} && $d->{driver} eq "vfio") {
3314 die "can't unbind/bind pci group to vfio '$d->{pciid}'\n" if !pci_dev_group_bind_to_vfio($d->{pciid});
3315 } else {
3316 die "can't unbind/bind to stub pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
3317 }
3318
040b06b7
DA
3319 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
3320 }
1e3baf05
DM
3321
3322 PVE::Storage::activate_volumes($storecfg, $vollist);
3323
585b6e28
DM
3324 eval { run_command($cmd, timeout => $statefile ? undef : 30,
3325 umask => 0077); };
1e3baf05 3326 my $err = $@;
ff1a2432 3327 die "start failed: $err" if $err;
1e3baf05 3328
5bc1e039 3329 print "migration listens on $migrate_uri\n" if $migrate_uri;
afdb31d5 3330
8c609afd 3331 if ($statefile && $statefile ne 'tcp') {
95381ce0 3332 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 3333 warn $@ if $@;
62de2cbd
DM
3334 }
3335
1d794448 3336 if ($migratedfrom) {
a89fded1
AD
3337
3338 eval {
3339 PVE::QemuServer::set_migration_caps($vmid);
3340 };
1d794448 3341 warn $@ if $@;
a89fded1 3342
1d794448
DM
3343 if ($spice_port) {
3344 print "spice listens on port $spice_port\n";
3345 if ($spice_ticket) {
3346 PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
3347 PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
95a4b4a9
AD
3348 }
3349 }
3350
1d794448 3351 } else {
4ec05c4c 3352
15b1fc93 3353 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
be190583 3354 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4ec05c4c 3355 if $conf->{balloon};
be190583
DM
3356 vm_mon_cmd_nocheck($vmid, 'qom-set',
3357 path => "machine/peripheral/balloon0",
3358 property => "guest-stats-polling-interval",
4ec05c4c
AD
3359 value => 2);
3360 }
e18b0b99 3361 }
1e3baf05
DM
3362 });
3363}
3364
0eedc444
AD
3365sub vm_mon_cmd {
3366 my ($vmid, $execute, %params) = @_;
3367
26f11676
DM
3368 my $cmd = { execute => $execute, arguments => \%params };
3369 vm_qmp_command($vmid, $cmd);
0eedc444
AD
3370}
3371
3372sub vm_mon_cmd_nocheck {
3373 my ($vmid, $execute, %params) = @_;
3374
26f11676
DM
3375 my $cmd = { execute => $execute, arguments => \%params };
3376 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
3377}
3378
c971c4f2 3379sub vm_qmp_command {
d967756b 3380 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 3381
c971c4f2 3382 my $res;
26f11676 3383
14db5366
DM
3384 my $timeout;
3385 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
3386 $timeout = $cmd->{arguments}->{timeout};
3387 delete $cmd->{arguments}->{timeout};
3388 }
be190583 3389
c971c4f2
AD
3390 eval {
3391 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
ed221350 3392 my $sname = qmp_socket($vmid);
f5eb281a 3393 if (-e $sname) {
dab36e1e
DM
3394 my $qmpclient = PVE::QMPClient->new();
3395
14db5366 3396 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
dab36e1e
DM
3397 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
3398 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3399 if scalar(%{$cmd->{arguments}});
3400 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
3401 } else {
3402 die "unable to open monitor socket\n";
3403 }
c971c4f2 3404 };
26f11676 3405 if (my $err = $@) {
c971c4f2
AD
3406 syslog("err", "VM $vmid qmp command failed - $err");
3407 die $err;
3408 }
3409
3410 return $res;
3411}
3412
9df5cbcc
DM
3413sub vm_human_monitor_command {
3414 my ($vmid, $cmdline) = @_;
3415
3416 my $res;
3417
f5eb281a 3418 my $cmd = {
9df5cbcc
DM
3419 execute => 'human-monitor-command',
3420 arguments => { 'command-line' => $cmdline},
3421 };
3422
3423 return vm_qmp_command($vmid, $cmd);
3424}
3425
1e3baf05
DM
3426sub vm_commandline {
3427 my ($storecfg, $vmid) = @_;
3428
6b64503e 3429 my $conf = load_config($vmid);
1e3baf05
DM
3430
3431 my $defaults = load_defaults();
3432
6b64503e 3433 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 3434
6b64503e 3435 return join(' ', @$cmd);
1e3baf05
DM
3436}
3437
3438sub vm_reset {
3439 my ($vmid, $skiplock) = @_;
3440
6b64503e 3441 lock_config($vmid, sub {
1e3baf05 3442
6b64503e 3443 my $conf = load_config($vmid);
1e3baf05 3444
6b64503e 3445 check_lock($conf) if !$skiplock;
1e3baf05 3446
816e2c4a 3447 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
3448 });
3449}
3450
3451sub get_vm_volumes {
3452 my ($conf) = @_;
1e3baf05 3453
ff1a2432 3454 my $vollist = [];
d5769dc2
DM
3455 foreach_volid($conf, sub {
3456 my ($volid, $is_cdrom) = @_;
ff1a2432 3457
d5769dc2 3458 return if $volid =~ m|^/|;
ff1a2432 3459
d5769dc2
DM
3460 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
3461 return if !$sid;
ff1a2432
DM
3462
3463 push @$vollist, $volid;
1e3baf05 3464 });
ff1a2432
DM
3465
3466 return $vollist;
3467}
3468
3469sub vm_stop_cleanup {
254575e9 3470 my ($storecfg, $vmid, $conf, $keepActive) = @_;
ff1a2432 3471
745fed70
DM
3472 eval {
3473 fairsched_rmnod($vmid); # try to destroy group
ff1a2432 3474
254575e9
DM
3475 if (!$keepActive) {
3476 my $vollist = get_vm_volumes($conf);
3477 PVE::Storage::deactivate_volumes($storecfg, $vollist);
3478 }
961bfcb2 3479
ab6a046f 3480 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
3481 unlink "/var/run/qemu-server/${vmid}.$ext";
3482 }
745fed70
DM
3483 };
3484 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
3485}
3486
e6c3b671 3487# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
3488# We need that when migration VMs to other nodes (files already moved)
3489# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 3490sub vm_stop {
af30308f 3491 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 3492
9269013a 3493 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 3494
af30308f
DM
3495 if ($migratedfrom){
3496 my $pid = check_running($vmid, $nocheck, $migratedfrom);
3497 kill 15, $pid if $pid;
3498 my $conf = load_config($vmid, $migratedfrom);
3499 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive);
3500 return;
3501 }
3502
e6c3b671 3503 lock_config($vmid, sub {
1e3baf05 3504
e6c3b671 3505 my $pid = check_running($vmid, $nocheck);
ff1a2432 3506 return if !$pid;
1e3baf05 3507
ff1a2432 3508 my $conf;
e6c3b671 3509 if (!$nocheck) {
ff1a2432 3510 $conf = load_config($vmid);
e6c3b671 3511 check_lock($conf) if !$skiplock;
7f4a5b5a
DM
3512 if (!defined($timeout) && $shutdown && $conf->{startup}) {
3513 my $opts = parse_startup($conf->{startup});
3514 $timeout = $opts->{down} if $opts->{down};
3515 }
e6c3b671 3516 }
19672434 3517
7f4a5b5a
DM
3518 $timeout = 60 if !defined($timeout);
3519
9269013a
DM
3520 eval {
3521 if ($shutdown) {
988903ca 3522 $nocheck ? vm_mon_cmd_nocheck($vmid, "system_powerdown") : vm_mon_cmd($vmid, "system_powerdown");
bcb7c9cf 3523
9269013a 3524 } else {
988903ca 3525 $nocheck ? vm_mon_cmd_nocheck($vmid, "quit") : vm_mon_cmd($vmid, "quit");
afdb31d5 3526 }
9269013a 3527 };
1e3baf05
DM
3528 my $err = $@;
3529
3530 if (!$err) {
1e3baf05 3531 my $count = 0;
e6c3b671 3532 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
3533 $count++;
3534 sleep 1;
3535 }
3536
3537 if ($count >= $timeout) {
9269013a
DM
3538 if ($force) {
3539 warn "VM still running - terminating now with SIGTERM\n";
3540 kill 15, $pid;
3541 } else {
3542 die "VM quit/powerdown failed - got timeout\n";
3543 }
3544 } else {
254575e9 3545 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
9269013a 3546 return;
1e3baf05
DM
3547 }
3548 } else {
9269013a
DM
3549 if ($force) {
3550 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3551 kill 15, $pid;
3552 } else {
afdb31d5 3553 die "VM quit/powerdown failed\n";
9269013a 3554 }
1e3baf05
DM
3555 }
3556
3557 # wait again
ff1a2432 3558 $timeout = 10;
1e3baf05
DM
3559
3560 my $count = 0;
e6c3b671 3561 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
3562 $count++;
3563 sleep 1;
3564 }
3565
3566 if ($count >= $timeout) {
ff1a2432 3567 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 3568 kill 9, $pid;
ff1a2432 3569 sleep 1;
1e3baf05
DM
3570 }
3571
254575e9 3572 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
ff1a2432 3573 });
1e3baf05
DM
3574}
3575
3576sub vm_suspend {
3577 my ($vmid, $skiplock) = @_;
3578
6b64503e 3579 lock_config($vmid, sub {
1e3baf05 3580
6b64503e 3581 my $conf = load_config($vmid);
1e3baf05 3582
051347aa 3583 check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
bcb7c9cf 3584
f77f91f3 3585 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
3586 });
3587}
3588
3589sub vm_resume {
3590 my ($vmid, $skiplock) = @_;
3591
6b64503e 3592 lock_config($vmid, sub {
1e3baf05 3593
6b64503e 3594 my $conf = load_config($vmid);
1e3baf05 3595
051347aa 3596 check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
1e3baf05 3597
12060fe8 3598 vm_mon_cmd($vmid, "cont");
1e3baf05
DM
3599 });
3600}
3601
5fdbe4f0
DM
3602sub vm_sendkey {
3603 my ($vmid, $skiplock, $key) = @_;
1e3baf05 3604
6b64503e 3605 lock_config($vmid, sub {
1e3baf05 3606
6b64503e 3607 my $conf = load_config($vmid);
f5eb281a 3608
7b7c6d1b
DM
3609 # there is no qmp command, so we use the human monitor command
3610 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
3611 });
3612}
3613
3614sub vm_destroy {
3615 my ($storecfg, $vmid, $skiplock) = @_;
3616
6b64503e 3617 lock_config($vmid, sub {
1e3baf05 3618
6b64503e 3619 my $conf = load_config($vmid);
1e3baf05 3620
6b64503e 3621 check_lock($conf) if !$skiplock;
1e3baf05 3622
ff1a2432
DM
3623 if (!check_running($vmid)) {
3624 fairsched_rmnod($vmid); # try to destroy group
3625 destroy_vm($storecfg, $vmid);
3626 } else {
3627 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
3628 }
3629 });
3630}
3631
1e3baf05
DM
3632# pci helpers
3633
3634sub file_write {
3635 my ($filename, $buf) = @_;
3636
6b64503e 3637 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
3638 return undef if !$fh;
3639
3640 my $res = print $fh $buf;
3641
3642 $fh->close();
3643
3644 return $res;
3645}
3646
3647sub pci_device_info {
3648 my ($name) = @_;
3649
3650 my $res;
3651
3652 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3653 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3654
3655 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
3656 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3657
3658 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
3659 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3660
3661 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
3662 return undef if !defined($product) || $product !~ s/^0x//;
3663
3664 $res = {
3665 name => $name,
3666 vendor => $vendor,
3667 product => $product,
3668 domain => $domain,
3669 bus => $bus,
3670 slot => $slot,
3671 func => $func,
3672 irq => $irq,
3673 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
3674 };
3675
3676 return $res;
3677}
3678
3679sub pci_dev_reset {
3680 my ($dev) = @_;
3681
3682 my $name = $dev->{name};
3683
3684 my $fn = "$pcisysfs/devices/$name/reset";
3685
6b64503e 3686 return file_write($fn, "1");
1e3baf05
DM
3687}
3688
3689sub pci_dev_bind_to_stub {
3690 my ($dev) = @_;
3691
3692 my $name = $dev->{name};
3693
3694 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3695 return 1 if -d $testdir;
3696
3697 my $data = "$dev->{vendor} $dev->{product}";
6b64503e 3698 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
1e3baf05
DM
3699
3700 my $fn = "$pcisysfs/devices/$name/driver/unbind";
6b64503e 3701 if (!file_write($fn, $name)) {
1e3baf05
DM
3702 return undef if -f $fn;
3703 }
3704
3705 $fn = "$pcisysfs/drivers/pci-stub/bind";
3706 if (! -d $testdir) {
6b64503e 3707 return undef if !file_write($fn, $name);
1e3baf05
DM
3708 }
3709
3710 return -d $testdir;
3711}
3712
000fc0a2
SP
3713sub pci_dev_bind_to_vfio {
3714 my ($dev) = @_;
3715
3716 my $name = $dev->{name};
3717
3718 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
3719
3720 if (!-d $vfio_basedir) {
3721 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
3722 }
3723 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
3724
3725 my $testdir = "$vfio_basedir/$name";
3726 return 1 if -d $testdir;
3727
3728 my $data = "$dev->{vendor} $dev->{product}";
3729 return undef if !file_write("$vfio_basedir/new_id", $data);
3730
3731 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3732 if (!file_write($fn, $name)) {
3733 return undef if -f $fn;
3734 }
3735
3736 $fn = "$vfio_basedir/bind";
3737 if (! -d $testdir) {
3738 return undef if !file_write($fn, $name);
3739 }
3740
3741 return -d $testdir;
3742}
3743
3744sub pci_dev_group_bind_to_vfio {
3745 my ($pciid) = @_;
3746
3747 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
3748
3749 if (!-d $vfio_basedir) {
3750 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
3751 }
3752 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
3753
3754 # get IOMMU group devices
3755 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
3756 my @devs = grep /^0000:/, readdir($D);
3757 closedir($D);
3758
3759 foreach my $pciid (@devs) {
3760 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
3761 my $info = pci_device_info($1);
3762 pci_dev_bind_to_vfio($info) || die "Cannot bind $pciid to vfio\n";
3763 }
3764
3765 return 1;
3766}
3767
afdb31d5 3768sub print_pci_addr {
5bdcf937 3769 my ($id, $bridges) = @_;
6b64503e 3770
72a063e4 3771 my $res = '';
6b64503e 3772 my $devices = {
24f0d39a 3773 piix3 => { bus => 0, addr => 1 },
e5f7f8ed 3774 #addr2 : first videocard
13b5a753 3775 balloon0 => { bus => 0, addr => 3 },
0a40e8ea 3776 watchdog => { bus => 0, addr => 4 },
cdd20088
AD
3777 scsihw0 => { bus => 0, addr => 5 },
3778 scsihw1 => { bus => 0, addr => 6 },
26ee04b6 3779 ahci0 => { bus => 0, addr => 7 },
ab6a046f 3780 qga0 => { bus => 0, addr => 8 },
1011b570 3781 spice => { bus => 0, addr => 9 },
6b64503e
DM
3782 virtio0 => { bus => 0, addr => 10 },
3783 virtio1 => { bus => 0, addr => 11 },
3784 virtio2 => { bus => 0, addr => 12 },
3785 virtio3 => { bus => 0, addr => 13 },
3786 virtio4 => { bus => 0, addr => 14 },
3787 virtio5 => { bus => 0, addr => 15 },
b78ebef7
DA
3788 hostpci0 => { bus => 0, addr => 16 },
3789 hostpci1 => { bus => 0, addr => 17 },
f290f8d9
DA
3790 net0 => { bus => 0, addr => 18 },
3791 net1 => { bus => 0, addr => 19 },
3792 net2 => { bus => 0, addr => 20 },
3793 net3 => { bus => 0, addr => 21 },
3794 net4 => { bus => 0, addr => 22 },
3795 net5 => { bus => 0, addr => 23 },
2fa3151e
AD
3796 vga1 => { bus => 0, addr => 24 },
3797 vga2 => { bus => 0, addr => 25 },
3798 vga3 => { bus => 0, addr => 26 },
e5f7f8ed 3799 #addr29 : usb-host (pve-usb.cfg)
5bdcf937
AD
3800 'pci.1' => { bus => 0, addr => 30 },
3801 'pci.2' => { bus => 0, addr => 31 },
3802 'net6' => { bus => 1, addr => 1 },
3803 'net7' => { bus => 1, addr => 2 },
3804 'net8' => { bus => 1, addr => 3 },
3805 'net9' => { bus => 1, addr => 4 },
3806 'net10' => { bus => 1, addr => 5 },
3807 'net11' => { bus => 1, addr => 6 },
3808 'net12' => { bus => 1, addr => 7 },
3809 'net13' => { bus => 1, addr => 8 },
3810 'net14' => { bus => 1, addr => 9 },
3811 'net15' => { bus => 1, addr => 10 },
3812 'net16' => { bus => 1, addr => 11 },
3813 'net17' => { bus => 1, addr => 12 },
3814 'net18' => { bus => 1, addr => 13 },
3815 'net19' => { bus => 1, addr => 14 },
3816 'net20' => { bus => 1, addr => 15 },
3817 'net21' => { bus => 1, addr => 16 },
3818 'net22' => { bus => 1, addr => 17 },
3819 'net23' => { bus => 1, addr => 18 },
3820 'net24' => { bus => 1, addr => 19 },
3821 'net25' => { bus => 1, addr => 20 },
3822 'net26' => { bus => 1, addr => 21 },
3823 'net27' => { bus => 1, addr => 22 },
3824 'net28' => { bus => 1, addr => 23 },
3825 'net29' => { bus => 1, addr => 24 },
3826 'net30' => { bus => 1, addr => 25 },
3827 'net31' => { bus => 1, addr => 26 },
3828 'virtio6' => { bus => 2, addr => 1 },
3829 'virtio7' => { bus => 2, addr => 2 },
3830 'virtio8' => { bus => 2, addr => 3 },
3831 'virtio9' => { bus => 2, addr => 4 },
3832 'virtio10' => { bus => 2, addr => 5 },
3833 'virtio11' => { bus => 2, addr => 6 },
3834 'virtio12' => { bus => 2, addr => 7 },
3835 'virtio13' => { bus => 2, addr => 8 },
3836 'virtio14' => { bus => 2, addr => 9 },
3837 'virtio15' => { bus => 2, addr => 10 },
6b64503e
DM
3838 };
3839
3840 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
72a063e4 3841 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
5bdcf937
AD
3842 my $bus = $devices->{$id}->{bus};
3843 $res = ",bus=pci.$bus,addr=$addr";
98627641 3844 $bridges->{$bus} = 1 if $bridges;
72a063e4
DA
3845 }
3846 return $res;
3847
3848}
3849
2e3b7e2a
AD
3850sub print_pcie_addr {
3851 my ($id) = @_;
3852
3853 my $res = '';
3854 my $devices = {
3855 hostpci0 => { bus => "ich9-pcie-port-1", addr => 0 },
3856 hostpci1 => { bus => "ich9-pcie-port-2", addr => 0 },
3857 hostpci2 => { bus => "ich9-pcie-port-3", addr => 0 },
3858 hostpci3 => { bus => "ich9-pcie-port-4", addr => 0 },
3859 };
3860
3861 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
3862 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
3863 my $bus = $devices->{$id}->{bus};
3864 $res = ",bus=$bus,addr=$addr";
3865 }
3866 return $res;
3867
3868}
3869
3e16d5fc
DM
3870# vzdump restore implementaion
3871
ed221350 3872sub tar_archive_read_firstfile {
3e16d5fc 3873 my $archive = shift;
afdb31d5 3874
3e16d5fc
DM
3875 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
3876
3877 # try to detect archive type first
3878 my $pid = open (TMP, "tar tf '$archive'|") ||
3879 die "unable to open file '$archive'\n";
3880 my $firstfile = <TMP>;
3881 kill 15, $pid;
3882 close TMP;
3883
3884 die "ERROR: archive contaions no data\n" if !$firstfile;
3885 chomp $firstfile;
3886
3887 return $firstfile;
3888}
3889
ed221350
DM
3890sub tar_restore_cleanup {
3891 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
3892
3893 print STDERR "starting cleanup\n";
3894
3895 if (my $fd = IO::File->new($statfile, "r")) {
3896 while (defined(my $line = <$fd>)) {
3897 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3898 my $volid = $2;
3899 eval {
3900 if ($volid =~ m|^/|) {
3901 unlink $volid || die 'unlink failed\n';
3902 } else {
ed221350 3903 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 3904 }
afdb31d5 3905 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
3906 };
3907 print STDERR "unable to cleanup '$volid' - $@" if $@;
3908 } else {
3909 print STDERR "unable to parse line in statfile - $line";
afdb31d5 3910 }
3e16d5fc
DM
3911 }
3912 $fd->close();
3913 }
3914}
3915
3916sub restore_archive {
a0d1b1a2 3917 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 3918
91bd6c90
DM
3919 my $format = $opts->{format};
3920 my $comp;
3921
3922 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3923 $format = 'tar' if !$format;
3924 $comp = 'gzip';
3925 } elsif ($archive =~ m/\.tar$/) {
3926 $format = 'tar' if !$format;
3927 } elsif ($archive =~ m/.tar.lzo$/) {
3928 $format = 'tar' if !$format;
3929 $comp = 'lzop';
3930 } elsif ($archive =~ m/\.vma$/) {
3931 $format = 'vma' if !$format;
3932 } elsif ($archive =~ m/\.vma\.gz$/) {
3933 $format = 'vma' if !$format;
3934 $comp = 'gzip';
3935 } elsif ($archive =~ m/\.vma\.lzo$/) {
3936 $format = 'vma' if !$format;
3937 $comp = 'lzop';
3938 } else {
3939 $format = 'vma' if !$format; # default
3940 }
3941
3942 # try to detect archive format
3943 if ($format eq 'tar') {
3944 return restore_tar_archive($archive, $vmid, $user, $opts);
3945 } else {
3946 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
3947 }
3948}
3949
3950sub restore_update_config_line {
3951 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3952
3953 return if $line =~ m/^\#qmdump\#/;
3954 return if $line =~ m/^\#vzdump\#/;
3955 return if $line =~ m/^lock:/;
3956 return if $line =~ m/^unused\d+:/;
3957 return if $line =~ m/^parent:/;
ca3e4fa4 3958 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90
DM
3959
3960 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3961 # try to convert old 1.X settings
3962 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3963 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3964 my ($model, $macaddr) = split(/\=/, $devconfig);
3965 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $unique;
3966 my $net = {
3967 model => $model,
3968 bridge => "vmbr$ind",
3969 macaddr => $macaddr,
3970 };
3971 my $netstr = print_net($net);
3972
3973 print $outfd "net$cookie->{netcount}: $netstr\n";
3974 $cookie->{netcount}++;
3975 }
3976 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3977 my ($id, $netstr) = ($1, $2);
3978 my $net = parse_net($netstr);
3979 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3980 $netstr = print_net($net);
3981 print $outfd "$id: $netstr\n";
3982 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3983 my $virtdev = $1;
907ea891 3984 my $value = $3;
91bd6c90
DM
3985 if ($line =~ m/backup=no/) {
3986 print $outfd "#$line";
3987 } elsif ($virtdev && $map->{$virtdev}) {
ed221350 3988 my $di = parse_drive($virtdev, $value);
8fd57431 3989 delete $di->{format}; # format can change on restore
91bd6c90 3990 $di->{file} = $map->{$virtdev};
ed221350 3991 $value = print_drive($vmid, $di);
91bd6c90
DM
3992 print $outfd "$virtdev: $value\n";
3993 } else {
3994 print $outfd $line;
3995 }
3996 } else {
3997 print $outfd $line;
3998 }
3999}
4000
4001sub scan_volids {
4002 my ($cfg, $vmid) = @_;
4003
4004 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
4005
4006 my $volid_hash = {};
4007 foreach my $storeid (keys %$info) {
4008 foreach my $item (@{$info->{$storeid}}) {
4009 next if !($item->{volid} && $item->{size});
5996a936 4010 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
4011 $volid_hash->{$item->{volid}} = $item;
4012 }
4013 }
4014
4015 return $volid_hash;
4016}
4017
a8e2f942
DM
4018sub get_used_paths {
4019 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
4020
4021 my $used_path = {};
4022
4023 my $scan_config = sub {
4024 my ($cref, $snapname) = @_;
4025
4026 foreach my $key (keys %$cref) {
4027 my $value = $cref->{$key};
4028 if (valid_drivename($key)) {
4029 next if $skip_drive && $key eq $skip_drive;
4030 my $drive = parse_drive($key, $value);
4031 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
4032 if ($drive->{file} =~ m!^/!) {
4033 $used_path->{$drive->{file}}++; # = 1;
4034 } else {
4035 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
4036 next if !$storeid;
4037 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
4038 next if !$scfg;
4039 my $path = PVE::Storage::path($storecfg, $drive->{file}, $snapname);
4040 $used_path->{$path}++; # = 1;
4041 }
4042 }
4043 }
4044 };
4045
4046 &$scan_config($conf);
4047
4048 undef $skip_drive;
4049
4050 if ($scan_snapshots) {
4051 foreach my $snapname (keys %{$conf->{snapshots}}) {
4052 &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
4053 }
4054 }
4055
4056 return $used_path;
4057}
4058
91bd6c90
DM
4059sub update_disksize {
4060 my ($vmid, $conf, $volid_hash) = @_;
be190583 4061
91bd6c90
DM
4062 my $changes;
4063
4064 my $used = {};
4065
5996a936
DM
4066 # Note: it is allowed to define multiple storages with same path (alias), so
4067 # we need to check both 'volid' and real 'path' (two different volid can point
4068 # to the same path).
4069
4070 my $usedpath = {};
be190583 4071
91bd6c90
DM
4072 # update size info
4073 foreach my $opt (keys %$conf) {
ed221350
DM
4074 if (valid_drivename($opt)) {
4075 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
4076 my $volid = $drive->{file};
4077 next if !$volid;
4078
4079 $used->{$volid} = 1;
be190583 4080 if ($volid_hash->{$volid} &&
5996a936
DM
4081 (my $path = $volid_hash->{$volid}->{path})) {
4082 $usedpath->{$path} = 1;
4083 }
91bd6c90 4084
ed221350 4085 next if drive_is_cdrom($drive);
91bd6c90
DM
4086 next if !$volid_hash->{$volid};
4087
4088 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
4089 my $new = print_drive($vmid, $drive);
4090 if ($new ne $conf->{$opt}) {
4091 $changes = 1;
4092 $conf->{$opt} = $new;
4093 }
91bd6c90
DM
4094 }
4095 }
4096
5996a936
DM
4097 # remove 'unusedX' entry if volume is used
4098 foreach my $opt (keys %$conf) {
4099 next if $opt !~ m/^unused\d+$/;
4100 my $volid = $conf->{$opt};
4101 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
be190583 4102 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5996a936
DM
4103 $changes = 1;
4104 delete $conf->{$opt};
4105 }
4106 }
4107
91bd6c90
DM
4108 foreach my $volid (sort keys %$volid_hash) {
4109 next if $volid =~ m/vm-$vmid-state-/;
4110 next if $used->{$volid};
5996a936
DM
4111 my $path = $volid_hash->{$volid}->{path};
4112 next if !$path; # just to be sure
4113 next if $usedpath->{$path};
91bd6c90 4114 $changes = 1;
ed221350 4115 add_unused_volume($conf, $volid);
05937a14 4116 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
4117 }
4118
4119 return $changes;
4120}
4121
4122sub rescan {
4123 my ($vmid, $nolock) = @_;
4124
4125 my $cfg = PVE::Cluster::cfs_read_file("storage.cfg");
4126
4127 my $volid_hash = scan_volids($cfg, $vmid);
4128
4129 my $updatefn = sub {
4130 my ($vmid) = @_;
4131
ed221350 4132 my $conf = load_config($vmid);
be190583 4133
ed221350 4134 check_lock($conf);
91bd6c90 4135
03da3f0d
DM
4136 my $vm_volids = {};
4137 foreach my $volid (keys %$volid_hash) {
4138 my $info = $volid_hash->{$volid};
4139 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
4140 }
4141
4142 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 4143
ed221350 4144 update_config_nolock($vmid, $conf, 1) if $changes;
91bd6c90
DM
4145 };
4146
4147 if (defined($vmid)) {
4148 if ($nolock) {
4149 &$updatefn($vmid);
4150 } else {
ed221350 4151 lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
4152 }
4153 } else {
4154 my $vmlist = config_list();
4155 foreach my $vmid (keys %$vmlist) {
4156 if ($nolock) {
4157 &$updatefn($vmid);
4158 } else {
ed221350 4159 lock_config($vmid, $updatefn, $vmid);
be190583 4160 }
91bd6c90
DM
4161 }
4162 }
4163}
4164
4165sub restore_vma_archive {
4166 my ($archive, $vmid, $user, $opts, $comp) = @_;
4167
4168 my $input = $archive eq '-' ? "<&STDIN" : undef;
4169 my $readfrom = $archive;
4170
4171 my $uncomp = '';
4172 if ($comp) {
4173 $readfrom = '-';
4174 my $qarchive = PVE::Tools::shellquote($archive);
4175 if ($comp eq 'gzip') {
4176 $uncomp = "zcat $qarchive|";
4177 } elsif ($comp eq 'lzop') {
4178 $uncomp = "lzop -d -c $qarchive|";
4179 } else {
4180 die "unknown compression method '$comp'\n";
4181 }
be190583 4182
91bd6c90
DM
4183 }
4184
4185 my $tmpdir = "/var/tmp/vzdumptmp$$";
4186 rmtree $tmpdir;
4187
4188 # disable interrupts (always do cleanups)
4189 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
4190 warn "got interrupt - ignored\n";
4191 };
4192
4193 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
4194 POSIX::mkfifo($mapfifo, 0600);
4195 my $fifofh;
4196
4197 my $openfifo = sub {
4198 open($fifofh, '>', $mapfifo) || die $!;
4199 };
4200
4201 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
4202
4203 my $oldtimeout;
4204 my $timeout = 5;
4205
4206 my $devinfo = {};
4207
4208 my $rpcenv = PVE::RPCEnvironment::get();
4209
ed221350 4210 my $conffile = config_file($vmid);
91bd6c90
DM
4211 my $tmpfn = "$conffile.$$.tmp";
4212
ed221350
DM
4213 # Note: $oldconf is undef if VM does not exists
4214 my $oldconf = PVE::Cluster::cfs_read_file(cfs_config_path($vmid));
4215
91bd6c90
DM
4216 my $print_devmap = sub {
4217 my $virtdev_hash = {};
4218
4219 my $cfgfn = "$tmpdir/qemu-server.conf";
4220
4221 # we can read the config - that is already extracted
4222 my $fh = IO::File->new($cfgfn, "r") ||
4223 "unable to read qemu-server.conf - $!\n";
4224
4225 while (defined(my $line = <$fh>)) {
4226 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
4227 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
4228 die "archive does not contain data for drive '$virtdev'\n"
4229 if !$devinfo->{$devname};
4230 if (defined($opts->{storage})) {
4231 $storeid = $opts->{storage} || 'local';
4232 } elsif (!$storeid) {
4233 $storeid = 'local';
4234 }
4235 $format = 'raw' if !$format;
4236 $devinfo->{$devname}->{devname} = $devname;
4237 $devinfo->{$devname}->{virtdev} = $virtdev;
4238 $devinfo->{$devname}->{format} = $format;
4239 $devinfo->{$devname}->{storeid} = $storeid;
4240
be190583 4241 # check permission on storage
91bd6c90
DM
4242 my $pool = $opts->{pool}; # todo: do we need that?
4243 if ($user ne 'root@pam') {
4244 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
4245 }
4246
4247 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
4248 }
4249 }
4250
4251 foreach my $devname (keys %$devinfo) {
be190583
DM
4252 die "found no device mapping information for device '$devname'\n"
4253 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
4254 }
4255
91bd6c90 4256 my $cfg = cfs_read_file('storage.cfg');
ed221350
DM
4257
4258 # create empty/temp config
be190583 4259 if ($oldconf) {
ed221350
DM
4260 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
4261 foreach_drive($oldconf, sub {
4262 my ($ds, $drive) = @_;
4263
4264 return if drive_is_cdrom($drive);
4265
4266 my $volid = $drive->{file};
4267
4268 return if !$volid || $volid =~ m|^/|;
4269
4270 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
4271 return if !$path || !$owner || ($owner != $vmid);
4272
4273 # Note: only delete disk we want to restore
4274 # other volumes will become unused
4275 if ($virtdev_hash->{$ds}) {
4276 PVE::Storage::vdisk_free($cfg, $volid);
4277 }
4278 });
4279 }
4280
4281 my $map = {};
91bd6c90
DM
4282 foreach my $virtdev (sort keys %$virtdev_hash) {
4283 my $d = $virtdev_hash->{$virtdev};
4284 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
4285 my $scfg = PVE::Storage::storage_config($cfg, $d->{storeid});
8fd57431
DM
4286
4287 # test if requested format is supported
4288 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $d->{storeid});
4289 my $supported = grep { $_ eq $d->{format} } @$validFormats;
4290 $d->{format} = $defFormat if !$supported;
4291
91bd6c90
DM
4292 my $volid = PVE::Storage::vdisk_alloc($cfg, $d->{storeid}, $vmid,
4293 $d->{format}, undef, $alloc_size);
4294 print STDERR "new volume ID is '$volid'\n";
4295 $d->{volid} = $volid;
4296 my $path = PVE::Storage::path($cfg, $volid);
4297
4298 my $write_zeros = 1;
4299 # fixme: what other storages types initialize volumes with zero?
244f2577 4300 if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs' || $scfg->{type} eq 'glusterfs' ||
013d5275 4301 $scfg->{type} eq 'sheepdog' || $scfg->{type} eq 'rbd') {
91bd6c90
DM
4302 $write_zeros = 0;
4303 }
4304
4305 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
4306
4307 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
4308 $map->{$virtdev} = $volid;
4309 }
4310
4311 $fh->seek(0, 0) || die "seek failed - $!\n";
4312
4313 my $outfd = new IO::File ($tmpfn, "w") ||
4314 die "unable to write config for VM $vmid\n";
4315
4316 my $cookie = { netcount => 0 };
4317 while (defined(my $line = <$fh>)) {
be190583 4318 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
4319 }
4320
4321 $fh->close();
4322 $outfd->close();
4323 };
4324
4325 eval {
4326 # enable interrupts
4327 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
4328 die "interrupted by signal\n";
4329 };
4330 local $SIG{ALRM} = sub { die "got timeout\n"; };
4331
4332 $oldtimeout = alarm($timeout);
4333
4334 my $parser = sub {
4335 my $line = shift;
4336
4337 print "$line\n";
4338
4339 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
4340 my ($dev_id, $size, $devname) = ($1, $2, $3);
4341 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
4342 } elsif ($line =~ m/^CTIME: /) {
46f58b5f 4343 # we correctly received the vma config, so we can disable
3cf90d7a
DM
4344 # the timeout now for disk allocation (set to 10 minutes, so
4345 # that we always timeout if something goes wrong)
4346 alarm(600);
91bd6c90
DM
4347 &$print_devmap();
4348 print $fifofh "done\n";
4349 my $tmp = $oldtimeout || 0;
4350 $oldtimeout = undef;
4351 alarm($tmp);
4352 close($fifofh);
4353 }
4354 };
be190583 4355
91bd6c90
DM
4356 print "restore vma archive: $cmd\n";
4357 run_command($cmd, input => $input, outfunc => $parser, afterfork => $openfifo);
4358 };
4359 my $err = $@;
4360
4361 alarm($oldtimeout) if $oldtimeout;
4362
4363 unlink $mapfifo;
4364
4365 if ($err) {
4366 rmtree $tmpdir;
4367 unlink $tmpfn;
4368
4369 my $cfg = cfs_read_file('storage.cfg');
4370 foreach my $devname (keys %$devinfo) {
4371 my $volid = $devinfo->{$devname}->{volid};
4372 next if !$volid;
4373 eval {
4374 if ($volid =~ m|^/|) {
4375 unlink $volid || die 'unlink failed\n';
4376 } else {
4377 PVE::Storage::vdisk_free($cfg, $volid);
4378 }
4379 print STDERR "temporary volume '$volid' sucessfuly removed\n";
4380 };
4381 print STDERR "unable to cleanup '$volid' - $@" if $@;
4382 }
4383 die $err;
4384 }
4385
4386 rmtree $tmpdir;
ed221350
DM
4387
4388 rename($tmpfn, $conffile) ||
91bd6c90
DM
4389 die "unable to commit configuration file '$conffile'\n";
4390
ed221350
DM
4391 PVE::Cluster::cfs_update(); # make sure we read new file
4392
91bd6c90
DM
4393 eval { rescan($vmid, 1); };
4394 warn $@ if $@;
4395}
4396
4397sub restore_tar_archive {
4398 my ($archive, $vmid, $user, $opts) = @_;
4399
9c502e26 4400 if ($archive ne '-') {
ed221350 4401 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
4402 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
4403 if $firstfile ne 'qemu-server.conf';
4404 }
3e16d5fc 4405
ed221350 4406 my $storecfg = cfs_read_file('storage.cfg');
ebb55558 4407
ed221350 4408 # destroy existing data - keep empty config
ebb55558
DM
4409 my $vmcfgfn = PVE::QemuServer::config_file($vmid);
4410 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 4411
3e16d5fc
DM
4412 my $tocmd = "/usr/lib/qemu-server/qmextract";
4413
2415a446 4414 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 4415 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
4416 $tocmd .= ' --prealloc' if $opts->{prealloc};
4417 $tocmd .= ' --info' if $opts->{info};
4418
a0d1b1a2 4419 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 4420 # so we pipe to zcat
2415a446
DM
4421 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
4422 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
4423
4424 my $tmpdir = "/var/tmp/vzdumptmp$$";
4425 mkpath $tmpdir;
4426
4427 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
4428 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 4429 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 4430
ed221350 4431 my $conffile = config_file($vmid);
3e16d5fc
DM
4432 my $tmpfn = "$conffile.$$.tmp";
4433
4434 # disable interrupts (always do cleanups)
4435 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
4436 print STDERR "got interrupt - ignored\n";
4437 };
4438
afdb31d5 4439 eval {
3e16d5fc
DM
4440 # enable interrupts
4441 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
4442 die "interrupted by signal\n";
4443 };
4444
9c502e26
DM
4445 if ($archive eq '-') {
4446 print "extracting archive from STDIN\n";
4447 run_command($cmd, input => "<&STDIN");
4448 } else {
4449 print "extracting archive '$archive'\n";
4450 run_command($cmd);
4451 }
3e16d5fc
DM
4452
4453 return if $opts->{info};
4454
4455 # read new mapping
4456 my $map = {};
4457 my $statfile = "$tmpdir/qmrestore.stat";
4458 if (my $fd = IO::File->new($statfile, "r")) {
4459 while (defined (my $line = <$fd>)) {
4460 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4461 $map->{$1} = $2 if $1;
4462 } else {
4463 print STDERR "unable to parse line in statfile - $line\n";
4464 }
4465 }
4466 $fd->close();
4467 }
4468
4469 my $confsrc = "$tmpdir/qemu-server.conf";
4470
4471 my $srcfd = new IO::File($confsrc, "r") ||
4472 die "unable to open file '$confsrc'\n";
4473
4474 my $outfd = new IO::File ($tmpfn, "w") ||
4475 die "unable to write config for VM $vmid\n";
4476
91bd6c90 4477 my $cookie = { netcount => 0 };
3e16d5fc 4478 while (defined (my $line = <$srcfd>)) {
be190583 4479 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
4480 }
4481
4482 $srcfd->close();
4483 $outfd->close();
4484 };
4485 my $err = $@;
4486
afdb31d5 4487 if ($err) {
3e16d5fc
DM
4488
4489 unlink $tmpfn;
4490
ed221350 4491 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 4492
3e16d5fc 4493 die $err;
afdb31d5 4494 }
3e16d5fc
DM
4495
4496 rmtree $tmpdir;
4497
4498 rename $tmpfn, $conffile ||
4499 die "unable to commit configuration file '$conffile'\n";
91bd6c90 4500
ed221350
DM
4501 PVE::Cluster::cfs_update(); # make sure we read new file
4502
91bd6c90
DM
4503 eval { rescan($vmid, 1); };
4504 warn $@ if $@;
3e16d5fc
DM
4505};
4506
0d18dcfc
DM
4507
4508# Internal snapshots
4509
4510# NOTE: Snapshot create/delete involves several non-atomic
4511# action, and can take a long time.
4512# So we try to avoid locking the file and use 'lock' variable
4513# inside the config file instead.
4514
ef59d1ca
DM
4515my $snapshot_copy_config = sub {
4516 my ($source, $dest) = @_;
4517
4518 foreach my $k (keys %$source) {
4519 next if $k eq 'snapshots';
982c7f12
DM
4520 next if $k eq 'snapstate';
4521 next if $k eq 'snaptime';
18bfb361 4522 next if $k eq 'vmstate';
ef59d1ca
DM
4523 next if $k eq 'lock';
4524 next if $k eq 'digest';
db7c26e5 4525 next if $k eq 'description';
ef59d1ca 4526 next if $k =~ m/^unused\d+$/;
be190583 4527
ef59d1ca
DM
4528 $dest->{$k} = $source->{$k};
4529 }
4530};
4531
4532my $snapshot_apply_config = sub {
4533 my ($conf, $snap) = @_;
4534
4535 # copy snapshot list
4536 my $newconf = {
4537 snapshots => $conf->{snapshots},
4538 };
4539
db7c26e5 4540 # keep description and list of unused disks
ef59d1ca 4541 foreach my $k (keys %$conf) {
db7c26e5 4542 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
ef59d1ca
DM
4543 $newconf->{$k} = $conf->{$k};
4544 }
4545
4546 &$snapshot_copy_config($snap, $newconf);
4547
4548 return $newconf;
4549};
4550
18bfb361
DM
4551sub foreach_writable_storage {
4552 my ($conf, $func) = @_;
4553
4554 my $sidhash = {};
4555
4556 foreach my $ds (keys %$conf) {
4557 next if !valid_drivename($ds);
4558
4559 my $drive = parse_drive($ds, $conf->{$ds});
4560 next if !$drive;
4561 next if drive_is_cdrom($drive);
4562
4563 my $volid = $drive->{file};
4564
4565 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 4566 $sidhash->{$sid} = $sid if $sid;
18bfb361
DM
4567 }
4568
4569 foreach my $sid (sort keys %$sidhash) {
4570 &$func($sid);
4571 }
4572}
4573
4574my $alloc_vmstate_volid = sub {
4575 my ($storecfg, $vmid, $conf, $snapname) = @_;
be190583 4576
18bfb361
DM
4577 # Note: we try to be smart when selecting a $target storage
4578
4579 my $target;
4580
4581 # search shared storage first
4582 foreach_writable_storage($conf, sub {
4583 my ($sid) = @_;
4584 my $scfg = PVE::Storage::storage_config($storecfg, $sid);
4585 return if !$scfg->{shared};
4586
4587 $target = $sid if !$target || $scfg->{path}; # prefer file based storage
4588 });
4589
4590 if (!$target) {
4591 # now search local storage
4592 foreach_writable_storage($conf, sub {
4593 my ($sid) = @_;
4594 my $scfg = PVE::Storage::storage_config($storecfg, $sid);
4595 return if $scfg->{shared};
4596
4597 $target = $sid if !$target || $scfg->{path}; # prefer file based storage;
4598 });
4599 }
4600
4601 $target = 'local' if !$target;
4602
fe6249f4
DM
4603 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4604 # we abort live save after $conf->{memory}, so we need at max twice that space
4605 my $size = $conf->{memory}*2 + $driver_state_size;
18bfb361
DM
4606
4607 my $name = "vm-$vmid-state-$snapname";
4608 my $scfg = PVE::Storage::storage_config($storecfg, $target);
4609 $name .= ".raw" if $scfg->{path}; # add filename extension for file base storage
4610 my $volid = PVE::Storage::vdisk_alloc($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4611
4612 return $volid;
4613};
4614
0d18dcfc 4615my $snapshot_prepare = sub {
18bfb361 4616 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
22c377f0
DM
4617
4618 my $snap;
0d18dcfc
DM
4619
4620 my $updatefn = sub {
4621
4622 my $conf = load_config($vmid);
4623
be190583 4624 die "you can't take a snapshot if it's a template\n"
5295b23d
DM
4625 if is_template($conf);
4626
0d18dcfc
DM
4627 check_lock($conf);
4628
22c377f0
DM
4629 $conf->{lock} = 'snapshot';
4630
be190583
DM
4631 die "snapshot name '$snapname' already used\n"
4632 if defined($conf->{snapshots}->{$snapname});
0d18dcfc 4633
ee2f90b1 4634 my $storecfg = PVE::Storage::config();
7ea975ef 4635 die "snapshot feature is not available" if !has_feature('snapshot', $conf, $storecfg);
18bfb361 4636
782f4f75 4637 $snap = $conf->{snapshots}->{$snapname} = {};
0d18dcfc 4638
18bfb361
DM
4639 if ($save_vmstate && check_running($vmid)) {
4640 $snap->{vmstate} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4641 }
4642
ef59d1ca 4643 &$snapshot_copy_config($conf, $snap);
0d18dcfc 4644
782f4f75
DM
4645 $snap->{snapstate} = "prepare";
4646 $snap->{snaptime} = time();
4647 $snap->{description} = $comment if $comment;
4648
4b15803d
DM
4649 # always overwrite machine if we save vmstate. This makes sure we
4650 # can restore it later using correct machine type
4651 $snap->{machine} = get_current_qemu_machine($vmid) if $snap->{vmstate};
4652
0d18dcfc
DM
4653 update_config_nolock($vmid, $conf, 1);
4654 };
4655
4656 lock_config($vmid, $updatefn);
22c377f0
DM
4657
4658 return $snap;
0d18dcfc
DM
4659};
4660
4661my $snapshot_commit = sub {
4662 my ($vmid, $snapname) = @_;
4663
4664 my $updatefn = sub {
4665
4666 my $conf = load_config($vmid);
4667
be190583
DM
4668 die "missing snapshot lock\n"
4669 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
0d18dcfc
DM
4670
4671 my $snap = $conf->{snapshots}->{$snapname};
4672
be190583
DM
4673 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4674
4675 die "wrong snapshot state\n"
4676 if !($snap->{snapstate} && $snap->{snapstate} eq "prepare");
0d18dcfc 4677
0d18dcfc 4678 delete $snap->{snapstate};
ee2f90b1 4679 delete $conf->{lock};
0d18dcfc 4680
ef59d1ca 4681 my $newconf = &$snapshot_apply_config($conf, $snap);
0d18dcfc 4682
05e5ad3f
DM
4683 $newconf->{parent} = $snapname;
4684
0d18dcfc
DM
4685 update_config_nolock($vmid, $newconf, 1);
4686 };
4687
4688 lock_config($vmid, $updatefn);
4689};
4690
22c377f0
DM
4691sub snapshot_rollback {
4692 my ($vmid, $snapname) = @_;
4693
4694 my $snap;
4695
4696 my $prepare = 1;
4697
a3222b91 4698 my $storecfg = PVE::Storage::config();
be190583 4699
22c377f0
DM
4700 my $updatefn = sub {
4701
4702 my $conf = load_config($vmid);
4703
8b43bc11 4704 die "you can't rollback if vm is a template\n" if is_template($conf);
90b0c6b3 4705
ab33a7c2
DM
4706 $snap = $conf->{snapshots}->{$snapname};
4707
be190583 4708 die "snapshot '$snapname' does not exist\n" if !defined($snap);
ab33a7c2 4709
be190583 4710 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
ab33a7c2
DM
4711 if $snap->{snapstate};
4712
a3222b91
DM
4713 if ($prepare) {
4714 check_lock($conf);
4715 vm_stop($storecfg, $vmid, undef, undef, 5, undef, undef);
4716 }
22c377f0
DM
4717
4718 die "unable to rollback vm $vmid: vm is running\n"
4719 if check_running($vmid);
4720
4721 if ($prepare) {
4722 $conf->{lock} = 'rollback';
4723 } else {
4724 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4725 delete $conf->{lock};
4726 }
4727
4b15803d
DM
4728 my $forcemachine;
4729
22c377f0 4730 if (!$prepare) {
4b15803d
DM
4731 my $has_machine_config = defined($conf->{machine});
4732
22c377f0 4733 # copy snapshot config to current config
ef59d1ca
DM
4734 $conf = &$snapshot_apply_config($conf, $snap);
4735 $conf->{parent} = $snapname;
4b15803d 4736
d8b916fd
DM
4737 # Note: old code did not store 'machine', so we try to be smart
4738 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
4739 $forcemachine = $conf->{machine} || 'pc-i440fx-1.4';
be190583 4740 # we remove the 'machine' configuration if not explicitly specified
4b15803d
DM
4741 # in the original config.
4742 delete $conf->{machine} if $snap->{vmstate} && !$has_machine_config;
22c377f0
DM
4743 }
4744
4745 update_config_nolock($vmid, $conf, 1);
a3222b91
DM
4746
4747 if (!$prepare && $snap->{vmstate}) {
4748 my $statefile = PVE::Storage::path($storecfg, $snap->{vmstate});
4b15803d 4749 vm_start($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
a3222b91 4750 }
22c377f0
DM
4751 };
4752
4753 lock_config($vmid, $updatefn);
be190583 4754
22c377f0
DM
4755 foreach_drive($snap, sub {
4756 my ($ds, $drive) = @_;
4757
4758 return if drive_is_cdrom($drive);
4759
4760 my $volid = $drive->{file};
4761 my $device = "drive-$ds";
4762
79e57b29 4763 PVE::Storage::volume_snapshot_rollback($storecfg, $volid, $snapname);
22c377f0
DM
4764 });
4765
4766 $prepare = 0;
4767 lock_config($vmid, $updatefn);
4768}
4769
9dcf4909
DM
4770my $savevm_wait = sub {
4771 my ($vmid) = @_;
4772
4773 for(;;) {
ed221350 4774 my $stat = vm_mon_cmd_nocheck($vmid, "query-savevm");
9dcf4909
DM
4775 if (!$stat->{status}) {
4776 die "savevm not active\n";
4777 } elsif ($stat->{status} eq 'active') {
4778 sleep(1);
4779 next;
4780 } elsif ($stat->{status} eq 'completed') {
4781 last;
4782 } else {
4783 die "query-savevm returned status '$stat->{status}'\n";
4784 }
4785 }
4786};
4787
0d18dcfc 4788sub snapshot_create {
18bfb361 4789 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
0d18dcfc 4790
18bfb361 4791 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
0d18dcfc 4792
18bfb361 4793 $freezefs = $save_vmstate = 0 if !$snap->{vmstate}; # vm is not running
030dd626 4794
3ee28e38
DM
4795 my $drivehash = {};
4796
18bfb361
DM
4797 my $running = check_running($vmid);
4798
0d18dcfc
DM
4799 eval {
4800 # create internal snapshots of all drives
22c377f0
DM
4801
4802 my $storecfg = PVE::Storage::config();
a3222b91
DM
4803
4804 if ($running) {
4805 if ($snap->{vmstate}) {
be190583 4806 my $path = PVE::Storage::path($storecfg, $snap->{vmstate});
9dcf4909
DM
4807 vm_mon_cmd($vmid, "savevm-start", statefile => $path);
4808 &$savevm_wait($vmid);
a3222b91 4809 } else {
9dcf4909 4810 vm_mon_cmd($vmid, "savevm-start");
a3222b91
DM
4811 }
4812 };
4813
4814 qga_freezefs($vmid) if $running && $freezefs;
be190583 4815
22c377f0
DM
4816 foreach_drive($snap, sub {
4817 my ($ds, $drive) = @_;
4818
4819 return if drive_is_cdrom($drive);
0d18dcfc 4820
22c377f0
DM
4821 my $volid = $drive->{file};
4822 my $device = "drive-$ds";
4823
4824 qemu_volume_snapshot($vmid, $device, $storecfg, $volid, $snapname);
3ee28e38 4825 $drivehash->{$ds} = 1;
22c377f0 4826 });
0d18dcfc 4827 };
22c377f0
DM
4828 my $err = $@;
4829
1a71fa73 4830 eval { qga_unfreezefs($vmid) if $running && $freezefs; };
22c377f0
DM
4831 warn $@ if $@;
4832
9dcf4909 4833 eval { vm_mon_cmd($vmid, "savevm-end") if $running; };
22c377f0
DM
4834 warn $@ if $@;
4835
4836 if ($err) {
0d18dcfc 4837 warn "snapshot create failed: starting cleanup\n";
3ee28e38 4838 eval { snapshot_delete($vmid, $snapname, 0, $drivehash); };
0d18dcfc
DM
4839 warn $@ if $@;
4840 die $err;
4841 }
4842
4843 &$snapshot_commit($vmid, $snapname);
4844}
4845
3ee28e38 4846# Note: $drivehash is only set when called from snapshot_create.
0d18dcfc 4847sub snapshot_delete {
3ee28e38 4848 my ($vmid, $snapname, $force, $drivehash) = @_;
0d18dcfc
DM
4849
4850 my $prepare = 1;
4851
22c377f0 4852 my $snap;
ee2f90b1 4853 my $unused = [];
0d18dcfc 4854
6cb1a8cf
DM
4855 my $unlink_parent = sub {
4856 my ($confref, $new_parent) = @_;
4857
4858 if ($confref->{parent} && $confref->{parent} eq $snapname) {
4859 if ($new_parent) {
4860 $confref->{parent} = $new_parent;
4861 } else {
4862 delete $confref->{parent};
4863 }
4864 }
4865 };
be190583 4866
0d18dcfc 4867 my $updatefn = sub {
2009f324 4868 my ($remove_drive) = @_;
0d18dcfc 4869
22c377f0 4870 my $conf = load_config($vmid);
0d18dcfc 4871
5295b23d
DM
4872 if (!$drivehash) {
4873 check_lock($conf);
be190583 4874 die "you can't delete a snapshot if vm is a template\n"
5295b23d
DM
4875 if is_template($conf);
4876 }
0d18dcfc 4877
22c377f0 4878 $snap = $conf->{snapshots}->{$snapname};
0d18dcfc 4879
be190583 4880 die "snapshot '$snapname' does not exist\n" if !defined($snap);
0d18dcfc
DM
4881
4882 # remove parent refs
6cb1a8cf 4883 &$unlink_parent($conf, $snap->{parent});
0d18dcfc
DM
4884 foreach my $sn (keys %{$conf->{snapshots}}) {
4885 next if $sn eq $snapname;
6cb1a8cf 4886 &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent});
0d18dcfc
DM
4887 }
4888
2009f324 4889 if ($remove_drive) {
18bfb361
DM
4890 if ($remove_drive eq 'vmstate') {
4891 delete $snap->{$remove_drive};
4892 } else {
4893 my $drive = parse_drive($remove_drive, $snap->{$remove_drive});
4894 my $volid = $drive->{file};
4895 delete $snap->{$remove_drive};
4896 add_unused_volume($conf, $volid);
4897 }
2009f324
DM
4898 }
4899
0d18dcfc
DM
4900 if ($prepare) {
4901 $snap->{snapstate} = 'delete';
4902 } else {
4903 delete $conf->{snapshots}->{$snapname};
3ee28e38 4904 delete $conf->{lock} if $drivehash;
ee2f90b1
DM
4905 foreach my $volid (@$unused) {
4906 add_unused_volume($conf, $volid);
4907 }
0d18dcfc
DM
4908 }
4909
4910 update_config_nolock($vmid, $conf, 1);
4911 };
4912
4913 lock_config($vmid, $updatefn);
4914
18bfb361 4915 # now remove vmstate file
0d18dcfc 4916
22c377f0
DM
4917 my $storecfg = PVE::Storage::config();
4918
18bfb361
DM
4919 if ($snap->{vmstate}) {
4920 eval { PVE::Storage::vdisk_free($storecfg, $snap->{vmstate}); };
4921 if (my $err = $@) {
4922 die $err if !$force;
4923 warn $err;
4924 }
4925 # save changes (remove vmstate from snapshot)
4926 lock_config($vmid, $updatefn, 'vmstate') if !$force;
4927 };
4928
4929 # now remove all internal snapshots
4930 foreach_drive($snap, sub {
22c377f0
DM
4931 my ($ds, $drive) = @_;
4932
4933 return if drive_is_cdrom($drive);
3ee28e38 4934
22c377f0
DM
4935 my $volid = $drive->{file};
4936 my $device = "drive-$ds";
4937
2009f324
DM
4938 if (!$drivehash || $drivehash->{$ds}) {
4939 eval { qemu_volume_snapshot_delete($vmid, $device, $storecfg, $volid, $snapname); };
4940 if (my $err = $@) {
4941 die $err if !$force;
4942 warn $err;
4943 }
3ee28e38 4944 }
2009f324
DM
4945
4946 # save changes (remove drive fron snapshot)
4947 lock_config($vmid, $updatefn, $ds) if !$force;
ee2f90b1 4948 push @$unused, $volid;
22c377f0 4949 });
0d18dcfc
DM
4950
4951 # now cleanup config
4952 $prepare = 0;
4953 lock_config($vmid, $updatefn);
4954}
4955
9cd07842 4956sub has_feature {
7ea975ef
AD
4957 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4958
719893a9 4959 my $err;
7ea975ef
AD
4960 foreach_drive($conf, sub {
4961 my ($ds, $drive) = @_;
4962
4963 return if drive_is_cdrom($drive);
4964 my $volid = $drive->{file};
4965 $err = 1 if !PVE::Storage::volume_has_feature($storecfg, $feature, $volid, $snapname, $running);
4966 });
4967
719893a9 4968 return $err ? 0 : 1;
7ea975ef 4969}
04a69bb4
AD
4970
4971sub template_create {
4972 my ($vmid, $conf, $disk) = @_;
4973
04a69bb4 4974 my $storecfg = PVE::Storage::config();
04a69bb4 4975
9cd07842
DM
4976 foreach_drive($conf, sub {
4977 my ($ds, $drive) = @_;
4978
4979 return if drive_is_cdrom($drive);
4980 return if $disk && $ds ne $disk;
4981
4982 my $volid = $drive->{file};
bbd56097 4983 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 4984
04a69bb4
AD
4985 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
4986 $drive->{file} = $voliddst;
152fe752
DM
4987 $conf->{$ds} = print_drive($vmid, $drive);
4988 update_config_nolock($vmid, $conf, 1);
04a69bb4 4989 });
04a69bb4
AD
4990}
4991
624361b3
AD
4992sub is_template {
4993 my ($conf) = @_;
4994
96d695c0 4995 return 1 if defined $conf->{template} && $conf->{template} == 1;
624361b3
AD
4996}
4997
5133de42
AD
4998sub qemu_img_convert {
4999 my ($src_volid, $dst_volid, $size, $snapname) = @_;
5000
5001 my $storecfg = PVE::Storage::config();
5002 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
5003 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
5004
5005 if ($src_storeid && $dst_storeid) {
5006 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
5007 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
5008
5009 my $src_format = qemu_img_format($src_scfg, $src_volname);
5010 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
5011
5012 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
5013 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
5014
5015 my $cmd = [];
71ddbff9 5016 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5133de42
AD
5017 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5018 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
5019
5020 my $parser = sub {
5021 my $line = shift;
5022 if($line =~ m/\((\S+)\/100\%\)/){
5023 my $percent = $1;
5024 my $transferred = int($size * $percent / 100);
5025 my $remaining = $size - $transferred;
5026
5027 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5028 }
5029
5030 };
5031
5032 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
5033 my $err = $@;
5034 die "copy failed: $err" if $err;
5035 }
5036}
5037
5038sub qemu_img_format {
5039 my ($scfg, $volname) = @_;
5040
ccb5c001 5041 if ($scfg->{path} && $volname =~ m/\.(raw|qcow2|qed|vmdk)$/) {
5133de42 5042 return $1;
ccb5c001 5043 } elsif ($scfg->{type} eq 'iscsi') {
5133de42 5044 return "host_device";
be190583 5045 } else {
5133de42 5046 return "raw";
5133de42
AD
5047 }
5048}
5049
cfad42af
AD
5050sub qemu_drive_mirror {
5051 my ($vmid, $drive, $dst_volid, $vmiddst, $maxwait) = @_;
5052
5053 my $count = 1;
5054 my $old_len = 0;
5055 my $frozen = undef;
5056
5057 my $storecfg = PVE::Storage::config();
5058 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
5059
5060 if ($dst_storeid) {
5061 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
5062
152fe752 5063 my $format;
cfad42af
AD
5064 if ($dst_volname =~ m/\.(raw|qcow2)$/){
5065 $format = $1;
5066 }
5067
5068 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
5069
152fe752 5070 if ($format) {
be190583 5071 #fixme : sometime drive-mirror timeout, but works fine after.
152fe752 5072 # (I have see the problem with big volume > 200GB), so we need to eval
be190583 5073 eval { vm_mon_cmd($vmid, "drive-mirror", timeout => 10, device => "drive-$drive", mode => "existing",
152fe752
DM
5074 sync => "full", target => $dst_path, format => $format); };
5075 } else {
be190583 5076 eval { vm_mon_cmd($vmid, "drive-mirror", timeout => 10, device => "drive-$drive", mode => "existing",
152fe752 5077 sync => "full", target => $dst_path); };
cfad42af 5078 }
152fe752
DM
5079
5080 eval {
cfad42af 5081 while (1) {
152fe752 5082 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
cfad42af 5083 my $stat = @$stats[0];
f6ab3bdb
AD
5084 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5085 die "error job is not mirroring" if $stat->{type} ne "mirror";
5086
cfad42af
AD
5087 my $transferred = $stat->{offset};
5088 my $total = $stat->{len};
5089 my $remaining = $total - $transferred;
5090 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
cfad42af
AD
5091
5092 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent %\n";
5093
5094 last if ($stat->{len} == $stat->{offset});
5095 if ($old_len == $stat->{offset}) {
5096 if ($maxwait && $count > $maxwait) {
5097 # if writes to disk occurs the disk needs to be freezed
5098 # to be able to complete the migration
5099 vm_suspend($vmid,1);
5100 $count = 0;
5101 $frozen = 1;
152fe752 5102 } else {
cfad42af
AD
5103 $count++ unless $frozen;
5104 }
152fe752
DM
5105 } elsif ($frozen) {
5106 vm_resume($vmid,1);
5107 $count = 0;
cfad42af
AD
5108 }
5109 $old_len = $stat->{offset};
5110 sleep 1;
5111 }
be190583 5112
2fc6bc17 5113 if ($vmiddst == $vmid) {
be190583 5114 # switch the disk if source and destination are on the same guest
2fc6bc17
DM
5115 vm_mon_cmd($vmid, "block-job-complete", device => "drive-$drive");
5116 }
cfad42af 5117 };
4fca0153 5118 if (my $err = $@) {
152fe752 5119 eval { vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive"); };
4fca0153 5120 die "mirroring error: $err";
cfad42af
AD
5121 }
5122
2fc6bc17
DM
5123 if ($vmiddst != $vmid) {
5124 # if we clone a disk for a new target vm, we don't switch the disk
152fe752 5125 vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive");
cfad42af
AD
5126 }
5127 }
5128}
5129
152fe752 5130sub clone_disk {
be190583 5131 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
152fe752
DM
5132 $newvmid, $storage, $format, $full, $newvollist) = @_;
5133
5134 my $newvolid;
5135
5136 if (!$full) {
5137 print "create linked clone of drive $drivename ($drive->{file})\n";
5138 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid);
5139 push @$newvollist, $newvolid;
5140 } else {
5141 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
5142 $storeid = $storage if $storage;
5143
1377d7b0
DM
5144 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
5145 if (!$format) {
5146 $format = $drive->{format} || $defFormat;
152fe752
DM
5147 }
5148
1377d7b0
DM
5149 # test if requested format is supported - else use default
5150 my $supported = grep { $_ eq $format } @$validFormats;
5151 $format = $defFormat if !$supported;
5152
152fe752
DM
5153 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
5154
5155 print "create full clone of drive $drivename ($drive->{file})\n";
5156 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5157 push @$newvollist, $newvolid;
5158
5159 if (!$running || $snapname) {
5160 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname);
5161 } else {
5162 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid);
be190583 5163 }
152fe752
DM
5164 }
5165
5166 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
5167
5168 my $disk = $drive;
5169 $disk->{format} = undef;
5170 $disk->{file} = $newvolid;
5171 $disk->{size} = $size;
5172
5173 return $disk;
5174}
5175
ff556cf2
DM
5176# this only works if VM is running
5177sub get_current_qemu_machine {
5178 my ($vmid) = @_;
5179
5180 my $cmd = { execute => 'query-machines', arguments => {} };
be190583 5181 my $res = PVE::QemuServer::vm_qmp_command($vmid, $cmd);
ff556cf2
DM
5182
5183 my ($current, $default);
5184 foreach my $e (@$res) {
5185 $default = $e->{name} if $e->{'is-default'};
5186 $current = $e->{name} if $e->{'is-current'};
5187 }
5188
5189 # fallback to the default machine if current is not supported by qemu
5190 return $current || $default || 'pc';
5191}
5192
4543ecf0
AD
5193sub lspci {
5194
5195 my $devices = {};
5196
5197 dir_glob_foreach("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5198 my (undef, $id, $function) = @_;
5199 my $res = { id => $id, function => $function};
5200 push @{$devices->{$id}}, $res;
5201 });
5202
5203 return $devices;
5204}
5205
1e3baf05 52061;