]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
add warning for iothread with invalid scsi controller
[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;
ffda963f 30use PVE::QemuConfig;
26f11676 31use PVE::QMPClient;
91bd6c90 32use PVE::RPCEnvironment;
6b64503e 33use Time::HiRes qw(gettimeofday);
a783c78e 34use File::Copy qw(copy);
46630a5f 35use URI::Escape;
1e3baf05 36
e5eaa028
WL
37my $qemu_snap_storage = {rbd => 1, sheepdog => 1};
38
7f0b5beb 39my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 40
19672434 41# Note about locking: we use flock on the config file protect
1e3baf05
DM
42# against concurent actions.
43# Aditionaly, we have a 'lock' setting in the config file. This
22c377f0 44# can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
1e3baf05
DM
45# allowed when such lock is set. But you can ignore this kind of
46# lock with the --skiplock flag.
47
97d62eb7 48cfs_register_file('/qemu-server/',
1858638f
DM
49 \&parse_vm_config,
50 \&write_vm_config);
1e3baf05 51
3ea94c60
DM
52PVE::JSONSchema::register_standard_option('skiplock', {
53 description => "Ignore locks - only root is allowed to use this option.",
afdb31d5 54 type => 'boolean',
3ea94c60
DM
55 optional => 1,
56});
57
58PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
59 description => "Some command save/restore state from this location.",
60 type => 'string',
61 maxLength => 128,
62 optional => 1,
63});
64
8abd398b
DM
65PVE::JSONSchema::register_standard_option('pve-snapshot-name', {
66 description => "The name of the snapshot.",
67 type => 'string', format => 'pve-configid',
68 maxLength => 40,
69});
70
1e3baf05
DM
71#no warnings 'redefine';
72
c8effec3
AD
73sub cgroups_write {
74 my ($controller, $vmid, $option, $value) = @_;
75
3a515a88
DM
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE::ProcFSTools::write_proc_entry($path, $value);
c8effec3
AD
78
79}
80
1e3baf05
DM
81my $nodename = PVE::INotify::nodename();
82
83mkdir "/etc/pve/nodes/$nodename";
84my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
85mkdir $confdir;
86
87my $var_run_tmpdir = "/var/run/qemu-server";
88mkdir $var_run_tmpdir;
89
90my $lock_dir = "/var/lock/qemu-server";
91mkdir $lock_dir;
92
93my $pcisysfs = "/sys/bus/pci";
94
8930da74
DM
95my $cpu_vendor_list = {
96 # Intel CPUs
97 486 => 'GenuineIntel',
98 pentium => 'GenuineIntel',
99 pentium2 => 'GenuineIntel',
100 pentium3 => 'GenuineIntel',
101 coreduo => 'GenuineIntel',
102 core2duo => 'GenuineIntel',
103 Conroe => 'GenuineIntel',
104 Penryn => 'GenuineIntel',
105 Nehalem => 'GenuineIntel',
106 Westmere => 'GenuineIntel',
107 SandyBridge => 'GenuineIntel',
108 IvyBridge => 'GenuineIntel',
109 Haswell => 'GenuineIntel',
110 'Haswell-noTSX' => 'GenuineIntel',
111 Broadwell => 'GenuineIntel',
112 'Broadwell-noTSX' => 'GenuineIntel',
113
114 # AMD CPUs
115 athlon => 'AuthenticAMD',
116 phenom => 'AuthenticAMD',
117 Opteron_G1 => 'AuthenticAMD',
118 Opteron_G2 => 'AuthenticAMD',
119 Opteron_G3 => 'AuthenticAMD',
120 Opteron_G4 => 'AuthenticAMD',
121 Opteron_G5 => 'AuthenticAMD',
122
123 # generic types, use vendor from host node
124 host => 'default',
125 kvm32 => 'default',
126 kvm64 => 'default',
127 qemu32 => 'default',
128 qemu64 => 'default',
129};
130
ff6ffe20 131my $cpu_fmt = {
16a91d65
WB
132 cputype => {
133 description => "Emulated CPU type.",
134 type => 'string',
8930da74 135 enum => [ sort keys %$cpu_vendor_list ],
bb9207e0 136 format_description => 'cputype',
16a91d65
WB
137 default => 'kvm64',
138 default_key => 1,
139 },
140 hidden => {
141 description => "Do not identify as a KVM virtual machine.",
142 type => 'boolean',
143 optional => 1,
144 default => 0
145 },
146};
147
ec3582b5
WB
148my $watchdog_fmt = {
149 model => {
150 default_key => 1,
151 type => 'string',
152 enum => [qw(i6300esb ib700)],
153 description => "Watchdog type to emulate.",
154 default => 'i6300esb',
155 optional => 1,
156 },
157 action => {
158 type => 'string',
159 enum => [qw(reset shutdown poweroff pause debug none)],
160 description => "The action to perform if after activation the guest fails to poll the watchdog in time.",
161 optional => 1,
162 },
163};
164PVE::JSONSchema::register_format('pve-qm-watchdog', $watchdog_fmt);
165
1e3baf05
DM
166my $confdesc = {
167 onboot => {
168 optional => 1,
169 type => 'boolean',
170 description => "Specifies whether a VM will be started during system bootup.",
171 default => 0,
172 },
173 autostart => {
174 optional => 1,
175 type => 'boolean',
176 description => "Automatic restart after crash (currently ignored).",
177 default => 0,
178 },
2ff09f52
DA
179 hotplug => {
180 optional => 1,
b3c2bdd1
DM
181 type => 'string', format => 'pve-hotplug-features',
182 description => "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
183 default => 'network,disk,usb',
2ff09f52 184 },
1e3baf05
DM
185 reboot => {
186 optional => 1,
187 type => 'boolean',
188 description => "Allow reboot. If set to '0' the VM exit on reboot.",
189 default => 1,
190 },
191 lock => {
192 optional => 1,
193 type => 'string',
194 description => "Lock/unlock the VM.",
22c377f0 195 enum => [qw(migrate backup snapshot rollback)],
1e3baf05
DM
196 },
197 cpulimit => {
198 optional => 1,
c6f773b8 199 type => 'number',
8a61e0fd 200 description => "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
1e3baf05 201 minimum => 0,
c6f773b8 202 maximum => 128,
1e3baf05
DM
203 default => 0,
204 },
205 cpuunits => {
206 optional => 1,
207 type => 'integer',
208 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.",
209 minimum => 0,
210 maximum => 500000,
211 default => 1000,
212 },
213 memory => {
214 optional => 1,
215 type => 'integer',
7878afeb 216 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
217 minimum => 16,
218 default => 512,
219 },
13a48620
DA
220 balloon => {
221 optional => 1,
222 type => 'integer',
8b1accf7
DM
223 description => "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
224 minimum => 0,
225 },
226 shares => {
227 optional => 1,
228 type => 'integer',
229 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",
230 minimum => 0,
231 maximum => 50000,
232 default => 1000,
13a48620 233 },
1e3baf05
DM
234 keyboard => {
235 optional => 1,
236 type => 'string',
237 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
e95fe75f 238 enum => PVE::Tools::kvmkeymaplist(),
1e3baf05
DM
239 default => 'en-us',
240 },
241 name => {
242 optional => 1,
7fabe17d 243 type => 'string', format => 'dns-name',
1e3baf05
DM
244 description => "Set a name for the VM. Only used on the configuration web interface.",
245 },
cdd20088
AD
246 scsihw => {
247 optional => 1,
248 type => 'string',
249 description => "scsi controller model",
6731a4cf 250 enum => [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
cdd20088
AD
251 default => 'lsi',
252 },
1e3baf05
DM
253 description => {
254 optional => 1,
255 type => 'string',
0581fe4f 256 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
1e3baf05
DM
257 },
258 ostype => {
259 optional => 1,
260 type => 'string',
6b9d84cf 261 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
1e3baf05
DM
262 description => <<EODESC,
263Used to enable special optimization/features for specific
264operating systems:
265
266other => unspecified OS
267wxp => Microsoft Windows XP
268w2k => Microsoft Windows 2000
269w2k3 => Microsoft Windows 2003
270w2k8 => Microsoft Windows 2008
271wvista => Microsoft Windows Vista
272win7 => Microsoft Windows 7
a70ebde3 273win8 => Microsoft Windows 8/2012
1e3baf05
DM
274l24 => Linux 2.4 Kernel
275l26 => Linux 2.6/3.X Kernel
6b9d84cf 276solaris => solaris/opensolaris/openindiania kernel
1e3baf05 277
6b9d84cf 278other|l24|l26|solaris ... no special behaviour
a70ebde3 279wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
1e3baf05
DM
280EODESC
281 },
282 boot => {
283 optional => 1,
284 type => 'string',
285 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
286 pattern => '[acdn]{1,4}',
32baffb4 287 default => 'cdn',
1e3baf05
DM
288 },
289 bootdisk => {
290 optional => 1,
291 type => 'string', format => 'pve-qm-bootdisk',
292 description => "Enable booting from specified disk.",
03e480fc 293 pattern => '(ide|sata|scsi|virtio)\d+',
1e3baf05
DM
294 },
295 smp => {
296 optional => 1,
297 type => 'integer',
298 description => "The number of CPUs. Please use option -sockets instead.",
299 minimum => 1,
300 default => 1,
301 },
302 sockets => {
303 optional => 1,
304 type => 'integer',
305 description => "The number of CPU sockets.",
306 minimum => 1,
307 default => 1,
308 },
309 cores => {
310 optional => 1,
311 type => 'integer',
312 description => "The number of cores per socket.",
313 minimum => 1,
314 default => 1,
315 },
8a010eae
AD
316 numa => {
317 optional => 1,
318 type => 'boolean',
1917695c 319 description => "Enable/disable NUMA.",
8a010eae
AD
320 default => 0,
321 },
de9d1e55 322 vcpus => {
3bd18e48
AD
323 optional => 1,
324 type => 'integer',
de9d1e55 325 description => "Number of hotplugged vcpus.",
3bd18e48 326 minimum => 1,
de9d1e55 327 default => 0,
3bd18e48 328 },
1e3baf05
DM
329 acpi => {
330 optional => 1,
331 type => 'boolean',
332 description => "Enable/disable ACPI.",
333 default => 1,
334 },
bc84dcca 335 agent => {
ab6a046f
AD
336 optional => 1,
337 type => 'boolean',
338 description => "Enable/disable Qemu GuestAgent.",
be79c214 339 default => 0,
ab6a046f 340 },
1e3baf05
DM
341 kvm => {
342 optional => 1,
343 type => 'boolean',
344 description => "Enable/disable KVM hardware virtualization.",
345 default => 1,
346 },
347 tdf => {
348 optional => 1,
349 type => 'boolean',
8c559505
DM
350 description => "Enable/disable time drift fix.",
351 default => 0,
1e3baf05 352 },
19672434 353 localtime => {
1e3baf05
DM
354 optional => 1,
355 type => 'boolean',
356 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
357 },
358 freeze => {
359 optional => 1,
360 type => 'boolean',
361 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
362 },
363 vga => {
364 optional => 1,
365 type => 'string',
1917695c
TL
366 description => "Select the VGA type. If you want to use high resolution" .
367 " modes (>= 1280x1024x16) then you should use the options " .
368 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
369 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
370 "display sever. For win* OS you can select how many independent " .
371 "displays you want, Linux guests can add displays them self. " .
372 "You can also run without any graphic card, using a serial device" .
373 " as terminal.",
2fa3151e 374 enum => [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
1e3baf05 375 },
0ea9541d
DM
376 watchdog => {
377 optional => 1,
378 type => 'string', format => 'pve-qm-watchdog',
1917695c
TL
379 description => "Create a virtual hardware watchdog device. Once enabled" .
380 " (by a guest action), the watchdog must be periodically polled " .
381 "by an agent inside the guest or else the watchdog will reset " .
382 "the guest (or execute the respective action specified)",
0ea9541d 383 },
1e3baf05
DM
384 startdate => {
385 optional => 1,
19672434 386 type => 'string',
1e3baf05
DM
387 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
388 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'.",
389 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
390 default => 'now',
391 },
43574f73 392 startup => get_standard_option('pve-startup-order'),
68eda3ab
AD
393 template => {
394 optional => 1,
395 type => 'boolean',
396 description => "Enable/disable Template.",
397 default => 0,
398 },
1e3baf05
DM
399 args => {
400 optional => 1,
401 type => 'string',
402 description => <<EODESCR,
c7a8aad6 403Arbitrary arguments passed to kvm, for example:
1e3baf05
DM
404
405args: -no-reboot -no-hpet
c7a8aad6
FG
406
407NOTE: this option is for experts only.
1e3baf05
DM
408EODESCR
409 },
410 tablet => {
411 optional => 1,
412 type => 'boolean',
413 default => 1,
1917695c
TL
414 description => "Enable/disable the USB tablet device. This device is " .
415 "usually needed to allow absolute mouse positioning with VNC. " .
416 "Else the mouse runs out of sync with normal VNC clients. " .
417 "If you're running lots of console-only guests on one host, " .
418 "you may consider disabling this to save some context switches. " .
419 "This is turned off by default if you use spice (-vga=qxl).",
1e3baf05
DM
420 },
421 migrate_speed => {
422 optional => 1,
423 type => 'integer',
424 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
425 minimum => 0,
426 default => 0,
427 },
428 migrate_downtime => {
429 optional => 1,
04432191 430 type => 'number',
1e3baf05
DM
431 description => "Set maximum tolerated downtime (in seconds) for migrations.",
432 minimum => 0,
04432191 433 default => 0.1,
1e3baf05
DM
434 },
435 cdrom => {
436 optional => 1,
437 type => 'string', format => 'pve-qm-drive',
438 typetext => 'volume',
439 description => "This is an alias for option -ide2",
440 },
441 cpu => {
442 optional => 1,
443 description => "Emulated CPU type.",
444 type => 'string',
ff6ffe20 445 format => $cpu_fmt,
1e3baf05 446 },
b7ba6b79
DM
447 parent => get_standard_option('pve-snapshot-name', {
448 optional => 1,
449 description => "Parent snapshot name. This is used internally, and should not be modified.",
450 }),
982c7f12
DM
451 snaptime => {
452 optional => 1,
453 description => "Timestamp for snapshots.",
454 type => 'integer',
455 minimum => 0,
456 },
18bfb361
DM
457 vmstate => {
458 optional => 1,
459 type => 'string', format => 'pve-volume-id',
460 description => "Reference to a volume which stores the VM state. This is used internally for snapshots.",
461 },
3bafc510
DM
462 machine => {
463 description => "Specific the Qemu machine type.",
464 type => 'string',
7bac824e 465 pattern => '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
3bafc510
DM
466 maxLength => 40,
467 optional => 1,
468 },
2796e7d5
DM
469 smbios1 => {
470 description => "Specify SMBIOS type 1 fields.",
471 type => 'string', format => 'pve-qm-smbios1',
2796e7d5
DM
472 maxLength => 256,
473 optional => 1,
474 },
cb0e4540
AG
475 protection => {
476 optional => 1,
477 type => 'boolean',
478 description => "Sets the protection flag of the VM. This will prevent the remove operation.",
479 default => 0,
480 },
3edb45e7 481 bios => {
a783c78e 482 optional => 1,
3edb45e7
DM
483 type => 'string',
484 enum => [ qw(seabios ovmf) ],
485 description => "Select BIOS implementation.",
486 default => 'seabios',
a783c78e 487 },
1e3baf05
DM
488};
489
490# what about other qemu settings ?
491#cpu => 'string',
492#machine => 'string',
493#fda => 'file',
494#fdb => 'file',
495#mtdblock => 'file',
496#sd => 'file',
497#pflash => 'file',
498#snapshot => 'bool',
499#bootp => 'file',
500##tftp => 'dir',
501##smb => 'dir',
502#kernel => 'file',
503#append => 'string',
504#initrd => 'file',
505##soundhw => 'string',
506
507while (my ($k, $v) = each %$confdesc) {
508 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
509}
510
511my $MAX_IDE_DISKS = 4;
f62db2a4 512my $MAX_SCSI_DISKS = 14;
a2650619 513my $MAX_VIRTIO_DISKS = 16;
cdb0931f 514my $MAX_SATA_DISKS = 6;
1e3baf05 515my $MAX_USB_DEVICES = 5;
5bdcf937 516my $MAX_NETS = 32;
1e3baf05 517my $MAX_UNUSED_DISKS = 8;
5cffb2d2 518my $MAX_HOSTPCI_DEVICES = 4;
bae179aa 519my $MAX_SERIAL_PORTS = 4;
1989a89c 520my $MAX_PARALLEL_PORTS = 3;
2ed5d572 521my $MAX_NUMA = 8;
4d3f29ed
AD
522my $MAX_MEM = 4194304;
523my $STATICMEM = 1024;
2ed5d572 524
ffc0d8c7
WB
525my $numa_fmt = {
526 cpus => {
527 type => "string",
528 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
529 description => "CPUs accessing this numa node.",
530 format_description => "id[-id];...",
531 },
532 memory => {
533 type => "number",
534 description => "Amount of memory this numa node provides.",
535 format_description => "mb",
536 optional => 1,
537 },
538 hostnodes => {
539 type => "string",
540 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
541 description => "host numa nodes to use",
542 format_description => "id[-id];...",
543 optional => 1,
544 },
545 policy => {
546 type => 'string',
547 enum => [qw(preferred bind interleave)],
548 format_description => 'preferred|bind|interleave',
549 description => "numa allocation policy.",
550 optional => 1,
551 },
552};
553PVE::JSONSchema::register_format('pve-qm-numanode', $numa_fmt);
2ed5d572
AD
554my $numadesc = {
555 optional => 1,
ffc0d8c7 556 type => 'string', format => $numa_fmt,
2ed5d572
AD
557 description => "numa topology",
558};
559PVE::JSONSchema::register_standard_option("pve-qm-numanode", $numadesc);
560
561for (my $i = 0; $i < $MAX_NUMA; $i++) {
562 $confdesc->{"numa$i"} = $numadesc;
563}
1e3baf05
DM
564
565my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
55034103
KT
566 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
567 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
6b64503e 568my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05 569
cd9c34d1
WB
570my $net_fmt = {
571 macaddr => {
572 type => 'string',
573 pattern => qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
574 description => "MAC address",
575 format_description => "XX:XX:XX:XX:XX:XX",
576 optional => 1,
577 },
578 model => { alias => 'macaddr', default_key => 1 },
579 (map { $_ => { group => 'model' } } @$nic_model_list),
580 bridge => {
581 type => 'string',
582 description => 'Bridge to attach the network device to.',
583 format_description => 'bridge',
584 optional => 1,
585 },
586 queues => {
587 type => 'integer',
588 minimum => 0, maximum => 16,
589 description => 'Number of packet queues to be used on the device.',
590 format_description => 'number',
591 optional => 1,
592 },
593 rate => {
594 type => 'number',
595 minimum => 0,
596 description => 'Rate limit in mbps as floating point number.',
597 format_description => 'mbps',
598 optional => 1,
599 },
600 tag => {
601 type => 'integer',
602 minimum => 2, maximum => 4094,
603 description => 'VLAN tag to apply to packets on this interface.',
604 format_description => 'vlanid',
605 optional => 1,
606 },
607 trunks => {
608 type => 'string',
609 pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
610 description => 'VLAN trunks to pass through this interface.',
611 format_description => 'id;id...',
612 optional => 1,
613 },
614 firewall => {
615 type => 'boolean',
616 description => 'Whether this interface should be protected by the firewall.',
617 format_description => '0|1',
618 optional => 1,
619 },
620 link_down => {
621 type => 'boolean',
622 description => 'Whether this interface should be DISconnected (like pulling the plug).',
623 format_description => '0|1',
624 optional => 1,
625 },
626};
1e3baf05
DM
627my $netdesc = {
628 optional => 1,
629 type => 'string', format => 'pve-qm-net',
1e3baf05 630 description => <<EODESCR,
19672434 631Specify network devices.
1e3baf05
DM
632
633MODEL is one of: $nic_model_list_txt
634
19672434 635XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
1e3baf05
DM
636automatically generated if not specified.
637
638The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
639
640Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
641
642If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
643
64410.0.2.2 Gateway
64510.0.2.3 DNS Server
64610.0.2.4 SMB Server
647
648The DHCP server assign addresses to the guest starting from 10.0.2.15.
649
650EODESCR
651};
652PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
653
654for (my $i = 0; $i < $MAX_NETS; $i++) {
655 $confdesc->{"net$i"} = $netdesc;
656}
657
ffa42b86
DC
658PVE::JSONSchema::register_format('pve-volume-id-or-qm-path', \&verify_volume_id_or_qm_path);
659sub verify_volume_id_or_qm_path {
822c8a07
WB
660 my ($volid, $noerr) = @_;
661
ffa42b86
DC
662 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m|^/|) {
663 return $volid;
664 }
665
666 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
822c8a07
WB
667 $volid = eval { PVE::JSONSchema::check_format('pve-volume-id', $volid, '') };
668 if ($@) {
669 return undef if $noerr;
670 die $@;
671 }
672 return $volid;
673}
674
1e3baf05 675my $drivename_hash;
19672434 676
0541eeb8
WB
677my %drivedesc_base = (
678 volume => { alias => 'file' },
679 file => {
93c0971c 680 type => 'string',
ffa42b86 681 format => 'pve-volume-id-or-qm-path',
0541eeb8
WB
682 default_key => 1,
683 format_description => 'volume',
684 description => "The drive's backing volume.",
685 },
686 media => {
687 type => 'string',
688 format_description => 'cdrom|disk',
689 enum => [qw(cdrom disk)],
690 description => "The drive's media type.",
691 default => 'disk',
692 optional => 1
693 },
694 cyls => {
695 type => 'integer',
696 format_description => 'count',
697 description => "Force the drive's physical geometry to have a specific cylinder count.",
698 optional => 1
699 },
700 heads => {
701 type => 'integer',
702 format_description => 'count',
703 description => "Force the drive's physical geometry to have a specific head count.",
704 optional => 1
705 },
706 secs => {
707 type => 'integer',
708 format_description => 'count',
709 description => "Force the drive's physical geometry to have a specific sector count.",
710 optional => 1
711 },
712 trans => {
713 type => 'string',
714 format_description => 'none|lba|auto',
715 enum => [qw(none lba auto)],
716 description => "Force disk geometry bios translation mode.",
717 optional => 1,
718 },
719 snapshot => {
720 type => 'boolean',
721 format_description => 'on|off',
722 description => "Whether the drive should be included when making snapshots.",
723 optional => 1,
724 },
725 cache => {
726 type => 'string',
727 format_description => 'none|writethrough|writeback|unsafe|directsync',
728 enum => [qw(none writethrough writeback unsafe directsync)],
729 description => "The drive's cache mode",
730 optional => 1,
731 },
732 format => {
733 type => 'string',
734 format_description => 'drive format',
735 enum => [qw(raw cow qcow qed qcow2 vmdk cloop)],
736 description => "The drive's backing file's data format.",
737 optional => 1,
738 },
739 size => {
47c28a68
WB
740 type => 'string',
741 format => 'disk-size',
0541eeb8
WB
742 description => "Disk size. This is purely informational and has no effect.",
743 optional => 1,
744 },
745 backup => {
746 type => 'boolean',
747 format_description => 'on|off',
748 description => "Whether the drive should be included when making backups.",
749 optional => 1,
750 },
751 werror => {
752 type => 'string',
753 format_description => 'enospc|ignore|report|stop',
754 enum => [qw(enospc ignore report stop)],
755 description => 'Write error action.',
756 optional => 1,
757 },
758 aio => {
759 type => 'string',
760 format_description => 'native|threads',
761 enum => [qw(native threads)],
762 description => 'AIO type to use.',
763 optional => 1,
764 },
765 discard => {
766 type => 'string',
767 format_description => 'ignore|on',
768 enum => [qw(ignore on)],
769 description => 'Controls whether to pass discard/trim requests to the underlying storage.',
770 optional => 1,
771 },
772 detect_zeroes => {
773 type => 'boolean',
774 description => 'Controls whether to detect and try to optimize writes of zeroes.',
775 optional => 1,
776 },
777 serial => {
778 type => 'string',
46630a5f 779 format => 'urlencoded',
0541eeb8 780 format_description => 'serial',
ba8fc5d1
WB
781 maxLength => 20*3, # *3 since it's %xx url enoded
782 description => "The drive's reported serial number, url-encoded, up to 20 bytes long.",
0541eeb8
WB
783 optional => 1,
784 }
785);
786
787my %rerror_fmt = (
788 rerror => {
789 type => 'string',
790 format_description => 'ignore|report|stop',
791 enum => [qw(ignore report stop)],
792 description => 'Read error action.',
793 optional => 1,
794 },
795);
796
797my %iothread_fmt = ( iothread => {
798 type => 'boolean',
799 format_description => 'off|on',
800 description => "Whether to use iothreads for this drive",
801 optional => 1,
802});
803
804my %model_fmt = (
805 model => {
806 type => 'string',
46630a5f 807 format => 'urlencoded',
0541eeb8 808 format_description => 'model',
ba8fc5d1
WB
809 maxLength => 40*3, # *3 since it's %xx url enoded
810 description => "The drive's reported model name, url-encoded, up to 40 bytes long.",
0541eeb8
WB
811 optional => 1,
812 },
813);
814
815my %queues_fmt = (
816 queues => {
817 type => 'integer',
818 format_description => 'nbqueues',
819 description => "Number of queues.",
820 minimum => 2,
821 optional => 1
822 }
823);
824
825my $add_throttle_desc = sub {
826 my ($key, $type, $what, $size, $longsize) = @_;
827 $drivedesc_base{$key} = {
828 type => $type,
829 format_description => $size,
830 description => "Maximum $what speed in $longsize per second.",
831 optional => 1,
832 };
833};
834# throughput: (leaky bucket)
835$add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
836$add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
837$add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
93c0971c
WB
838$add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
839$add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
840$add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
0541eeb8
WB
841$add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
842$add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
843$add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
844
845# pools: (pool of IO before throttling starts taking effect)
93c0971c
WB
846$add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
847$add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
848$add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
0541eeb8
WB
849$add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
850$add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
851$add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
852
853my $ide_fmt = {
854 %drivedesc_base,
855 %rerror_fmt,
856 %model_fmt,
857};
858
1e3baf05
DM
859my $idedesc = {
860 optional => 1,
0541eeb8 861 type => 'string', format => $ide_fmt,
3c770faa 862 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
1e3baf05
DM
863};
864PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
865
0541eeb8
WB
866my $scsi_fmt = {
867 %drivedesc_base,
868 %iothread_fmt,
869 %queues_fmt,
870};
1e3baf05
DM
871my $scsidesc = {
872 optional => 1,
0541eeb8 873 type => 'string', format => $scsi_fmt,
3c770faa 874 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
1e3baf05
DM
875};
876PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
877
0541eeb8
WB
878my $sata_fmt = {
879 %drivedesc_base,
880 %rerror_fmt,
881};
cdb0931f
DA
882my $satadesc = {
883 optional => 1,
0541eeb8 884 type => 'string', format => $sata_fmt,
3c770faa 885 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
cdb0931f
DA
886};
887PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
888
0541eeb8
WB
889my $virtio_fmt = {
890 %drivedesc_base,
891 %iothread_fmt,
892 %rerror_fmt,
893};
1e3baf05
DM
894my $virtiodesc = {
895 optional => 1,
0541eeb8 896 type => 'string', format => $virtio_fmt,
3c770faa 897 description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
1e3baf05
DM
898};
899PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
900
0541eeb8
WB
901my $alldrive_fmt = {
902 %drivedesc_base,
903 %rerror_fmt,
904 %iothread_fmt,
905 %model_fmt,
906 %queues_fmt,
907};
908
ff6ffe20 909my $usb_fmt = {
a6b9aee4
DC
910 host => {
911 default_key => 1,
912 type => 'string', format => 'pve-qm-usb-device',
913 format_description => 'HOSTUSBDEVICE|spice',
914 description => 'The Host USB device or port or the value spice',
915 },
916 usb3 => {
917 optional => 1,
918 type => 'boolean',
919 format_description => 'yes|no',
920 description => 'Specifies whether if given host option is a USB3 device or port',
921 },
922};
923
1e3baf05
DM
924my $usbdesc = {
925 optional => 1,
ff6ffe20 926 type => 'string', format => $usb_fmt,
1e3baf05 927 description => <<EODESCR,
2fe1a152 928Configure an USB device (n is 0 to 4). This can be used to
1e3baf05
DM
929pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
930
19672434 931'bus-port(.port)*' (decimal numbers) or
a6b9aee4
DC
932'vendor_id:product_id' (hexadeciaml numbers) or
933'spice'
1e3baf05 934
19672434 935You can use the 'lsusb -t' command to list existing usb devices.
1e3baf05 936
8a61e0fd 937NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1e3baf05 938
80401dd8
DM
939The value 'spice' can be used to add a usb redirection devices for spice.
940
a6b9aee4 941The 'usb3' option determines whether the device is a USB3 device or not (this does currently not work reliably with spice redirection and is then ignored).
da8b4189 942
1e3baf05
DM
943EODESCR
944};
945PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
946
1f4f447b
WB
947# NOTE: the match-groups of this regex are used in parse_hostpci
948my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
949my $hostpci_fmt = {
950 host => {
951 default_key => 1,
952 type => 'string',
953 pattern => qr/$PCIRE(;$PCIRE)*/,
954 format_description => 'HOSTPCIID[;HOSTPCIID2...]',
955 description => "The PCI ID of a host's PCI device or a list of PCI virtual functions of the host.",
956 },
957 rombar => {
958 type => 'boolean',
959 optional => 1,
960 default => 1,
961 },
962 pcie => {
963 type => 'boolean',
964 optional => 1,
965 default => 0,
966 },
967 'x-vga' => {
968 type => 'boolean',
969 optional => 1,
970 default => 0,
971 },
972};
973PVE::JSONSchema::register_format('pve-qm-hostpci', $hostpci_fmt);
974
040b06b7
DA
975my $hostpcidesc = {
976 optional => 1,
977 type => 'string', format => 'pve-qm-hostpci',
040b06b7
DA
978 description => <<EODESCR,
979Map host pci devices. HOSTPCIDEVICE syntax is:
980
981'bus:dev.func' (hexadecimal numbers)
982
983You can us the 'lspci' command to list existing pci devices.
984
0cea6a01
DM
985The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
986
8a61e0fd 987NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
040b06b7
DA
988
989Experimental: user reported problems with this option.
990EODESCR
991};
992PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
993
bae179aa
DA
994my $serialdesc = {
995 optional => 1,
ca0cef26 996 type => 'string',
1b0b51ed 997 pattern => '(/dev/.+|socket)',
bae179aa 998 description => <<EODESCR,
1b0b51ed 999Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
bae179aa 1000
8a61e0fd 1001NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
bae179aa
DA
1002
1003Experimental: user reported problems with this option.
1004EODESCR
1005};
bae179aa 1006
1989a89c
DA
1007my $paralleldesc= {
1008 optional => 1,
ca0cef26 1009 type => 'string',
9ecc8431 1010 pattern => '/dev/parport\d+|/dev/usb/lp\d+',
1989a89c 1011 description => <<EODESCR,
19672434 1012Map host parallel devices (n is 0 to 2).
1989a89c 1013
8a61e0fd 1014NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1989a89c
DA
1015
1016Experimental: user reported problems with this option.
1017EODESCR
1018};
1989a89c
DA
1019
1020for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1021 $confdesc->{"parallel$i"} = $paralleldesc;
1022}
1023
bae179aa
DA
1024for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1025 $confdesc->{"serial$i"} = $serialdesc;
1026}
1027
040b06b7
DA
1028for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1029 $confdesc->{"hostpci$i"} = $hostpcidesc;
1030}
1e3baf05
DM
1031
1032for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1033 $drivename_hash->{"ide$i"} = 1;
1034 $confdesc->{"ide$i"} = $idedesc;
1035}
1036
cdb0931f
DA
1037for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1038 $drivename_hash->{"sata$i"} = 1;
1039 $confdesc->{"sata$i"} = $satadesc;
1040}
1041
1e3baf05
DM
1042for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1043 $drivename_hash->{"scsi$i"} = 1;
1044 $confdesc->{"scsi$i"} = $scsidesc ;
1045}
1046
1047for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1048 $drivename_hash->{"virtio$i"} = 1;
1049 $confdesc->{"virtio$i"} = $virtiodesc;
1050}
1051
1052for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1053 $confdesc->{"usb$i"} = $usbdesc;
1054}
1055
1056my $unuseddesc = {
1057 optional => 1,
1058 type => 'string', format => 'pve-volume-id',
1059 description => "Reference to unused volumes.",
1060};
1061
1062for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1063 $confdesc->{"unused$i"} = $unuseddesc;
1064}
1065
1066my $kvm_api_version = 0;
1067
1068sub kvm_version {
1069
1070 return $kvm_api_version if $kvm_api_version;
1071
6b64503e 1072 my $fh = IO::File->new("</dev/kvm") ||
1e3baf05
DM
1073 return 0;
1074
6b64503e 1075 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
1e3baf05
DM
1076 $kvm_api_version = $v;
1077 }
1078
1079 $fh->close();
1080
1081 return $kvm_api_version;
1082}
1083
1084my $kvm_user_version;
1085
1086sub kvm_user_version {
1087
1088 return $kvm_user_version if $kvm_user_version;
1089
1090 $kvm_user_version = 'unknown';
1091
09b11429
TL
1092 my $code = sub {
1093 my $line = shift;
1094 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1095 $kvm_user_version = $2;
1096 }
1097 };
19672434 1098
09b11429
TL
1099 eval { run_command("kvm -version", outfunc => $code); };
1100 warn $@ if $@;
1e3baf05
DM
1101
1102 return $kvm_user_version;
1103
1104}
1105
1106my $kernel_has_vhost_net = -c '/dev/vhost-net';
1107
74479ee9 1108sub valid_drive_names {
1e3baf05 1109 # order is important - used to autoselect boot disk
19672434 1110 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05 1111 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
cdb0931f
DA
1112 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1113 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1e3baf05
DM
1114}
1115
74479ee9 1116sub is_valid_drivename {
1e3baf05
DM
1117 my $dev = shift;
1118
6b64503e 1119 return defined($drivename_hash->{$dev});
1e3baf05
DM
1120}
1121
1122sub option_exists {
1123 my $key = shift;
1124 return defined($confdesc->{$key});
19672434 1125}
1e3baf05
DM
1126
1127sub nic_models {
1128 return $nic_model_list;
1129}
1130
1131sub os_list_description {
1132
1133 return {
1134 other => 'Other',
1135 wxp => 'Windows XP',
1136 w2k => 'Windows 2000',
1137 w2k3 =>, 'Windows 2003',
1138 w2k8 => 'Windows 2008',
1139 wvista => 'Windows Vista',
1140 win7 => 'Windows 7',
a70ebde3 1141 win8 => 'Windows 8/2012',
1e3baf05
DM
1142 l24 => 'Linux 2.4',
1143 l26 => 'Linux 2.6',
19672434 1144 };
1e3baf05
DM
1145}
1146
1e3baf05
DM
1147my $cdrom_path;
1148
1149sub get_cdrom_path {
1150
1151 return $cdrom_path if $cdrom_path;
1152
1153 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
1154 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
1155 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
1156}
1157
1158sub get_iso_path {
1159 my ($storecfg, $vmid, $cdrom) = @_;
1160
1161 if ($cdrom eq 'cdrom') {
1162 return get_cdrom_path();
1163 } elsif ($cdrom eq 'none') {
1164 return '';
1165 } elsif ($cdrom =~ m|^/|) {
1166 return $cdrom;
1167 } else {
6b64503e 1168 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
1169 }
1170}
1171
1172# try to convert old style file names to volume IDs
1173sub filename_to_volume_id {
1174 my ($vmid, $file, $media) = @_;
1175
1176 if (!($file eq 'none' || $file eq 'cdrom' ||
1177 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
19672434 1178
1e3baf05 1179 return undef if $file =~ m|/|;
19672434 1180
1e3baf05
DM
1181 if ($media && $media eq 'cdrom') {
1182 $file = "local:iso/$file";
1183 } else {
1184 $file = "local:$vmid/$file";
1185 }
1186 }
1187
1188 return $file;
1189}
1190
1191sub verify_media_type {
1192 my ($opt, $vtype, $media) = @_;
1193
1194 return if !$media;
1195
1196 my $etype;
1197 if ($media eq 'disk') {
a125592c 1198 $etype = 'images';
1e3baf05
DM
1199 } elsif ($media eq 'cdrom') {
1200 $etype = 'iso';
1201 } else {
1202 die "internal error";
1203 }
1204
1205 return if ($vtype eq $etype);
19672434 1206
1e3baf05
DM
1207 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
1208}
1209
1210sub cleanup_drive_path {
1211 my ($opt, $storecfg, $drive) = @_;
1212
1213 # try to convert filesystem paths to volume IDs
1214
1215 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
1216 ($drive->{file} !~ m|^/dev/.+|) &&
1217 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
19672434 1218 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
1219 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
1220 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1221 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
1222 verify_media_type($opt, $vtype, $drive->{media});
1223 $drive->{file} = $volid;
1224 }
1225
1226 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
1227}
1228
b3c2bdd1
DM
1229sub parse_hotplug_features {
1230 my ($data) = @_;
1231
1232 my $res = {};
1233
1234 return $res if $data eq '0';
a1b7d579 1235
b3c2bdd1
DM
1236 $data = $confdesc->{hotplug}->{default} if $data eq '1';
1237
45827685 1238 foreach my $feature (PVE::Tools::split_list($data)) {
b3c2bdd1
DM
1239 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1240 $res->{$1} = 1;
1241 } else {
1242 warn "ignoring unknown hotplug feature '$feature'\n";
1243 }
1244 }
1245 return $res;
1246}
1247
1248PVE::JSONSchema::register_format('pve-hotplug-features', \&pve_verify_hotplug_features);
1249sub pve_verify_hotplug_features {
1250 my ($value, $noerr) = @_;
1251
1252 return $value if parse_hotplug_features($value);
1253
1254 return undef if $noerr;
1255
1256 die "unable to parse hotplug option\n";
1257}
1258
1e3baf05
DM
1259# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1260# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
036e0e2b 1261# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
6e47c3b4
WB
1262# [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1263# [,iothread=on][,serial=serial][,model=model]
1e3baf05
DM
1264
1265sub parse_drive {
1266 my ($key, $data) = @_;
1267
0541eeb8 1268 my ($interface, $index);
19672434 1269
0541eeb8
WB
1270 if ($key =~ m/^([^\d]+)(\d+)$/) {
1271 $interface = $1;
1272 $index = $2;
1e3baf05
DM
1273 } else {
1274 return undef;
1275 }
1276
0541eeb8
WB
1277 my $desc = $key =~ /^unused\d+$/ ? $alldrive_fmt
1278 : $confdesc->{$key}->{format};
1279 if (!$desc) {
1280 warn "invalid drive key: $key\n";
1281 return undef;
1282 }
1283 my $res = eval { PVE::JSONSchema::parse_property_string($desc, $data) };
1284 return undef if !$res;
1285 $res->{interface} = $interface;
1286 $res->{index} = $index;
1287
1288 my $error = 0;
1289 foreach my $opt (qw(bps bps_rd bps_wr)) {
1290 if (my $bps = defined(delete $res->{$opt})) {
1291 if (defined($res->{"m$opt"})) {
1292 warn "both $opt and m$opt specified\n";
1293 ++$error;
1294 next;
1e3baf05 1295 }
0541eeb8 1296 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1e3baf05
DM
1297 }
1298 }
0541eeb8 1299 return undef if $error;
be190583 1300
9bf371a6
DM
1301 return undef if $res->{mbps_rd} && $res->{mbps};
1302 return undef if $res->{mbps_wr} && $res->{mbps};
affd2f88
AD
1303 return undef if $res->{iops_rd} && $res->{iops};
1304 return undef if $res->{iops_wr} && $res->{iops};
74edd76b 1305
1e3baf05
DM
1306 if ($res->{media} && ($res->{media} eq 'cdrom')) {
1307 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
19672434 1308 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
1309 return undef if $res->{interface} eq 'virtio';
1310 }
1311
0541eeb8
WB
1312 if (my $size = $res->{size}) {
1313 return undef if !defined($res->{size} = PVE::JSONSchema::parse_size($size));
1e3baf05
DM
1314 }
1315
1316 return $res;
1317}
1318
1e3baf05
DM
1319sub print_drive {
1320 my ($vmid, $drive) = @_;
0541eeb8
WB
1321 my $data = { %$drive };
1322 delete $data->{$_} for qw(index interface);
1323 return PVE::JSONSchema::print_property_string($data, $alldrive_fmt);
1e3baf05
DM
1324}
1325
28ef82d3
DM
1326sub scsi_inquiry {
1327 my($fh, $noerr) = @_;
1328
1329 my $SG_IO = 0x2285;
1330 my $SG_GET_VERSION_NUM = 0x2282;
1331
1332 my $versionbuf = "\x00" x 8;
1333 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1334 if (!$ret) {
1335 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1336 return undef;
1337 }
97d62eb7 1338 my $version = unpack("I", $versionbuf);
28ef82d3
DM
1339 if ($version < 30000) {
1340 die "scsi generic interface too old\n" if !$noerr;
1341 return undef;
1342 }
97d62eb7 1343
28ef82d3
DM
1344 my $buf = "\x00" x 36;
1345 my $sensebuf = "\x00" x 8;
f334aa3e 1346 my $cmd = pack("C x3 C x1", 0x12, 36);
97d62eb7 1347
28ef82d3
DM
1348 # see /usr/include/scsi/sg.h
1349 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";
1350
97d62eb7
DM
1351 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1352 length($sensebuf), 0, length($buf), $buf,
28ef82d3
DM
1353 $cmd, $sensebuf, 6000);
1354
1355 $ret = ioctl($fh, $SG_IO, $packet);
1356 if (!$ret) {
1357 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1358 return undef;
1359 }
97d62eb7 1360
28ef82d3
DM
1361 my @res = unpack($sg_io_hdr_t, $packet);
1362 if ($res[17] || $res[18]) {
1363 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1364 return undef;
1365 }
1366
1367 my $res = {};
09984754 1368 (my $byte0, my $byte1, $res->{vendor},
28ef82d3
DM
1369 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
1370
09984754
DM
1371 $res->{removable} = $byte1 & 128 ? 1 : 0;
1372 $res->{type} = $byte0 & 31;
1373
28ef82d3
DM
1374 return $res;
1375}
1376
1377sub path_is_scsi {
1378 my ($path) = @_;
1379
1380 my $fh = IO::File->new("+<$path") || return undef;
1381 my $res = scsi_inquiry($fh, 1);
1382 close($fh);
1383
1384 return $res;
1385}
1386
db656e5f
DM
1387sub machine_type_is_q35 {
1388 my ($conf) = @_;
b467f79a 1389
db656e5f
DM
1390 return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
1391}
1392
1393sub print_tabletdevice_full {
1394 my ($conf) = @_;
b467f79a 1395
db656e5f
DM
1396 my $q35 = machine_type_is_q35($conf);
1397
1398 # we use uhci for old VMs because tablet driver was buggy in older qemu
1399 my $usbbus = $q35 ? "ehci" : "uhci";
b467f79a 1400
db656e5f
DM
1401 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1402}
1403
ca916ecc 1404sub print_drivedevice_full {
5bdcf937 1405 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
ca916ecc
DA
1406
1407 my $device = '';
1408 my $maxdev = 0;
19672434 1409
ca916ecc 1410 if ($drive->{interface} eq 'virtio') {
5bdcf937 1411 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges);
2ed36a41 1412 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
51f492cd 1413 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread};
2ed36a41 1414 } elsif ($drive->{interface} eq 'scsi') {
6731a4cf 1415
ee034f5c 1416 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
2ed36a41
DM
1417 my $unit = $drive->{index} % $maxdev;
1418 my $devicetype = 'hd';
69bcf246
WB
1419 my $path = '';
1420 if (drive_is_cdrom($drive)) {
1421 $devicetype = 'cd';
29b19529 1422 } else {
69bcf246
WB
1423 if ($drive->{file} =~ m|^/|) {
1424 $path = $drive->{file};
1425 if (my $info = path_is_scsi($path)) {
1426 if ($info->{type} == 0) {
1427 $devicetype = 'block';
1428 } elsif ($info->{type} == 1) { # tape
1429 $devicetype = 'generic';
1430 }
1431 }
1432 } else {
1433 $path = PVE::Storage::path($storecfg, $drive->{file});
1434 }
1435
1436 if($path =~ m/^iscsi\:\/\//){
1437 $devicetype = 'generic';
1438 }
1439 }
1440
1441 if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)){
1442 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1443 } else {
1444 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1445 }
cdd20088 1446
2ed36a41
DM
1447 } elsif ($drive->{interface} eq 'ide'){
1448 $maxdev = 2;
1449 my $controller = int($drive->{index} / $maxdev);
1450 my $unit = $drive->{index} % $maxdev;
1451 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
1452
7ebe888a 1453 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
0f2812c2 1454 if ($devicetype eq 'hd' && (my $model = $drive->{model})) {
46630a5f 1455 $model = URI::Escape::uri_unescape($model);
0f2812c2
WB
1456 $device .= ",model=$model";
1457 }
cdb0931f
DA
1458 } elsif ($drive->{interface} eq 'sata'){
1459 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1460 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1461 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
1462 } elsif ($drive->{interface} eq 'usb') {
1463 die "implement me";
1464 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1465 } else {
1466 die "unsupported interface type";
ca916ecc
DA
1467 }
1468
3b408e82
DM
1469 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1470
ca916ecc
DA
1471 return $device;
1472}
1473
15b21acc 1474sub get_initiator_name {
46f58b5f 1475 my $initiator;
15b21acc 1476
46f58b5f
DM
1477 my $fh = IO::File->new('/etc/iscsi/initiatorname.iscsi') || return undef;
1478 while (defined(my $line = <$fh>)) {
1479 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
15b21acc
MR
1480 $initiator = $1;
1481 last;
1482 }
46f58b5f
DM
1483 $fh->close();
1484
15b21acc
MR
1485 return $initiator;
1486}
1487
1e3baf05
DM
1488sub print_drive_full {
1489 my ($storecfg, $vmid, $drive) = @_;
1490
d81f0f09
DM
1491 my $path;
1492 my $volid = $drive->{file};
1493 my $format;
1494
1495 if (drive_is_cdrom($drive)) {
1496 $path = get_iso_path($storecfg, $vmid, $volid);
1497 } else {
1498 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1499 if ($storeid) {
1500 $path = PVE::Storage::path($storecfg, $volid);
1501 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
1502 $format = qemu_img_format($scfg, $volname);
1503 } else {
1504 $path = $volid;
5b61bff2 1505 $format = "raw";
d81f0f09
DM
1506 }
1507 }
1508
1e3baf05 1509 my $opts = '';
46630a5f 1510 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
1e3baf05
DM
1511 foreach my $o (@qemu_drive_options) {
1512 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
19672434 1513 }
46630a5f
WB
1514 if (my $serial = $drive->{serial}) {
1515 $serial = URI::Escape::uri_unescape($serial);
1516 $opts .= ",serial=$serial";
1517 }
1e3baf05 1518
d81f0f09
DM
1519 $opts .= ",format=$format" if $format && !$drive->{format};
1520
9bf371a6
DM
1521 foreach my $o (qw(bps bps_rd bps_wr)) {
1522 my $v = $drive->{"m$o"};
1523 $opts .= ",$o=" . int($v*1024*1024) if $v;
1524 }
1525
b2ee900e
WB
1526 my $cache_direct = 0;
1527
1528 if (my $cache = $drive->{cache}) {
1529 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1530 } elsif (!drive_is_cdrom($drive)) {
1531 $opts .= ",cache=none";
1532 $cache_direct = 1;
1533 }
1534
1535 # aio native works only with O_DIRECT
1536 if (!$drive->{aio}) {
1537 if($cache_direct) {
1538 $opts .= ",aio=native";
1539 } else {
1540 $opts .= ",aio=threads";
1541 }
1542 }
11490cf2 1543
6e47c3b4
WB
1544 if (!drive_is_cdrom($drive)) {
1545 my $detectzeroes;
7d4e30f3 1546 if (defined($drive->{detect_zeroes}) && !$drive->{detect_zeroes}) {
6e47c3b4
WB
1547 $detectzeroes = 'off';
1548 } elsif ($drive->{discard}) {
1549 $detectzeroes = $drive->{discard} eq 'on' ? 'unmap' : 'on';
1550 } else {
1551 # This used to be our default with discard not being specified:
1552 $detectzeroes = 'on';
1553 }
1554 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1555 }
f1e05305 1556
1e3baf05
DM
1557 my $pathinfo = $path ? "file=$path," : '';
1558
3ebfcc86 1559 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
1560}
1561
cc4d6182 1562sub print_netdevice_full {
ba9e1000 1563 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
cc4d6182
DA
1564
1565 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
1566
1567 my $device = $net->{model};
1568 if ($net->{model} eq 'virtio') {
1569 $device = 'virtio-net-pci';
1570 };
1571
5bdcf937 1572 my $pciaddr = print_pci_addr("$netid", $bridges);
5e2068d2 1573 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
a9410357
AD
1574 if ($net->{queues} && $net->{queues} > 1 && $net->{model} eq 'virtio'){
1575 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1576 my $vectors = $net->{queues} * 2 + 2;
1577 $tmpstr .= ",vectors=$vectors,mq=on";
1578 }
cc4d6182 1579 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
ba9e1000
DM
1580
1581 if ($use_old_bios_files) {
1582 my $romfile;
1583 if ($device eq 'virtio-net-pci') {
1584 $romfile = 'pxe-virtio.rom';
1585 } elsif ($device eq 'e1000') {
1586 $romfile = 'pxe-e1000.rom';
1587 } elsif ($device eq 'ne2k') {
1588 $romfile = 'pxe-ne2k_pci.rom';
1589 } elsif ($device eq 'pcnet') {
1590 $romfile = 'pxe-pcnet.rom';
1591 } elsif ($device eq 'rtl8139') {
1592 $romfile = 'pxe-rtl8139.rom';
1593 }
1594 $tmpstr .= ",romfile=$romfile" if $romfile;
1595 }
1596
cc4d6182
DA
1597 return $tmpstr;
1598}
1599
1600sub print_netdev_full {
208ba94e 1601 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
cc4d6182
DA
1602
1603 my $i = '';
1604 if ($netid =~ m/^net(\d+)$/) {
1605 $i = int($1);
1606 }
1607
1608 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
1609
1610 my $ifname = "tap${vmid}i$i";
1611
1612 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1613 die "interface name '$ifname' is too long (max 15 character)\n"
1614 if length($ifname) >= 16;
1615
1616 my $vhostparam = '';
1617 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
1618
1619 my $vmname = $conf->{name} || "vm$vmid";
1620
a9410357 1621 my $netdev = "";
208ba94e 1622 my $script = $hotplug ? "pve-bridge-hotplug" : "pve-bridge";
a9410357 1623
cc4d6182 1624 if ($net->{bridge}) {
208ba94e 1625 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
cc4d6182 1626 } else {
a9410357 1627 $netdev = "type=user,id=$netid,hostname=$vmname";
cc4d6182 1628 }
a9410357
AD
1629
1630 $netdev .= ",queues=$net->{queues}" if ($net->{queues} && $net->{model} eq 'virtio');
1631
1632 return $netdev;
cc4d6182 1633}
1e3baf05
DM
1634
1635sub drive_is_cdrom {
1636 my ($drive) = @_;
1637
1638 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
1639
1640}
1641
ffc0d8c7
WB
1642sub parse_number_sets {
1643 my ($set) = @_;
1644 my $res = [];
1645 foreach my $part (split(/;/, $set)) {
1646 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1647 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1648 push @$res, [ $1, $2 ];
2ed5d572 1649 } else {
ffc0d8c7 1650 die "invalid range: $part\n";
2ed5d572
AD
1651 }
1652 }
ffc0d8c7
WB
1653 return $res;
1654}
2ed5d572 1655
ffc0d8c7
WB
1656sub parse_numa {
1657 my ($data) = @_;
1658
1659 my $res = PVE::JSONSchema::parse_property_string($numa_fmt, $data);
1660 $res->{cpus} = parse_number_sets($res->{cpus}) if defined($res->{cpus});
1661 $res->{hostnodes} = parse_number_sets($res->{hostnodes}) if defined($res->{hostnodes});
2ed5d572
AD
1662 return $res;
1663}
1664
040b06b7
DA
1665sub parse_hostpci {
1666 my ($value) = @_;
1667
1668 return undef if !$value;
1669
1f4f447b 1670 my $res = PVE::JSONSchema::parse_property_string($hostpci_fmt, $value);
0cea6a01 1671
1f4f447b
WB
1672 my @idlist = split(/;/, $res->{host});
1673 delete $res->{host};
1674 foreach my $id (@idlist) {
1675 if ($id =~ /^$PCIRE$/) {
1676 push @{$res->{pciid}}, { id => $1, function => ($2//'0') };
0cea6a01 1677 } else {
1f4f447b
WB
1678 # should have been caught by parse_property_string already
1679 die "failed to parse PCI id: $id\n";
0cea6a01 1680 }
040b06b7 1681 }
040b06b7
DA
1682 return $res;
1683}
1684
1e3baf05
DM
1685# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1686sub parse_net {
1687 my ($data) = @_;
1688
cd9c34d1
WB
1689 my $res = eval { PVE::JSONSchema::parse_property_string($net_fmt, $data) };
1690 if ($@) {
1691 warn $@;
1692 return undef;
1e3baf05 1693 }
cd9c34d1 1694 $res->{macaddr} = PVE::Tools::random_ether_addr() if !defined($res->{macaddr});
1e3baf05
DM
1695 return $res;
1696}
1697
1698sub print_net {
1699 my $net = shift;
1700
cd9c34d1 1701 return PVE::JSONSchema::print_property_string($net, $net_fmt);
1e3baf05
DM
1702}
1703
1704sub add_random_macs {
1705 my ($settings) = @_;
1706
1707 foreach my $opt (keys %$settings) {
1708 next if $opt !~ m/^net(\d+)$/;
1709 my $net = parse_net($settings->{$opt});
1710 next if !$net;
1711 $settings->{$opt} = print_net($net);
1712 }
1713}
1714
055d554d
DM
1715sub vm_is_volid_owner {
1716 my ($storecfg, $vmid, $volid) = @_;
1717
1718 if ($volid !~ m|^/|) {
1719 my ($path, $owner);
1720 eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
1721 if ($owner && ($owner == $vmid)) {
1722 return 1;
1723 }
1724 }
1725
1726 return undef;
1727}
1728
3dc38fbb
WB
1729sub split_flagged_list {
1730 my $text = shift || '';
1731 $text =~ s/[,;]/ /g;
1732 $text =~ s/^\s+//;
1733 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1734}
1735
1736sub join_flagged_list {
1737 my ($how, $lst) = @_;
1738 join $how, map { $lst->{$_} . $_ } keys %$lst;
1739}
1740
055d554d 1741sub vmconfig_delete_pending_option {
3dc38fbb 1742 my ($conf, $key, $force) = @_;
055d554d
DM
1743
1744 delete $conf->{pending}->{$key};
3dc38fbb
WB
1745 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
1746 $pending_delete_hash->{$key} = $force ? '!' : '';
1747 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
1748}
1749
1750sub vmconfig_undelete_pending_option {
1751 my ($conf, $key) = @_;
1752
3dc38fbb 1753 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
055d554d
DM
1754 delete $pending_delete_hash->{$key};
1755
3dc38fbb
WB
1756 if (%$pending_delete_hash) {
1757 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
055d554d
DM
1758 } else {
1759 delete $conf->{pending}->{delete};
1760 }
1761}
1762
1763sub vmconfig_register_unused_drive {
1764 my ($storecfg, $vmid, $conf, $drive) = @_;
1765
1766 if (!drive_is_cdrom($drive)) {
1767 my $volid = $drive->{file};
1768 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
8793d495 1769 PVE::QemuConfig->add_unused_volume($conf, $volid, $vmid);
055d554d
DM
1770 }
1771 }
1772}
1773
c750e90a
DM
1774sub vmconfig_cleanup_pending {
1775 my ($conf) = @_;
1776
1777 # remove pending changes when nothing changed
1778 my $changes;
1779 foreach my $opt (keys %{$conf->{pending}}) {
1780 if (defined($conf->{$opt}) && ($conf->{pending}->{$opt} eq $conf->{$opt})) {
1781 $changes = 1;
1782 delete $conf->{pending}->{$opt};
1783 }
1784 }
1785
3dc38fbb 1786 my $current_delete_hash = split_flagged_list($conf->{pending}->{delete});
c750e90a 1787 my $pending_delete_hash = {};
3dc38fbb 1788 while (my ($opt, $force) = each %$current_delete_hash) {
c750e90a 1789 if (defined($conf->{$opt})) {
3dc38fbb 1790 $pending_delete_hash->{$opt} = $force;
c750e90a
DM
1791 } else {
1792 $changes = 1;
1793 }
1794 }
1795
3dc38fbb
WB
1796 if (%$pending_delete_hash) {
1797 $conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
c750e90a
DM
1798 } else {
1799 delete $conf->{pending}->{delete};
1800 }
1801
1802 return $changes;
1803}
1804
bd27e851 1805# smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
ff6ffe20 1806my $smbios1_fmt = {
bd27e851
WB
1807 uuid => {
1808 type => 'string',
1809 pattern => '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1810 format_description => 'UUID',
1811 optional => 1,
1812 },
1813 version => {
1814 type => 'string',
1815 pattern => '\S+',
1816 format_description => 'str',
1817 optional => 1,
1818 },
1819 serial => {
1820 type => 'string',
1821 pattern => '\S+',
1822 format_description => 'str',
1823 optional => 1,
1824 },
1825 manufacturer => {
1826 type => 'string',
1827 pattern => '\S+',
1828 format_description => 'name',
1829 optional => 1,
1830 },
1831 product => {
1832 type => 'string',
1833 pattern => '\S+',
1834 format_description => 'name',
1835 optional => 1,
1836 },
1837 sku => {
1838 type => 'string',
1839 pattern => '\S+',
1840 format_description => 'str',
1841 optional => 1,
1842 },
1843 family => {
1844 type => 'string',
1845 pattern => '\S+',
1846 format_description => 'str',
1847 optional => 1,
1848 },
2796e7d5
DM
1849};
1850
2796e7d5
DM
1851sub parse_smbios1 {
1852 my ($data) = @_;
1853
ff6ffe20 1854 my $res = eval { PVE::JSONSchema::parse_property_string($smbios1_fmt, $data) };
bd27e851 1855 warn $@ if $@;
2796e7d5
DM
1856 return $res;
1857}
1858
cd11416f
DM
1859sub print_smbios1 {
1860 my ($smbios1) = @_;
ff6ffe20 1861 return PVE::JSONSchema::print_property_string($smbios1, $smbios1_fmt);
cd11416f
DM
1862}
1863
ff6ffe20 1864PVE::JSONSchema::register_format('pve-qm-smbios1', $smbios1_fmt);
2796e7d5 1865
1e3baf05
DM
1866PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1867sub verify_bootdisk {
1868 my ($value, $noerr) = @_;
1869
74479ee9 1870 return $value if is_valid_drivename($value);
1e3baf05
DM
1871
1872 return undef if $noerr;
1873
1874 die "invalid boot disk '$value'\n";
1875}
1876
1877PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
1878sub verify_net {
1879 my ($value, $noerr) = @_;
1880
1881 return $value if parse_net($value);
1882
1883 return undef if $noerr;
19672434 1884
1e3baf05
DM
1885 die "unable to parse network options\n";
1886}
1887
0ea9541d
DM
1888sub parse_watchdog {
1889 my ($value) = @_;
1890
1891 return undef if !$value;
1892
ec3582b5
WB
1893 my $res = eval { PVE::JSONSchema::parse_property_string($watchdog_fmt, $value) };
1894 warn $@ if $@;
0ea9541d
DM
1895 return $res;
1896}
1897
1e3baf05
DM
1898sub parse_usb_device {
1899 my ($value) = @_;
1900
1901 return undef if !$value;
1902
1e3baf05 1903 my $res = {};
a6b9aee4
DC
1904 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1905 $res->{vendorid} = $2;
1906 $res->{productid} = $4;
1907 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1908 $res->{hostbus} = $1;
1909 $res->{hostport} = $2;
1910 } elsif ($value =~ m/^spice$/i) {
1911 $res->{spice} = 1;
1912 } else {
1913 return undef;
1e3baf05 1914 }
1e3baf05
DM
1915
1916 return $res;
1917}
19672434 1918
1e3baf05
DM
1919PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
1920sub verify_usb_device {
1921 my ($value, $noerr) = @_;
1922
1923 return $value if parse_usb_device($value);
1924
1925 return undef if $noerr;
19672434 1926
1e3baf05
DM
1927 die "unable to parse usb device\n";
1928}
1929
1e3baf05
DM
1930# add JSON properties for create and set function
1931sub json_config_properties {
1932 my $prop = shift;
1933
1934 foreach my $opt (keys %$confdesc) {
18bfb361 1935 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1e3baf05
DM
1936 $prop->{$opt} = $confdesc->{$opt};
1937 }
1938
1939 return $prop;
1940}
1941
1942sub check_type {
1943 my ($key, $value) = @_;
1944
1945 die "unknown setting '$key'\n" if !$confdesc->{$key};
1946
1947 my $type = $confdesc->{$key}->{type};
1948
6b64503e 1949 if (!defined($value)) {
1e3baf05
DM
1950 die "got undefined value\n";
1951 }
1952
1953 if ($value =~ m/[\n\r]/) {
1954 die "property contains a line feed\n";
1955 }
1956
1957 if ($type eq 'boolean') {
19672434
DM
1958 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1959 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1960 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
1961 } elsif ($type eq 'integer') {
1962 return int($1) if $value =~ m/^(\d+)$/;
1963 die "type check ('integer') failed - got '$value'\n";
04432191
AD
1964 } elsif ($type eq 'number') {
1965 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1966 die "type check ('number') failed - got '$value'\n";
1e3baf05
DM
1967 } elsif ($type eq 'string') {
1968 if (my $fmt = $confdesc->{$key}->{format}) {
1969 if ($fmt eq 'pve-qm-drive') {
1970 # special case - we need to pass $key to parse_drive()
6b64503e 1971 my $drive = parse_drive($key, $value);
1e3baf05
DM
1972 return $value if $drive;
1973 die "unable to parse drive options\n";
1974 }
1975 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
1976 return $value;
1977 }
1e3baf05 1978 $value =~ s/^\"(.*)\"$/$1/;
19672434 1979 return $value;
1e3baf05
DM
1980 } else {
1981 die "internal error"
1982 }
1983}
1984
040b06b7
DA
1985sub check_iommu_support{
1986 #fixme : need to check IOMMU support
1987 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1988
1989 my $iommu=1;
1990 return $iommu;
1991
1992}
1993
1e3baf05
DM
1994sub touch_config {
1995 my ($vmid) = @_;
1996
ffda963f 1997 my $conf = PVE::QemuConfig->config_file($vmid);
1e3baf05
DM
1998 utime undef, undef, $conf;
1999}
2000
1e3baf05 2001sub destroy_vm {
15cc8784 2002 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1e3baf05 2003
ffda963f 2004 my $conffile = PVE::QemuConfig->config_file($vmid);
1e3baf05 2005
ffda963f 2006 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 2007
ffda963f 2008 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 2009
19672434 2010 # only remove disks owned by this VM
1e3baf05
DM
2011 foreach_drive($conf, sub {
2012 my ($ds, $drive) = @_;
2013
6b64503e 2014 return if drive_is_cdrom($drive);
1e3baf05
DM
2015
2016 my $volid = $drive->{file};
ed221350 2017
ff1a2432 2018 return if !$volid || $volid =~ m|^/|;
1e3baf05 2019
6b64503e 2020 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 2021 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 2022
6b64503e 2023 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 2024 });
19672434 2025
a6af7b3e 2026 if ($keep_empty_config) {
9c502e26 2027 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
2028 } else {
2029 unlink $conffile;
2030 }
1e3baf05
DM
2031
2032 # also remove unused disk
2033 eval {
6b64503e 2034 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
2035
2036 eval {
6b64503e 2037 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 2038 my ($volid, $sid, $volname, $d) = @_;
6b64503e 2039 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
2040 });
2041 };
2042 warn $@ if $@;
2043
2044 };
2045 warn $@ if $@;
2046}
2047
1e3baf05
DM
2048sub parse_vm_config {
2049 my ($filename, $raw) = @_;
2050
2051 return undef if !defined($raw);
2052
554ac7e7 2053 my $res = {
fc1ddcdc 2054 digest => Digest::SHA::sha1_hex($raw),
0d18dcfc 2055 snapshots => {},
0d732d16 2056 pending => {},
554ac7e7 2057 };
1e3baf05 2058
19672434 2059 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
2060 || die "got strange filename '$filename'";
2061
2062 my $vmid = $1;
2063
0d18dcfc 2064 my $conf = $res;
b0ec896e 2065 my $descr;
e297c490 2066 my $section = '';
0581fe4f 2067
0d18dcfc
DM
2068 my @lines = split(/\n/, $raw);
2069 foreach my $line (@lines) {
1e3baf05 2070 next if $line =~ m/^\s*$/;
be190583 2071
eab09f4e 2072 if ($line =~ m/^\[PENDING\]\s*$/i) {
e297c490 2073 $section = 'pending';
b0ec896e
DM
2074 if (defined($descr)) {
2075 $descr =~ s/\s+$//;
2076 $conf->{description} = $descr;
2077 }
2078 $descr = undef;
e297c490 2079 $conf = $res->{$section} = {};
eab09f4e
AD
2080 next;
2081
0d732d16 2082 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
e297c490 2083 $section = $1;
b0ec896e
DM
2084 if (defined($descr)) {
2085 $descr =~ s/\s+$//;
2086 $conf->{description} = $descr;
2087 }
2088 $descr = undef;
e297c490 2089 $conf = $res->{snapshots}->{$section} = {};
0d18dcfc
DM
2090 next;
2091 }
1e3baf05 2092
0581fe4f 2093 if ($line =~ m/^\#(.*)\s*$/) {
b0ec896e 2094 $descr = '' if !defined($descr);
0581fe4f
DM
2095 $descr .= PVE::Tools::decode_text($1) . "\n";
2096 next;
2097 }
2098
1e3baf05 2099 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
b0ec896e 2100 $descr = '' if !defined($descr);
0581fe4f 2101 $descr .= PVE::Tools::decode_text($2);
0d18dcfc
DM
2102 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2103 $conf->{snapstate} = $1;
1e3baf05
DM
2104 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2105 my $key = $1;
2106 my $value = $2;
0d18dcfc 2107 $conf->{$key} = $value;
ef824322 2108 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
e297c490 2109 my $value = $1;
ef824322
DM
2110 if ($section eq 'pending') {
2111 $conf->{delete} = $value; # we parse this later
2112 } else {
2113 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
eab09f4e 2114 }
1e3baf05
DM
2115 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2116 my $key = $1;
2117 my $value = $2;
2118 eval { $value = check_type($key, $value); };
2119 if ($@) {
2120 warn "vm $vmid - unable to parse value of '$key' - $@";
2121 } else {
2122 my $fmt = $confdesc->{$key}->{format};
2123 if ($fmt && $fmt eq 'pve-qm-drive') {
2124 my $v = parse_drive($key, $value);
2125 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
2126 $v->{file} = $volid;
6b64503e 2127 $value = print_drive($vmid, $v);
1e3baf05
DM
2128 } else {
2129 warn "vm $vmid - unable to parse value of '$key'\n";
2130 next;
2131 }
2132 }
2133
2134 if ($key eq 'cdrom') {
0d18dcfc 2135 $conf->{ide2} = $value;
1e3baf05 2136 } else {
0d18dcfc 2137 $conf->{$key} = $value;
1e3baf05
DM
2138 }
2139 }
2140 }
2141 }
2142
b0ec896e
DM
2143 if (defined($descr)) {
2144 $descr =~ s/\s+$//;
2145 $conf->{description} = $descr;
2146 }
0d18dcfc 2147 delete $res->{snapstate}; # just to be sure
1e3baf05
DM
2148
2149 return $res;
2150}
2151
1858638f
DM
2152sub write_vm_config {
2153 my ($filename, $conf) = @_;
1e3baf05 2154
0d18dcfc
DM
2155 delete $conf->{snapstate}; # just to be sure
2156
1858638f
DM
2157 if ($conf->{cdrom}) {
2158 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
2159 $conf->{ide2} = $conf->{cdrom};
2160 delete $conf->{cdrom};
2161 }
1e3baf05
DM
2162
2163 # we do not use 'smp' any longer
1858638f
DM
2164 if ($conf->{sockets}) {
2165 delete $conf->{smp};
2166 } elsif ($conf->{smp}) {
2167 $conf->{sockets} = $conf->{smp};
2168 delete $conf->{cores};
2169 delete $conf->{smp};
1e3baf05
DM
2170 }
2171
ee2f90b1 2172 my $used_volids = {};
0d18dcfc 2173
ee2f90b1 2174 my $cleanup_config = sub {
ef824322 2175 my ($cref, $pending, $snapname) = @_;
1858638f 2176
ee2f90b1
DM
2177 foreach my $key (keys %$cref) {
2178 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
ef824322 2179 $key eq 'snapstate' || $key eq 'pending';
ee2f90b1 2180 my $value = $cref->{$key};
ef824322
DM
2181 if ($key eq 'delete') {
2182 die "propertry 'delete' is only allowed in [PENDING]\n"
2183 if !$pending;
2184 # fixme: check syntax?
2185 next;
2186 }
ee2f90b1
DM
2187 eval { $value = check_type($key, $value); };
2188 die "unable to parse value of '$key' - $@" if $@;
1858638f 2189
ee2f90b1
DM
2190 $cref->{$key} = $value;
2191
74479ee9 2192 if (!$snapname && is_valid_drivename($key)) {
ed221350 2193 my $drive = parse_drive($key, $value);
ee2f90b1
DM
2194 $used_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
2195 }
1e3baf05 2196 }
ee2f90b1
DM
2197 };
2198
2199 &$cleanup_config($conf);
ef824322
DM
2200
2201 &$cleanup_config($conf->{pending}, 1);
2202
ee2f90b1 2203 foreach my $snapname (keys %{$conf->{snapshots}}) {
ef824322
DM
2204 die "internal error" if $snapname eq 'pending';
2205 &$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
1e3baf05
DM
2206 }
2207
1858638f
DM
2208 # remove 'unusedX' settings if we re-add a volume
2209 foreach my $key (keys %$conf) {
2210 my $value = $conf->{$key};
ee2f90b1 2211 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1858638f 2212 delete $conf->{$key};
1e3baf05 2213 }
1858638f 2214 }
be190583 2215
0d18dcfc 2216 my $generate_raw_config = sub {
b0ec896e 2217 my ($conf, $pending) = @_;
0581fe4f 2218
0d18dcfc
DM
2219 my $raw = '';
2220
2221 # add description as comment to top of file
b0ec896e
DM
2222 if (defined(my $descr = $conf->{description})) {
2223 if ($descr) {
2224 foreach my $cl (split(/\n/, $descr)) {
2225 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
2226 }
2227 } else {
2228 $raw .= "#\n" if $pending;
2229 }
0d18dcfc
DM
2230 }
2231
2232 foreach my $key (sort keys %$conf) {
ef824322 2233 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
0d18dcfc
DM
2234 $raw .= "$key: $conf->{$key}\n";
2235 }
2236 return $raw;
2237 };
0581fe4f 2238
0d18dcfc 2239 my $raw = &$generate_raw_config($conf);
ef824322
DM
2240
2241 if (scalar(keys %{$conf->{pending}})){
2242 $raw .= "\n[PENDING]\n";
b0ec896e 2243 $raw .= &$generate_raw_config($conf->{pending}, 1);
ef824322
DM
2244 }
2245
0d18dcfc
DM
2246 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
2247 $raw .= "\n[$snapname]\n";
2248 $raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
1858638f 2249 }
1e3baf05 2250
1858638f
DM
2251 return $raw;
2252}
1e3baf05 2253
19672434 2254sub load_defaults {
1e3baf05
DM
2255
2256 my $res = {};
2257
2258 # we use static defaults from our JSON schema configuration
2259 foreach my $key (keys %$confdesc) {
2260 if (defined(my $default = $confdesc->{$key}->{default})) {
2261 $res->{$key} = $default;
2262 }
2263 }
19672434 2264
1e3baf05
DM
2265 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
2266 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
2267
2268 return $res;
2269}
2270
2271sub config_list {
2272 my $vmlist = PVE::Cluster::get_vmlist();
2273 my $res = {};
2274 return $res if !$vmlist || !$vmlist->{ids};
2275 my $ids = $vmlist->{ids};
2276
1e3baf05
DM
2277 foreach my $vmid (keys %$ids) {
2278 my $d = $ids->{$vmid};
2279 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 2280 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
2281 $res->{$vmid}->{exists} = 1;
2282 }
2283 return $res;
2284}
2285
64e13401
DM
2286# test if VM uses local resources (to prevent migration)
2287sub check_local_resources {
2288 my ($conf, $noerr) = @_;
2289
2290 my $loc_res = 0;
19672434 2291
e0ab7331
DM
2292 $loc_res = 1 if $conf->{hostusb}; # old syntax
2293 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 2294
0d29ab3b 2295 foreach my $k (keys %$conf) {
49ca581d 2296 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
d44712fc
EK
2297 # sockets are safe: they will recreated be on the target side post-migrate
2298 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2fe1a152 2299 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
2300 }
2301
2302 die "VM uses local resources\n" if $loc_res && !$noerr;
2303
2304 return $loc_res;
2305}
2306
719893a9 2307# check if used storages are available on all nodes (use by migrate)
47152e2e
DM
2308sub check_storage_availability {
2309 my ($storecfg, $conf, $node) = @_;
2310
2311 foreach_drive($conf, sub {
2312 my ($ds, $drive) = @_;
2313
2314 my $volid = $drive->{file};
2315 return if !$volid;
2316
2317 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2318 return if !$sid;
2319
2320 # check if storage is available on both nodes
2321 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
2322 PVE::Storage::storage_check_node($storecfg, $sid, $node);
2323 });
2324}
2325
719893a9
DM
2326# list nodes where all VM images are available (used by has_feature API)
2327sub shared_nodes {
2328 my ($conf, $storecfg) = @_;
2329
2330 my $nodelist = PVE::Cluster::get_nodelist();
2331 my $nodehash = { map { $_ => 1 } @$nodelist };
2332 my $nodename = PVE::INotify::nodename();
be190583 2333
719893a9
DM
2334 foreach_drive($conf, sub {
2335 my ($ds, $drive) = @_;
2336
2337 my $volid = $drive->{file};
2338 return if !$volid;
2339
2340 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
2341 if ($storeid) {
2342 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
2343 if ($scfg->{disable}) {
2344 $nodehash = {};
2345 } elsif (my $avail = $scfg->{nodes}) {
2346 foreach my $node (keys %$nodehash) {
2347 delete $nodehash->{$node} if !$avail->{$node};
2348 }
2349 } elsif (!$scfg->{shared}) {
2350 foreach my $node (keys %$nodehash) {
2351 delete $nodehash->{$node} if $node ne $nodename
2352 }
2353 }
2354 }
2355 });
2356
2357 return $nodehash
2358}
2359
1e3baf05
DM
2360sub check_cmdline {
2361 my ($pidfile, $pid) = @_;
2362
6b64503e
DM
2363 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
2364 if (defined($fh)) {
1e3baf05
DM
2365 my $line = <$fh>;
2366 $fh->close;
2367 return undef if !$line;
6b64503e 2368 my @param = split(/\0/, $line);
1e3baf05
DM
2369
2370 my $cmd = $param[0];
06094efd 2371 return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m|qemu-system-x86_64$|);
1e3baf05
DM
2372
2373 for (my $i = 0; $i < scalar (@param); $i++) {
2374 my $p = $param[$i];
2375 next if !$p;
2376 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2377 my $p = $param[$i+1];
2378 return 1 if $p && ($p eq $pidfile);
2379 return undef;
2380 }
2381 }
2382 }
2383 return undef;
2384}
2385
2386sub check_running {
7e8dcf2c 2387 my ($vmid, $nocheck, $node) = @_;
1e3baf05 2388
ffda963f 2389 my $filename = PVE::QemuConfig->config_file($vmid, $node);
1e3baf05
DM
2390
2391 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 2392 if !$nocheck && ! -f $filename;
1e3baf05 2393
e6c3b671 2394 my $pidfile = pidfile_name($vmid);
1e3baf05 2395
e6c3b671
DM
2396 if (my $fd = IO::File->new("<$pidfile")) {
2397 my $st = stat($fd);
1e3baf05 2398 my $line = <$fd>;
6b64503e 2399 close($fd);
1e3baf05
DM
2400
2401 my $mtime = $st->mtime;
2402 if ($mtime > time()) {
2403 warn "file '$filename' modified in future\n";
2404 }
2405
2406 if ($line =~ m/^(\d+)$/) {
2407 my $pid = $1;
e6c3b671
DM
2408 if (check_cmdline($pidfile, $pid)) {
2409 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
2410 return $pid;
2411 }
2412 }
1e3baf05
DM
2413 }
2414 }
2415
2416 return undef;
2417}
2418
2419sub vzlist {
19672434 2420
1e3baf05
DM
2421 my $vzlist = config_list();
2422
6b64503e 2423 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 2424
19672434 2425 while (defined(my $de = $fd->read)) {
1e3baf05
DM
2426 next if $de !~ m/^(\d+)\.pid$/;
2427 my $vmid = $1;
6b64503e
DM
2428 next if !defined($vzlist->{$vmid});
2429 if (my $pid = check_running($vmid)) {
1e3baf05
DM
2430 $vzlist->{$vmid}->{pid} = $pid;
2431 }
2432 }
2433
2434 return $vzlist;
2435}
2436
1e3baf05
DM
2437sub disksize {
2438 my ($storecfg, $conf) = @_;
2439
2440 my $bootdisk = $conf->{bootdisk};
2441 return undef if !$bootdisk;
74479ee9 2442 return undef if !is_valid_drivename($bootdisk);
1e3baf05
DM
2443
2444 return undef if !$conf->{$bootdisk};
2445
2446 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
2447 return undef if !defined($drive);
2448
2449 return undef if drive_is_cdrom($drive);
2450
2451 my $volid = $drive->{file};
2452 return undef if !$volid;
2453
24afaca0 2454 return $drive->{size};
1e3baf05
DM
2455}
2456
2457my $last_proc_pid_stat;
2458
03a33f30
DM
2459# get VM status information
2460# This must be fast and should not block ($full == false)
2461# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 2462sub vmstatus {
03a33f30 2463 my ($opt_vmid, $full) = @_;
1e3baf05
DM
2464
2465 my $res = {};
2466
19672434 2467 my $storecfg = PVE::Storage::config();
1e3baf05
DM
2468
2469 my $list = vzlist();
694fcad4 2470 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 2471
ae4915a2
DM
2472 my $cpucount = $cpuinfo->{cpus} || 1;
2473
1e3baf05
DM
2474 foreach my $vmid (keys %$list) {
2475 next if $opt_vmid && ($vmid ne $opt_vmid);
2476
ffda963f 2477 my $cfspath = PVE::QemuConfig->cfs_config_path($vmid);
1e3baf05
DM
2478 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
2479
2480 my $d = {};
2481 $d->{pid} = $list->{$vmid}->{pid};
2482
2483 # fixme: better status?
2484 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
2485
af990afe
DM
2486 my $size = disksize($storecfg, $conf);
2487 if (defined($size)) {
2488 $d->{disk} = 0; # no info available
1e3baf05
DM
2489 $d->{maxdisk} = $size;
2490 } else {
2491 $d->{disk} = 0;
2492 $d->{maxdisk} = 0;
2493 }
2494
2495 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
ae4915a2 2496 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
d7c8364b 2497 $d->{cpus} = $conf->{vcpus} if $conf->{vcpus};
ae4915a2 2498
1e3baf05 2499 $d->{name} = $conf->{name} || "VM $vmid";
19672434 2500 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1e3baf05 2501
8b1accf7 2502 if ($conf->{balloon}) {
4bdb0514 2503 $d->{balloon_min} = $conf->{balloon}*(1024*1024);
074e01c8 2504 $d->{shares} = defined($conf->{shares}) ? $conf->{shares} : 1000;
8b1accf7
DM
2505 }
2506
1e3baf05
DM
2507 $d->{uptime} = 0;
2508 $d->{cpu} = 0;
1e3baf05
DM
2509 $d->{mem} = 0;
2510
2511 $d->{netout} = 0;
2512 $d->{netin} = 0;
2513
2514 $d->{diskread} = 0;
2515 $d->{diskwrite} = 0;
2516
ffda963f 2517 $d->{template} = PVE::QemuConfig->is_template($conf);
4d8c851b 2518
1e3baf05
DM
2519 $res->{$vmid} = $d;
2520 }
2521
2522 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
2523 foreach my $dev (keys %$netdev) {
2524 next if $dev !~ m/^tap([1-9]\d*)i/;
2525 my $vmid = $1;
2526 my $d = $res->{$vmid};
2527 next if !$d;
19672434 2528
1e3baf05
DM
2529 $d->{netout} += $netdev->{$dev}->{receive};
2530 $d->{netin} += $netdev->{$dev}->{transmit};
604ea644
AD
2531
2532 if ($full) {
2533 $d->{nics}->{$dev}->{netout} = $netdev->{$dev}->{receive};
2534 $d->{nics}->{$dev}->{netin} = $netdev->{$dev}->{transmit};
2535 }
2536
1e3baf05
DM
2537 }
2538
1e3baf05
DM
2539 my $ctime = gettimeofday;
2540
2541 foreach my $vmid (keys %$list) {
2542
2543 my $d = $res->{$vmid};
2544 my $pid = $d->{pid};
2545 next if !$pid;
2546
694fcad4
DM
2547 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
2548 next if !$pstat; # not running
19672434 2549
694fcad4 2550 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 2551
694fcad4 2552 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 2553
694fcad4 2554 if ($pstat->{vsize}) {
6b64503e 2555 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
2556 }
2557
2558 my $old = $last_proc_pid_stat->{$pid};
2559 if (!$old) {
19672434
DM
2560 $last_proc_pid_stat->{$pid} = {
2561 time => $ctime,
1e3baf05
DM
2562 used => $used,
2563 cpu => 0,
1e3baf05
DM
2564 };
2565 next;
2566 }
2567
7f0b5beb 2568 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
2569
2570 if ($dtime > 1000) {
2571 my $dutime = $used - $old->{used};
2572
ae4915a2 2573 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 2574 $last_proc_pid_stat->{$pid} = {
19672434 2575 time => $ctime,
1e3baf05
DM
2576 used => $used,
2577 cpu => $d->{cpu},
1e3baf05
DM
2578 };
2579 } else {
2580 $d->{cpu} = $old->{cpu};
1e3baf05
DM
2581 }
2582 }
2583
f5eb281a 2584 return $res if !$full;
03a33f30
DM
2585
2586 my $qmpclient = PVE::QMPClient->new();
2587
64e7fcf2
DM
2588 my $ballooncb = sub {
2589 my ($vmid, $resp) = @_;
2590
2591 my $info = $resp->{'return'};
38babf81
DM
2592 return if !$info->{max_mem};
2593
64e7fcf2
DM
2594 my $d = $res->{$vmid};
2595
38babf81
DM
2596 # use memory assigned to VM
2597 $d->{maxmem} = $info->{max_mem};
2598 $d->{balloon} = $info->{actual};
2599
2600 if (defined($info->{total_mem}) && defined($info->{free_mem})) {
2601 $d->{mem} = $info->{total_mem} - $info->{free_mem};
2602 $d->{freemem} = $info->{free_mem};
64e7fcf2
DM
2603 }
2604
604ea644 2605 $d->{ballooninfo} = $info;
64e7fcf2
DM
2606 };
2607
03a33f30
DM
2608 my $blockstatscb = sub {
2609 my ($vmid, $resp) = @_;
2610 my $data = $resp->{'return'} || [];
2611 my $totalrdbytes = 0;
2612 my $totalwrbytes = 0;
604ea644 2613
03a33f30
DM
2614 for my $blockstat (@$data) {
2615 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
2616 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
604ea644
AD
2617
2618 $blockstat->{device} =~ s/drive-//;
2619 $res->{$vmid}->{blockstat}->{$blockstat->{device}} = $blockstat->{stats};
03a33f30
DM
2620 }
2621 $res->{$vmid}->{diskread} = $totalrdbytes;
2622 $res->{$vmid}->{diskwrite} = $totalwrbytes;
2623 };
2624
2625 my $statuscb = sub {
2626 my ($vmid, $resp) = @_;
64e7fcf2 2627
03a33f30 2628 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
64e7fcf2
DM
2629 # this fails if ballon driver is not loaded, so this must be
2630 # the last commnand (following command are aborted if this fails).
38babf81 2631 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
03a33f30
DM
2632
2633 my $status = 'unknown';
2634 if (!defined($status = $resp->{'return'}->{status})) {
2635 warn "unable to get VM status\n";
2636 return;
2637 }
2638
2639 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
2640 };
2641
2642 foreach my $vmid (keys %$list) {
2643 next if $opt_vmid && ($vmid ne $opt_vmid);
2644 next if !$res->{$vmid}->{pid}; # not running
2645 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2646 }
2647
c8125172 2648 $qmpclient->queue_execute(undef, 1);
03a33f30
DM
2649
2650 foreach my $vmid (keys %$list) {
2651 next if $opt_vmid && ($vmid ne $opt_vmid);
2652 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
2653 }
2654
1e3baf05
DM
2655 return $res;
2656}
2657
e059fb4d
AD
2658sub foreach_dimm {
2659 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2660
2661 my $dimm_id = 0;
2662 my $current_size = 1024;
2663 my $dimm_size = 512;
2664 return if $current_size == $memory;
2665
2666 for (my $j = 0; $j < 8; $j++) {
2667 for (my $i = 0; $i < 32; $i++) {
2668 my $name = "dimm${dimm_id}";
2669 $dimm_id++;
2670 my $numanode = $i % $sockets;
2671 $current_size += $dimm_size;
2672 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2673 return $current_size if $current_size >= $memory;
2674 }
2675 $dimm_size *= 2;
2676 }
2677}
2678
525814b2
AD
2679sub foreach_reverse_dimm {
2680 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2681
2682 my $dimm_id = 253;
2683 my $current_size = 4177920;
2684 my $dimm_size = 65536;
2685 return if $current_size == $memory;
2686
2687 for (my $j = 0; $j < 8; $j++) {
2688 for (my $i = 0; $i < 32; $i++) {
2689 my $name = "dimm${dimm_id}";
2690 $dimm_id--;
2691 my $numanode = $i % $sockets;
2692 $current_size -= $dimm_size;
2693 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2694 return $current_size if $current_size <= $memory;
2695 }
2696 $dimm_size /= 2;
2697 }
2698}
2699
1e3baf05
DM
2700sub foreach_drive {
2701 my ($conf, $func) = @_;
2702
74479ee9
FG
2703 foreach my $ds (valid_drive_names()) {
2704 next if !defined($conf->{$ds});
1e3baf05 2705
6b64503e 2706 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
2707 next if !$drive;
2708
2709 &$func($ds, $drive);
2710 }
2711}
2712
d5769dc2
DM
2713sub foreach_volid {
2714 my ($conf, $func) = @_;
be190583 2715
d5769dc2
DM
2716 my $volhash = {};
2717
2718 my $test_volid = sub {
2719 my ($volid, $is_cdrom) = @_;
2720
2721 return if !$volid;
be190583 2722
d5769dc2
DM
2723 $volhash->{$volid} = $is_cdrom || 0;
2724 };
2725
ed221350 2726 foreach_drive($conf, sub {
d5769dc2
DM
2727 my ($ds, $drive) = @_;
2728 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2729 });
2730
2731 foreach my $snapname (keys %{$conf->{snapshots}}) {
2732 my $snap = $conf->{snapshots}->{$snapname};
2733 &$test_volid($snap->{vmstate}, 0);
ed221350 2734 foreach_drive($snap, sub {
d5769dc2
DM
2735 my ($ds, $drive) = @_;
2736 &$test_volid($drive->{file}, drive_is_cdrom($drive));
2737 });
2738 }
2739
2740 foreach my $volid (keys %$volhash) {
be190583 2741 &$func($volid, $volhash->{$volid});
d5769dc2
DM
2742 }
2743}
2744
86b8228b
DM
2745sub vga_conf_has_spice {
2746 my ($vga) = @_;
2747
590e698c
DM
2748 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2749
2750 return $1 || 1;
86b8228b
DM
2751}
2752
1e3baf05 2753sub config_to_command {
67812f9c 2754 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
1e3baf05
DM
2755
2756 my $cmd = [];
8c559505
DM
2757 my $globalFlags = [];
2758 my $machineFlags = [];
2759 my $rtcFlags = [];
519ed28c 2760 my $cpuFlags = [];
5bdcf937 2761 my $devices = [];
b78ebef7 2762 my $pciaddr = '';
5bdcf937 2763 my $bridges = {};
1e3baf05
DM
2764 my $kvmver = kvm_user_version();
2765 my $vernum = 0; # unknown
b42d3cf9 2766 my $ostype = $conf->{ostype};
a3c52213
DM
2767 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2768 $vernum = $1*1000000+$2*1000;
2769 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
2770 $vernum = $1*1000000+$2*1000+$3;
2771 }
2772
a3c52213 2773 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
2774
2775 my $have_ovz = -f '/proc/vz/vestat';
2776
db656e5f 2777 my $q35 = machine_type_is_q35($conf);
4d3f29ed 2778 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
23f73120 2779 my $machine_type = $forcemachine || $conf->{machine};
249c4a6c
AD
2780 my $use_old_bios_files = undef;
2781 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
db656e5f 2782
f08e17c7
AD
2783 my $cpuunits = defined($conf->{cpuunits}) ?
2784 $conf->{cpuunits} : $defaults->{cpuunits};
2785
2786 push @$cmd, '/usr/bin/systemd-run';
2787 push @$cmd, '--scope';
2788 push @$cmd, '--slice', "qemu";
2789 push @$cmd, '--unit', $vmid;
ea002a8f
DM
2790 # set KillMode=none, so that systemd don't kill those scopes
2791 # at shutdown (pve-manager service should stop the VMs instead)
2792 push @$cmd, '-p', "KillMode=none";
f08e17c7 2793 push @$cmd, '-p', "CPUShares=$cpuunits";
58be00f1 2794 if ($conf->{cpulimit}) {
c6f773b8
DM
2795 my $cpulimit = int($conf->{cpulimit} * 100);
2796 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
58be00f1 2797 }
f08e17c7 2798
1e3baf05
DM
2799 push @$cmd, '/usr/bin/kvm';
2800
2801 push @$cmd, '-id', $vmid;
2802
2803 my $use_virtio = 0;
2804
c971c4f2
AD
2805 my $qmpsocket = qmp_socket($vmid);
2806 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2807 push @$cmd, '-mon', "chardev=qmp,mode=control";
2808
1e3baf05 2809
6b64503e 2810 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 2811
1e3baf05
DM
2812 push @$cmd, '-daemonize';
2813
2796e7d5
DM
2814 if ($conf->{smbios1}) {
2815 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2816 }
2817
3edb45e7 2818 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
a783c78e
AD
2819 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2820 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2821 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2bd70893 2822 PVE::Tools::file_copy($ovmfvar_src, $ovmfvar_dst, 256*1024);
a783c78e
AD
2823 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2824 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2825 }
2826
db656e5f 2827 if ($q35) {
b467f79a 2828 # the q35 chipset support native usb2, so we enable usb controller
db656e5f 2829 # by default for this machine type
f8e83f05 2830 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
db656e5f 2831 } else {
f8e83f05
AD
2832 $pciaddr = print_pci_addr("piix3", $bridges);
2833 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
24f0d39a 2834
f8e83f05 2835 my $use_usb2 = 0;
db656e5f
DM
2836 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2837 next if !$conf->{"usb$i"};
a6b9aee4
DC
2838 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format},$conf->{"usb$i"}) };
2839 next if !$d || $d->{usb3}; # do not add usb2 controller if we have only usb3 devices
db656e5f
DM
2840 $use_usb2 = 1;
2841 }
2842 # include usb device config
2843 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
fcc573ab 2844 }
19672434 2845
da8b4189
DC
2846 # add usb3 controller if needed
2847
2848 my $use_usb3 = 0;
2849 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2850 next if !$conf->{"usb$i"};
a6b9aee4
DC
2851 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format},$conf->{"usb$i"}) };
2852 next if !$d || !$d->{usb3};
da8b4189
DC
2853 $use_usb3 = 1;
2854 }
2855
2856 $pciaddr = print_pci_addr("xhci", $bridges);
2857 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2858
5acbfe9e 2859 my $vga = $conf->{vga};
2fa3151e 2860
590e698c
DM
2861 my $qxlnum = vga_conf_has_spice($vga);
2862 $vga = 'qxl' if $qxlnum;
2fa3151e 2863
5acbfe9e 2864 if (!$vga) {
264e519f
DM
2865 if ($conf->{ostype} && ($conf->{ostype} eq 'win8' ||
2866 $conf->{ostype} eq 'win7' ||
5acbfe9e
DM
2867 $conf->{ostype} eq 'w2k8')) {
2868 $vga = 'std';
2869 } else {
2870 $vga = 'cirrus';
2871 }
2872 }
2873
1e3baf05 2874 # enable absolute mouse coordinates (needed by vnc)
5acbfe9e
DM
2875 my $tablet;
2876 if (defined($conf->{tablet})) {
2877 $tablet = $conf->{tablet};
2878 } else {
2879 $tablet = $defaults->{tablet};
590e698c 2880 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
ef5e2be2 2881 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
5acbfe9e
DM
2882 }
2883
db656e5f 2884 push @$devices, '-device', print_tabletdevice_full($conf) if $tablet;
b467f79a 2885
16a91d65 2886 my $kvm_off = 0;
1e3baf05 2887 # host pci devices
040b06b7 2888 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2e3b7e2a
AD
2889 my $d = parse_hostpci($conf->{"hostpci$i"});
2890 next if !$d;
2891
2892 my $pcie = $d->{pcie};
2893 if($pcie){
2894 die "q35 machine model is not enabled" if !$q35;
2895 $pciaddr = print_pcie_addr("hostpci$i");
2896 }else{
2897 $pciaddr = print_pci_addr("hostpci$i", $bridges);
2898 }
2899
1f4f447b
WB
2900 my $rombar = defined($d->{rombar}) && !$d->{rombar} ? ',rombar=0' : '';
2901 my $xvga = '';
2902 if ($d->{'x-vga'}) {
2903 $xvga = ',x-vga=on';
16a91d65 2904 $kvm_off = 1;
137483c0 2905 $vga = 'none';
b42d3cf9 2906 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
bd92244c
AD
2907 push @$cpuFlags , 'hv_vendor_id=proxmox';
2908 }
230a4382
AD
2909 if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
2910 $xvga = "";
2911 }
137483c0 2912 }
4543ecf0
AD
2913 my $pcidevices = $d->{pciid};
2914 my $multifunction = 1 if @$pcidevices > 1;
2e3b7e2a 2915
4543ecf0
AD
2916 my $j=0;
2917 foreach my $pcidevice (@$pcidevices) {
2e3b7e2a 2918
4543ecf0
AD
2919 my $id = "hostpci$i";
2920 $id .= ".$j" if $multifunction;
2921 my $addr = $pciaddr;
2922 $addr .= ".$j" if $multifunction;
6ea8cd3b 2923 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
4543ecf0
AD
2924
2925 if($j == 0){
2926 $devicestr .= "$rombar$xvga";
2927 $devicestr .= ",multifunction=on" if $multifunction;
2928 }
2929
2930 push @$devices, '-device', $devicestr;
2931 $j++;
2932 }
1e3baf05
DM
2933 }
2934
2935 # usb devices
2936 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
a6b9aee4
DC
2937 next if !$conf->{"usb$i"};
2938 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format},$conf->{"usb$i"}) };
1e3baf05 2939 next if !$d;
da8b4189
DC
2940
2941 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2942 my $usbbus = '';
a6b9aee4 2943 if (defined($d->{usb3}) && $d->{usb3}) {
da8b4189
DC
2944 $usbbus = ',bus=xhci.0';
2945 }
2946
a6b9aee4
DC
2947 if (defined($d->{host})) {
2948 $d = parse_usb_device($d->{host});
2949 if (defined($d->{vendorid}) && defined($d->{productid})) {
2950 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2951 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
2952 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2953 } elsif (defined($d->{spice}) && $d->{spice}) {
2954 # usb redir support for spice, currently no usb3
2955 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2956 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2957 }
1e3baf05
DM
2958 }
2959 }
2960
1e3baf05 2961 # serial devices
bae179aa 2962 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 2963 if (my $path = $conf->{"serial$i"}) {
9f9d2fb2
DM
2964 if ($path eq 'socket') {
2965 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2966 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2967 push @$devices, '-device', "isa-serial,chardev=serial$i";
2968 } else {
2969 die "no such serial device\n" if ! -c $path;
2970 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2971 push @$devices, '-device', "isa-serial,chardev=serial$i";
2972 }
34978be3 2973 }
1e3baf05
DM
2974 }
2975
2976 # parallel devices
1989a89c 2977 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 2978 if (my $path = $conf->{"parallel$i"}) {
19672434 2979 die "no such parallel device\n" if ! -c $path;
32e69805 2980 my $devtype = $path =~ m!^/dev/usb/lp! ? 'tty' : 'parport';
4c5dbaf6 2981 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
5bdcf937 2982 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
34978be3 2983 }
1e3baf05
DM
2984 }
2985
2986 my $vmname = $conf->{name} || "vm$vmid";
2987
2988 push @$cmd, '-name', $vmname;
19672434 2989
1e3baf05
DM
2990 my $sockets = 1;
2991 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2992 $sockets = $conf->{sockets} if $conf->{sockets};
2993
2994 my $cores = $conf->{cores} || 1;
3bd18e48 2995
de9d1e55 2996 my $maxcpus = $sockets * $cores;
76267728 2997
de9d1e55 2998 my $vcpus = $conf->{vcpus} ? $conf->{vcpus} : $maxcpus;
76267728 2999
de9d1e55
AD
3000 my $allowed_vcpus = $cpuinfo->{cpus};
3001
6965d5d1 3002 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
de9d1e55
AD
3003 if ($allowed_vcpus < $maxcpus);
3004
3005 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
1e3baf05 3006
1e3baf05
DM
3007 push @$cmd, '-nodefaults';
3008
32baffb4 3009 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 3010
0888fdce
DM
3011 my $bootindex_hash = {};
3012 my $i = 1;
3013 foreach my $o (split(//, $bootorder)) {
3014 $bootindex_hash->{$o} = $i*100;
3015 $i++;
afdb31d5 3016 }
3b408e82 3017
cf71f776 3018 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
1e3baf05 3019
6b64503e 3020 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 3021
6b64503e 3022 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05 3023
ef5e2be2 3024 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
1e3baf05 3025
b7be4ba9
AD
3026 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3027 my $socket = vnc_socket($vmid);
3028 push @$cmd, '-vnc', "unix:$socket,x509,password";
3029 } else {
3030 push @$cmd, '-nographic';
3031 }
3032
1e3baf05 3033 # time drift fix
6b64503e 3034 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05 3035
6b64503e 3036 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
8c559505 3037 my $useLocaltime = $conf->{localtime};
1e3baf05 3038
b42d3cf9 3039 if ($ostype) {
6b9d84cf 3040 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
1e3baf05 3041
b42d3cf9 3042 if ($ostype =~ m/^w/) { # windows
8c559505 3043 $useLocaltime = 1 if !defined($conf->{localtime});
1e3baf05 3044
8c559505 3045 # use time drift fix when acpi is enabled
6b64503e 3046 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
8c559505 3047 $tdf = 1 if !defined($conf->{tdf});
1e3baf05
DM
3048 }
3049 }
3050
b42d3cf9
DM
3051 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3052 $ostype eq 'wvista') {
8c559505 3053 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
b7e0c8bf 3054 push @$cmd, '-no-hpet';
8f3f959d 3055 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
bd92244c
AD
3056 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3057 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3058 push @$cpuFlags , 'hv_time' if !$nokvm;
8a054ffd 3059
a1b7d579 3060 } else {
bd92244c 3061 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
8f3f959d 3062 }
462e8d19
AD
3063 }
3064
b42d3cf9 3065 if ($ostype eq 'win7' || $ostype eq 'win8') {
bd92244c 3066 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
b7e0c8bf 3067 }
1e3baf05
DM
3068 }
3069
8c559505
DM
3070 push @$rtcFlags, 'driftfix=slew' if $tdf;
3071
7f0b5beb 3072 if ($nokvm) {
8c559505 3073 push @$machineFlags, 'accel=tcg';
7f0b5beb
DM
3074 } else {
3075 die "No accelerator found!\n" if !$cpuinfo->{hvm};
3076 }
1e3baf05 3077
952958bc
DM
3078 if ($machine_type) {
3079 push @$machineFlags, "type=${machine_type}";
3bafc510
DM
3080 }
3081
8c559505
DM
3082 if ($conf->{startdate}) {
3083 push @$rtcFlags, "base=$conf->{startdate}";
3084 } elsif ($useLocaltime) {
3085 push @$rtcFlags, 'base=localtime';
3086 }
1e3baf05 3087
519ed28c 3088 my $cpu = $nokvm ? "qemu64" : "kvm64";
16a91d65 3089 if (my $cputype = $conf->{cpu}) {
ff6ffe20 3090 my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
16a91d65
WB
3091 or die "Cannot parse cpu description: $cputype\n";
3092 $cpu = $cpuconf->{cputype};
3093 $kvm_off = 1 if $cpuconf->{hidden};
3094 }
519ed28c 3095
4dc339e7
AD
3096 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3097
d853f40a
DM
3098 push @$cpuFlags , '-x2apic'
3099 if $conf->{ostype} && $conf->{ostype} eq 'solaris';
519ed28c 3100
2e1a5389
AD
3101 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3102
0dc48c3d
AD
3103 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3104
117a0414
AD
3105 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3106
3107 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
0da5a08c 3108 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
117a0414
AD
3109 }
3110
f1f7ea88 3111 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
dac7c619 3112
16a91d65
WB
3113 push @$cpuFlags, 'kvm=off' if $kvm_off;
3114
8930da74
DM
3115 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3116 die "internal error"; # should not happen
3117
3118 push @$cpuFlags, "vendor=${cpu_vendor}"
3119 if $cpu_vendor ne 'default';
3120
be190583 3121 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
519ed28c 3122
dac7c619 3123 push @$cmd, '-cpu', $cpu;
519ed28c 3124
4d3f29ed
AD
3125 my $memory = $conf->{memory} || $defaults->{memory};
3126 my $static_memory = 0;
3127 my $dimm_memory = 0;
3128
3129 if ($hotplug_features->{memory}) {
996635e5
DM
3130 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa};
3131 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
4d3f29ed 3132 $static_memory = $STATICMEM;
996635e5 3133 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
4d3f29ed 3134 $dimm_memory = $memory - $static_memory;
996635e5 3135 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
4d3f29ed
AD
3136
3137 } else {
3138
3139 $static_memory = $memory;
3140 push @$cmd, '-m', $static_memory;
3141 }
8a010eae 3142
67fb9de6 3143 if ($conf->{numa}) {
8a010eae 3144
2ed5d572
AD
3145 my $numa_totalmemory = undef;
3146 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3147 next if !$conf->{"numa$i"};
3148 my $numa = parse_numa($conf->{"numa$i"});
3149 next if !$numa;
67fb9de6
DM
3150 # memory
3151 die "missing numa node$i memory value\n" if !$numa->{memory};
2ed5d572
AD
3152 my $numa_memory = $numa->{memory};
3153 $numa_totalmemory += $numa_memory;
996635e5 3154 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2ed5d572 3155
67fb9de6 3156 # cpus
ffc0d8c7
WB
3157 my $cpulists = $numa->{cpus};
3158 die "missing numa node$i cpus\n" if !defined($cpulists);
3159 my $cpus = join(',', map {
3160 my ($start, $end) = @$_;
3161 defined($end) ? "$start-$end" : $start
3162 } @$cpulists);
8a010eae 3163
67fb9de6 3164 # hostnodes
ffc0d8c7
WB
3165 my $hostnodelists = $numa->{hostnodes};
3166 if (defined($hostnodelists)) {
3167 my $hostnodes;
3168 foreach my $hostnoderange (@$hostnodelists) {
3169 my ($start, $end) = @$hostnoderange;
3170 $hostnodes .= ',' if $hostnodes;
3171 $hostnodes .= $start;
3172 $hostnodes .= "-$end" if defined($end);
3173 $end //= $start;
3174 for (my $i = $start; $i <= $end; ++$i ) {
3175 die "host numa node$i don't exist\n" if ! -d "/sys/devices/system/node/node$i/";
3176 }
2ed5d572 3177 }
8a010eae 3178
67fb9de6 3179 # policy
2ed5d572 3180 my $policy = $numa->{policy};
67fb9de6
DM
3181 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3182 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2ed5d572
AD
3183 }
3184
3185 push @$cmd, '-object', $numa_object;
8a010eae
AD
3186 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3187 }
67fb9de6 3188
4d3f29ed
AD
3189 die "total memory for NUMA nodes must be equal to vm static memory\n"
3190 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2ed5d572
AD
3191
3192 #if no custom tology, we split memory and cores across numa nodes
3193 if(!$numa_totalmemory) {
3194
4d3f29ed 3195 my $numa_memory = ($static_memory / $sockets) . "M";
2ed5d572
AD
3196
3197 for (my $i = 0; $i < $sockets; $i++) {
3198
3199 my $cpustart = ($cores * $i);
3200 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3201 my $cpus = $cpustart;
3202 $cpus .= "-$cpuend" if $cpuend;
3203
3204 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3205 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3206 }
3207 }
8a010eae
AD
3208 }
3209
4d3f29ed 3210 if ($hotplug_features->{memory}) {
e059fb4d
AD
3211 foreach_dimm($conf, $vmid, $memory, $sockets, sub {
3212 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
996635e5 3213 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
e059fb4d
AD
3214 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3215
3216 #if dimm_memory is not aligned to dimm map
3217 if($current_size > $memory) {
3218 $conf->{memory} = $current_size;
ffda963f 3219 PVE::QemuConfig->write_config($vmid, $conf);
e059fb4d
AD
3220 }
3221 });
4d3f29ed
AD
3222 }
3223
1e3baf05
DM
3224 push @$cmd, '-S' if $conf->{freeze};
3225
3226 # set keyboard layout
3227 my $kb = $conf->{keyboard} || $defaults->{keyboard};
3228 push @$cmd, '-k', $kb if $kb;
3229
3230 # enable sound
3231 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3232 #push @$cmd, '-soundhw', 'es1370';
3233 #push @$cmd, '-soundhw', $soundhw if $soundhw;
ab6a046f 3234
bc84dcca 3235 if($conf->{agent}) {
7a6c2150 3236 my $qgasocket = qmp_socket($vmid, 1);
ab6a046f
AD
3237 my $pciaddr = print_pci_addr("qga0", $bridges);
3238 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3239 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3240 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3241 }
3242
1d794448 3243 my $spice_port;
2fa3151e 3244
590e698c
DM
3245 if ($qxlnum) {
3246 if ($qxlnum > 1) {
3247 if ($conf->{ostype} && $conf->{ostype} =~ m/^w/){
3248 for(my $i = 1; $i < $qxlnum; $i++){
3249 my $pciaddr = print_pci_addr("vga$i", $bridges);
3250 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3251 }
3252 } else {
3253 # assume other OS works like Linux
3254 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3255 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
2fa3151e
AD
3256 }
3257 }
3258
1011b570 3259 my $pciaddr = print_pci_addr("spice", $bridges);
95a4b4a9 3260
af0eba7e
WB
3261 my $nodename = PVE::INotify::nodename();
3262 my $pfamily = PVE::Tools::get_host_address_family($nodename);
3263 $spice_port = PVE::Tools::next_spice_port($pfamily);
943340a6 3264
fd1f36ac 3265 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
1011b570 3266
d2da6d9b
AD
3267 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3268 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3269 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
1011b570
DM
3270 }
3271
8d9ae0d2
DM
3272 # enable balloon by default, unless explicitly disabled
3273 if (!defined($conf->{balloon}) || $conf->{balloon}) {
3274 $pciaddr = print_pci_addr("balloon0", $bridges);
3275 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3276 }
1e3baf05 3277
0ea9541d
DM
3278 if ($conf->{watchdog}) {
3279 my $wdopts = parse_watchdog($conf->{watchdog});
5bdcf937 3280 $pciaddr = print_pci_addr("watchdog", $bridges);
0a40e8ea 3281 my $watchdog = $wdopts->{model} || 'i6300esb';
5bdcf937
AD
3282 push @$devices, '-device', "$watchdog$pciaddr";
3283 push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
0ea9541d
DM
3284 }
3285
1e3baf05 3286 my $vollist = [];
941e0c42 3287 my $scsicontroller = {};
26ee04b6 3288 my $ahcicontroller = {};
cdd20088 3289 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
1e3baf05 3290
5881b913
DM
3291 # Add iscsi initiator name if available
3292 if (my $initiator = get_initiator_name()) {
3293 push @$devices, '-iscsi', "initiator-name=$initiator";
3294 }
3295
1e3baf05
DM
3296 foreach_drive($conf, sub {
3297 my ($ds, $drive) = @_;
3298
ff1a2432 3299 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 3300 push @$vollist, $drive->{file};
ff1a2432 3301 }
afdb31d5 3302
1e3baf05 3303 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
3304
3305 if (drive_is_cdrom ($drive)) {
3306 if ($bootindex_hash->{d}) {
3307 $drive->{bootindex} = $bootindex_hash->{d};
3308 $bootindex_hash->{d} += 1;
3309 }
3310 } else {
3311 if ($bootindex_hash->{c}) {
3312 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
3313 $bootindex_hash->{c} += 1;
3314 }
3315 }
3316
51f492cd
AD
3317 if($drive->{interface} eq 'virtio'){
3318 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread};
3319 }
3320
941e0c42 3321 if ($drive->{interface} eq 'scsi') {
cdd20088 3322
ee034f5c 3323 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
6731a4cf 3324
6731a4cf 3325 $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges);
a1b7d579 3326 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
fc8b40fd
AD
3327
3328 my $iothread = '';
3329 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{iothread}){
3330 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3331 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
e7a5104d
DC
3332 } elsif ($drive->{iothread}) {
3333 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
fc8b40fd
AD
3334 }
3335
6e11f143
AD
3336 my $queues = '';
3337 if($conf->{scsihw} && $conf->{scsihw} eq "virtio-scsi-single" && $drive->{queues}){
3338 $queues = ",num_queues=$drive->{queues}";
3339 }
3340
3341 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
cdd20088 3342 $scsicontroller->{$controller}=1;
941e0c42 3343 }
3b408e82 3344
26ee04b6
DA
3345 if ($drive->{interface} eq 'sata') {
3346 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
5bdcf937
AD
3347 $pciaddr = print_pci_addr("ahci$controller", $bridges);
3348 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
26ee04b6
DA
3349 $ahcicontroller->{$controller}=1;
3350 }
46f58b5f 3351
15b21acc
MR
3352 my $drive_cmd = print_drive_full($storecfg, $vmid, $drive);
3353 push @$devices, '-drive',$drive_cmd;
46f58b5f 3354 push @$devices, '-device', print_drivedevice_full($storecfg, $conf, $vmid, $drive, $bridges);
1e3baf05
DM
3355 });
3356
cc4d6182 3357 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 3358 next if !$conf->{"net$i"};
cc4d6182
DA
3359 my $d = parse_net($conf->{"net$i"});
3360 next if !$d;
1e3baf05 3361
cc4d6182 3362 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 3363
cc4d6182
DA
3364 if ($bootindex_hash->{n}) {
3365 $d->{bootindex} = $bootindex_hash->{n};
3366 $bootindex_hash->{n} += 1;
3367 }
1e3baf05 3368
cc4d6182 3369 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
5bdcf937
AD
3370 push @$devices, '-netdev', $netdevfull;
3371
ba9e1000 3372 my $netdevicefull = print_netdevice_full($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
5bdcf937
AD
3373 push @$devices, '-device', $netdevicefull;
3374 }
1e3baf05 3375
db656e5f
DM
3376 if (!$q35) {
3377 # add pci bridges
fc79e813
AD
3378 if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3)) {
3379 $bridges->{1} = 1;
3380 $bridges->{2} = 1;
3381 }
3382
6731a4cf
AD
3383 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3384
f8e83f05
AD
3385 while (my ($k, $v) = each %$bridges) {
3386 $pciaddr = print_pci_addr("pci.$k");
3387 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3388 }
19672434
DM
3389 }
3390
1e3baf05
DM
3391 # add custom args
3392 if ($conf->{args}) {
3ada46c9 3393 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
3394 push @$cmd, @$aa;
3395 }
3396
5bdcf937 3397 push @$cmd, @$devices;
be190583 3398 push @$cmd, '-rtc', join(',', @$rtcFlags)
8c559505 3399 if scalar(@$rtcFlags);
be190583 3400 push @$cmd, '-machine', join(',', @$machineFlags)
8c559505
DM
3401 if scalar(@$machineFlags);
3402 push @$cmd, '-global', join(',', @$globalFlags)
3403 if scalar(@$globalFlags);
3404
1d794448 3405 return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
1e3baf05 3406}
19672434 3407
1e3baf05
DM
3408sub vnc_socket {
3409 my ($vmid) = @_;
3410 return "${var_run_tmpdir}/$vmid.vnc";
3411}
3412
943340a6 3413sub spice_port {
1011b570 3414 my ($vmid) = @_;
943340a6 3415
1d794448 3416 my $res = vm_mon_cmd($vmid, 'query-spice');
943340a6
DM
3417
3418 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
1011b570
DM
3419}
3420
c971c4f2 3421sub qmp_socket {
693d12a2
AD
3422 my ($vmid, $qga) = @_;
3423 my $sockettype = $qga ? 'qga' : 'qmp';
3424 return "${var_run_tmpdir}/$vmid.$sockettype";
c971c4f2
AD
3425}
3426
1e3baf05
DM
3427sub pidfile_name {
3428 my ($vmid) = @_;
3429 return "${var_run_tmpdir}/$vmid.pid";
3430}
3431
86fdcfb2
DA
3432sub vm_devices_list {
3433 my ($vmid) = @_;
3434
ceea9078 3435 my $res = vm_mon_cmd($vmid, 'query-pci');
ceea9078
DM
3436 my $devices = {};
3437 foreach my $pcibus (@$res) {
3438 foreach my $device (@{$pcibus->{devices}}) {
6e62a21f 3439 next if !$device->{'qdev_id'};
200644a7 3440 if ($device->{'pci_bridge'}) {
200644a7
AD
3441 $devices->{$device->{'qdev_id'}} = 1;
3442 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices}}) {
3443 next if !$bridge_device->{'qdev_id'};
3444 $devices->{$bridge_device->{'qdev_id'}} = 1;
3445 $devices->{$device->{'qdev_id'}}++;
3446 }
3447 } else {
200644a7
AD
3448 $devices->{$device->{'qdev_id'}} = 1;
3449 }
f78cc802
AD
3450 }
3451 }
3452
3453 my $resblock = vm_mon_cmd($vmid, 'query-block');
3454 foreach my $block (@$resblock) {
3455 if($block->{device} =~ m/^drive-(\S+)/){
3456 $devices->{$1} = 1;
1dc4f496
DM
3457 }
3458 }
86fdcfb2 3459
3d7389fe
DM
3460 my $resmice = vm_mon_cmd($vmid, 'query-mice');
3461 foreach my $mice (@$resmice) {
3462 if ($mice->{name} eq 'QEMU HID Tablet') {
3463 $devices->{tablet} = 1;
3464 last;
3465 }
3466 }
3467
1dc4f496 3468 return $devices;
86fdcfb2
DA
3469}
3470
ec21aa11 3471sub vm_deviceplug {
f19d1c47 3472 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
ae57f6b3 3473
db656e5f
DM
3474 my $q35 = machine_type_is_q35($conf);
3475
95d6343b
DA
3476 my $devices_list = vm_devices_list($vmid);
3477 return 1 if defined($devices_list->{$deviceid});
3478
fee46675
DM
3479 qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3480
3d7389fe 3481 if ($deviceid eq 'tablet') {
fee46675 3482
3d7389fe 3483 qemu_deviceadd($vmid, print_tabletdevice_full($conf));
3d7389fe 3484
fee46675 3485 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
40f28a9f 3486
22de899a
AD
3487 qemu_iothread_add($vmid, $deviceid, $device);
3488
fee46675 3489 qemu_driveadd($storecfg, $vmid, $device);
cdd20088 3490 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
fee46675 3491
5e5dcb73 3492 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3493 eval { qemu_deviceaddverify($vmid, $deviceid); };
3494 if (my $err = $@) {
63c2da2f
DM
3495 eval { qemu_drivedel($vmid, $deviceid); };
3496 warn $@ if $@;
fee46675 3497 die $err;
5e5dcb73 3498 }
cfc817c7 3499
2733141c 3500 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
fee46675 3501
fc8b40fd 3502
cdd20088 3503 my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
cfc817c7 3504 my $pciaddr = print_pci_addr($deviceid);
a1b7d579 3505 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw;
2733141c
AD
3506
3507 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
fee46675 3508
fc8b40fd
AD
3509 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) {
3510 qemu_iothread_add($vmid, $deviceid, $device);
3511 $devicefull .= ",iothread=iothread-$deviceid";
3512 }
3513
6e11f143
AD
3514 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues}) {
3515 $devicefull .= ",num_queues=$device->{queues}";
3516 }
3517
cfc817c7 3518 qemu_deviceadd($vmid, $devicefull);
fee46675 3519 qemu_deviceaddverify($vmid, $deviceid);
cfc817c7 3520
fee46675
DM
3521 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3522
3523 qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
3524 qemu_driveadd($storecfg, $vmid, $device);
a1b7d579 3525
fee46675
DM
3526 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
3527 eval { qemu_deviceadd($vmid, $devicefull); };
3528 if (my $err = $@) {
63c2da2f
DM
3529 eval { qemu_drivedel($vmid, $deviceid); };
3530 warn $@ if $@;
fee46675 3531 die $err;
a4f091a0 3532 }
a4f091a0 3533
fee46675
DM
3534 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3535
2630d2a9 3536 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
8718099c
AD
3537
3538 my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
3539 my $use_old_bios_files = undef;
3540 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
3541
3542 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
2630d2a9 3543 qemu_deviceadd($vmid, $netdevicefull);
fee46675
DM
3544 eval { qemu_deviceaddverify($vmid, $deviceid); };
3545 if (my $err = $@) {
3546 eval { qemu_netdevdel($vmid, $deviceid); };
3547 warn $@ if $@;
3548 die $err;
2630d2a9 3549 }
2630d2a9 3550
fee46675 3551 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
b467f79a 3552
40f28a9f
AD
3553 my $bridgeid = $2;
3554 my $pciaddr = print_pci_addr($deviceid);
3555 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
a1b7d579 3556
40f28a9f 3557 qemu_deviceadd($vmid, $devicefull);
fee46675
DM
3558 qemu_deviceaddverify($vmid, $deviceid);
3559
3560 } else {
a1b7d579 3561 die "can't hotplug device '$deviceid'\n";
40f28a9f
AD
3562 }
3563
5e5dcb73 3564 return 1;
a4dea331
DA
3565}
3566
3eec5767 3567# fixme: this should raise exceptions on error!
ec21aa11 3568sub vm_deviceunplug {
f19d1c47 3569 my ($vmid, $conf, $deviceid) = @_;
873c2d69 3570
95d6343b
DA
3571 my $devices_list = vm_devices_list($vmid);
3572 return 1 if !defined($devices_list->{$deviceid});
3573
63c2da2f
DM
3574 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
3575
3d7389fe 3576 if ($deviceid eq 'tablet') {
63c2da2f 3577
3d7389fe 3578 qemu_devicedel($vmid, $deviceid);
3d7389fe 3579
63c2da2f 3580 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
f19d1c47 3581
5e5dcb73 3582 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
3583 qemu_devicedelverify($vmid, $deviceid);
3584 qemu_drivedel($vmid, $deviceid);
22de899a
AD
3585 qemu_iothread_del($conf, $vmid, $deviceid);
3586
2733141c 3587 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
a1b7d579 3588
63c2da2f 3589 qemu_devicedel($vmid, $deviceid);
8ce30dde 3590 qemu_devicedelverify($vmid, $deviceid);
fc8b40fd 3591 qemu_iothread_del($conf, $vmid, $deviceid);
a1b7d579 3592
63c2da2f 3593 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
cfc817c7 3594
8bcf3068
AD
3595 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3596 my $device = parse_drive($deviceid, $conf->{$deviceid});
3597 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread};
3598
63c2da2f
DM
3599 qemu_devicedel($vmid, $deviceid);
3600 qemu_drivedel($vmid, $deviceid);
a1b7d579 3601 qemu_deletescsihw($conf, $vmid, $deviceid);
8ce30dde 3602
63c2da2f 3603 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
a4f091a0 3604
2630d2a9 3605 qemu_devicedel($vmid, $deviceid);
63c2da2f
DM
3606 qemu_devicedelverify($vmid, $deviceid);
3607 qemu_netdevdel($vmid, $deviceid);
3608
3609 } else {
3610 die "can't unplug device '$deviceid'\n";
2630d2a9
DA
3611 }
3612
5e5dcb73
DA
3613 return 1;
3614}
3615
3616sub qemu_deviceadd {
3617 my ($vmid, $devicefull) = @_;
873c2d69 3618
d695b5b7
AD
3619 $devicefull = "driver=".$devicefull;
3620 my %options = split(/[=,]/, $devicefull);
f19d1c47 3621
d695b5b7 3622 vm_mon_cmd($vmid, "device_add" , %options);
5e5dcb73 3623}
afdb31d5 3624
5e5dcb73 3625sub qemu_devicedel {
fee46675 3626 my ($vmid, $deviceid) = @_;
63c2da2f 3627
5a77d8c1 3628 my $ret = vm_mon_cmd($vmid, "device_del", id => $deviceid);
5e5dcb73
DA
3629}
3630
22de899a
AD
3631sub qemu_iothread_add {
3632 my($vmid, $deviceid, $device) = @_;
3633
3634 if ($device->{iothread}) {
3635 my $iothreads = vm_iothreads_list($vmid);
3636 qemu_objectadd($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3637 }
3638}
3639
3640sub qemu_iothread_del {
3641 my($conf, $vmid, $deviceid) = @_;
3642
3643 my $device = parse_drive($deviceid, $conf->{$deviceid});
3644 if ($device->{iothread}) {
3645 my $iothreads = vm_iothreads_list($vmid);
3646 qemu_objectdel($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3647 }
3648}
3649
4d3f29ed
AD
3650sub qemu_objectadd {
3651 my($vmid, $objectid, $qomtype) = @_;
3652
3653 vm_mon_cmd($vmid, "object-add", id => $objectid, "qom-type" => $qomtype);
3654
3655 return 1;
3656}
3657
3658sub qemu_objectdel {
3659 my($vmid, $objectid) = @_;
3660
3661 vm_mon_cmd($vmid, "object-del", id => $objectid);
3662
3663 return 1;
3664}
3665
5e5dcb73 3666sub qemu_driveadd {
fee46675 3667 my ($storecfg, $vmid, $device) = @_;
5e5dcb73
DA
3668
3669 my $drive = print_drive_full($storecfg, $vmid, $device);
7a69fc3c 3670 $drive =~ s/\\/\\\\/g;
8ead5ec7 3671 my $ret = vm_human_monitor_command($vmid, "drive_add auto \"$drive\"");
fee46675 3672
5e5dcb73 3673 # If the command succeeds qemu prints: "OK"
fee46675
DM
3674 return 1 if $ret =~ m/OK/s;
3675
3676 die "adding drive failed: $ret\n";
5e5dcb73 3677}
afdb31d5 3678
5e5dcb73
DA
3679sub qemu_drivedel {
3680 my($vmid, $deviceid) = @_;
873c2d69 3681
7b7c6d1b 3682 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73 3683 $ret =~ s/^\s+//;
a1b7d579 3684
63c2da2f 3685 return 1 if $ret eq "";
a1b7d579 3686
63c2da2f 3687 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
a1b7d579
DM
3688 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3689
63c2da2f 3690 die "deleting drive $deviceid failed : $ret\n";
5e5dcb73 3691}
f19d1c47 3692
5e5dcb73 3693sub qemu_deviceaddverify {
fee46675 3694 my ($vmid, $deviceid) = @_;
873c2d69 3695
5e5dcb73
DA
3696 for (my $i = 0; $i <= 5; $i++) {
3697 my $devices_list = vm_devices_list($vmid);
3698 return 1 if defined($devices_list->{$deviceid});
3699 sleep 1;
afdb31d5 3700 }
fee46675
DM
3701
3702 die "error on hotplug device '$deviceid'\n";
5e5dcb73 3703}
afdb31d5 3704
5e5dcb73
DA
3705
3706sub qemu_devicedelverify {
63c2da2f
DM
3707 my ($vmid, $deviceid) = @_;
3708
a1b7d579 3709 # need to verify that the device is correctly removed as device_del
63c2da2f 3710 # is async and empty return is not reliable
5e5dcb73 3711
5e5dcb73
DA
3712 for (my $i = 0; $i <= 5; $i++) {
3713 my $devices_list = vm_devices_list($vmid);
3714 return 1 if !defined($devices_list->{$deviceid});
3715 sleep 1;
afdb31d5 3716 }
63c2da2f
DM
3717
3718 die "error on hot-unplugging device '$deviceid'\n";
873c2d69
DA
3719}
3720
cdd20088 3721sub qemu_findorcreatescsihw {
cfc817c7
DA
3722 my ($storecfg, $conf, $vmid, $device) = @_;
3723
ee034f5c 3724 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
2733141c
AD
3725
3726 my $scsihwid="$controller_prefix$controller";
cfc817c7
DA
3727 my $devices_list = vm_devices_list($vmid);
3728
cdd20088 3729 if(!defined($devices_list->{$scsihwid})) {
fc8b40fd 3730 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
cfc817c7 3731 }
fee46675 3732
cfc817c7
DA
3733 return 1;
3734}
3735
8ce30dde
AD
3736sub qemu_deletescsihw {
3737 my ($conf, $vmid, $opt) = @_;
3738
3739 my $device = parse_drive($opt, $conf->{$opt});
3740
a1511b3c 3741 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
2733141c
AD
3742 vm_deviceunplug($vmid, $conf, "virtioscsi$device->{index}");
3743 return 1;
3744 }
3745
ee034f5c 3746 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
8ce30dde
AD
3747
3748 my $devices_list = vm_devices_list($vmid);
3749 foreach my $opt (keys %{$devices_list}) {
74479ee9 3750 if (PVE::QemuServer::is_valid_drivename($opt)) {
8ce30dde
AD
3751 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3752 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3753 return 1;
3754 }
3755 }
3756 }
3757
3758 my $scsihwid="scsihw$controller";
3759
3760 vm_deviceunplug($vmid, $conf, $scsihwid);
3761
3762 return 1;
3763}
3764
281fedb3 3765sub qemu_add_pci_bridge {
40f28a9f
AD
3766 my ($storecfg, $conf, $vmid, $device) = @_;
3767
3768 my $bridges = {};
281fedb3
DM
3769
3770 my $bridgeid;
3771
40f28a9f
AD
3772 print_pci_addr($device, $bridges);
3773
3774 while (my ($k, $v) = each %$bridges) {
3775 $bridgeid = $k;
3776 }
fee46675 3777 return 1 if !defined($bridgeid) || $bridgeid < 1;
281fedb3 3778
40f28a9f
AD
3779 my $bridge = "pci.$bridgeid";
3780 my $devices_list = vm_devices_list($vmid);
3781
281fedb3 3782 if (!defined($devices_list->{$bridge})) {
fee46675 3783 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
40f28a9f 3784 }
281fedb3 3785
40f28a9f
AD
3786 return 1;
3787}
3788
25088687
DM
3789sub qemu_set_link_status {
3790 my ($vmid, $device, $up) = @_;
3791
a1b7d579 3792 vm_mon_cmd($vmid, "set_link", name => $device,
25088687
DM
3793 up => $up ? JSON::true : JSON::false);
3794}
3795
2630d2a9
DA
3796sub qemu_netdevadd {
3797 my ($vmid, $conf, $device, $deviceid) = @_;
3798
208ba94e 3799 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
73aa03b8 3800 my %options = split(/[=,]/, $netdev);
2630d2a9 3801
73aa03b8
AD
3802 vm_mon_cmd($vmid, "netdev_add", %options);
3803 return 1;
2630d2a9
DA
3804}
3805
3806sub qemu_netdevdel {
3807 my ($vmid, $deviceid) = @_;
3808
89c1e0f4 3809 vm_mon_cmd($vmid, "netdev_del", id => $deviceid);
2630d2a9
DA
3810}
3811
838776ab 3812sub qemu_cpu_hotplug {
8edc9c08 3813 my ($vmid, $conf, $vcpus) = @_;
838776ab 3814
8edc9c08
AD
3815 my $sockets = 1;
3816 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3817 $sockets = $conf->{sockets} if $conf->{sockets};
3818 my $cores = $conf->{cores} || 1;
3819 my $maxcpus = $sockets * $cores;
838776ab 3820
8edc9c08 3821 $vcpus = $maxcpus if !$vcpus;
3a11fadb 3822
8edc9c08
AD
3823 die "you can't add more vcpus than maxcpus\n"
3824 if $vcpus > $maxcpus;
3a11fadb 3825
8edc9c08 3826 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3a11fadb 3827 die "online cpu unplug is not yet possible\n"
8edc9c08 3828 if $vcpus < $currentvcpus;
838776ab 3829
8edc9c08
AD
3830 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3831 die "vcpus in running vm is different than configuration\n"
3832 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
838776ab 3833
8edc9c08 3834 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
838776ab
AD
3835 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3836 }
3837}
3838
4d3f29ed
AD
3839sub qemu_memory_hotplug {
3840 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3841
3842 return $value if !check_running($vmid);
a1b7d579 3843
4d3f29ed 3844 my $memory = $conf->{memory} || $defaults->{memory};
a1b7d579 3845 $value = $defaults->{memory} if !$value;
4d3f29ed
AD
3846 return $value if $value == $memory;
3847
3848 my $static_memory = $STATICMEM;
3849 my $dimm_memory = $memory - $static_memory;
3850
3851 die "memory can't be lower than $static_memory MB" if $value < $static_memory;
4d3f29ed
AD
3852 die "you cannot add more memory than $MAX_MEM MB!\n" if $memory > $MAX_MEM;
3853
3854
3855 my $sockets = 1;
3856 $sockets = $conf->{sockets} if $conf->{sockets};
3857
525814b2 3858 if($value > $memory) {
e059fb4d 3859
525814b2
AD
3860 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3861 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
4d3f29ed 3862
525814b2 3863 return if $current_size <= $conf->{memory};
4d3f29ed 3864
525814b2
AD
3865 eval { vm_mon_cmd($vmid, "object-add", 'qom-type' => "memory-backend-ram", id => "mem-$name", props => { size => int($dimm_size*1024*1024) } ) };
3866 if (my $err = $@) {
3867 eval { qemu_objectdel($vmid, "mem-$name"); };
3868 die $err;
3869 }
3870
3871 eval { vm_mon_cmd($vmid, "device_add", driver => "pc-dimm", id => "$name", memdev => "mem-$name", node => $numanode) };
3872 if (my $err = $@) {
3873 eval { qemu_objectdel($vmid, "mem-$name"); };
3874 die $err;
3875 }
3876 #update conf after each succesful module hotplug
3877 $conf->{memory} = $current_size;
ffda963f 3878 PVE::QemuConfig->write_config($vmid, $conf);
525814b2
AD
3879 });
3880
3881 } else {
3882
3883 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3884 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3885
3886 return if $current_size >= $conf->{memory};
3887 print "try to unplug memory dimm $name\n";
3888
3889 my $retry = 0;
3890 while (1) {
3891 eval { qemu_devicedel($vmid, $name) };
3892 sleep 3;
3893 my $dimm_list = qemu_dimm_list($vmid);
3894 last if !$dimm_list->{$name};
3895 raise_param_exc({ $name => "error unplug memory module" }) if $retry > 5;
3896 $retry++;
3897 }
3898
3899 #update conf after each succesful module unplug
3900 $conf->{memory} = $current_size;
3901
3902 eval { qemu_objectdel($vmid, "mem-$name"); };
ffda963f 3903 PVE::QemuConfig->write_config($vmid, $conf);
525814b2
AD
3904 });
3905 }
3906}
3907
3908sub qemu_dimm_list {
3909 my ($vmid) = @_;
3910
3911 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices");
3912 my $dimms = {};
3913
3914 foreach my $dimm (@$dimmarray) {
3915
3916 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3917 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3918 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3919 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3920 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3921 }
3922 return $dimms;
4d3f29ed
AD
3923}
3924
affd2f88 3925sub qemu_block_set_io_throttle {
277ca170
WB
3926 my ($vmid, $deviceid,
3927 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3928 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
affd2f88 3929
f3f323a3
AD
3930 return if !check_running($vmid) ;
3931
277ca170
WB
3932 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3933 bps => int($bps),
3934 bps_rd => int($bps_rd),
3935 bps_wr => int($bps_wr),
3936 iops => int($iops),
3937 iops_rd => int($iops_rd),
3938 iops_wr => int($iops_wr),
3939 bps_max => int($bps_max),
3940 bps_rd_max => int($bps_rd_max),
3941 bps_wr_max => int($bps_wr_max),
3942 iops_max => int($iops_max),
3943 iops_rd_max => int($iops_rd_max),
3944 iops_wr_max => int($iops_wr_max)
3945 );
f3f323a3 3946
affd2f88
AD
3947}
3948
f5eb281a 3949# old code, only used to shutdown old VM after update
dab36e1e
DM
3950sub __read_avail {
3951 my ($fh, $timeout) = @_;
3952
3953 my $sel = new IO::Select;
3954 $sel->add($fh);
3955
3956 my $res = '';
3957 my $buf;
3958
3959 my @ready;
3960 while (scalar (@ready = $sel->can_read($timeout))) {
3961 my $count;
3962 if ($count = $fh->sysread($buf, 8192)) {
3963 if ($buf =~ /^(.*)\(qemu\) $/s) {
3964 $res .= $1;
3965 last;
3966 } else {
3967 $res .= $buf;
3968 }
3969 } else {
3970 if (!defined($count)) {
3971 die "$!\n";
3972 }
3973 last;
3974 }
3975 }
3976
3977 die "monitor read timeout\n" if !scalar(@ready);
f5eb281a 3978
dab36e1e
DM
3979 return $res;
3980}
3981
f5eb281a 3982# old code, only used to shutdown old VM after update
dab36e1e
DM
3983sub vm_monitor_command {
3984 my ($vmid, $cmdstr, $nocheck) = @_;
f5eb281a 3985
dab36e1e
DM
3986 my $res;
3987
3988 eval {
3989 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3990
3991 my $sname = "${var_run_tmpdir}/$vmid.mon";
3992
3993 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3994 die "unable to connect to VM $vmid socket - $!\n";
3995
3996 my $timeout = 3;
3997
3998 # hack: migrate sometime blocks the monitor (when migrate_downtime
3999 # is set)
4000 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4001 $timeout = 60*60; # 1 hour
4002 }
4003
4004 # read banner;
4005 my $data = __read_avail($sock, $timeout);
4006
4007 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4008 die "got unexpected qemu monitor banner\n";
4009 }
4010
4011 my $sel = new IO::Select;
4012 $sel->add($sock);
4013
4014 if (!scalar(my @ready = $sel->can_write($timeout))) {
4015 die "monitor write error - timeout";
4016 }
4017
4018 my $fullcmd = "$cmdstr\r";
4019
4020 # syslog('info', "VM $vmid monitor command: $cmdstr");
4021
4022 my $b;
4023 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4024 die "monitor write error - $!";
4025 }
4026
4027 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4028
4029 $timeout = 20;
4030
4031 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4032 $timeout = 60*60; # 1 hour
4033 } elsif ($cmdstr =~ m/^(eject|change)/) {
4034 $timeout = 60; # note: cdrom mount command is slow
4035 }
4036 if ($res = __read_avail($sock, $timeout)) {
4037
4038 my @lines = split("\r?\n", $res);
f5eb281a 4039
dab36e1e 4040 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
f5eb281a 4041
dab36e1e
DM
4042 $res = join("\n", @lines);
4043 $res .= "\n";
4044 }
4045 };
4046
4047 my $err = $@;
4048
4049 if ($err) {
4050 syslog("err", "VM $vmid monitor command failed - $err");
4051 die $err;
4052 }
f5eb281a 4053
dab36e1e
DM
4054 return $res;
4055}
4056
c1175c92
AD
4057sub qemu_block_resize {
4058 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4059
ed221350 4060 my $running = check_running($vmid);
c1175c92
AD
4061
4062 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4063
4064 return if !$running;
4065
4066 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4067
4068}
4069
1ab0057c
AD
4070sub qemu_volume_snapshot {
4071 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4072
ed221350 4073 my $running = check_running($vmid);
1ab0057c 4074
e5eaa028
WL
4075 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4076 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4077 } else {
4078 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4079 }
1ab0057c
AD
4080}
4081
fc46aff9
AD
4082sub qemu_volume_snapshot_delete {
4083 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4084
ed221350 4085 my $running = check_running($vmid);
fc46aff9
AD
4086
4087 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4088
4089 return if !$running;
4090
18bfb361 4091 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
fc46aff9
AD
4092}
4093
264e519f
DM
4094sub set_migration_caps {
4095 my ($vmid) = @_;
a89fded1 4096
8b8345f3 4097 my $cap_ref = [];
a89fded1
AD
4098
4099 my $enabled_cap = {
8b8345f3 4100 "auto-converge" => 1,
0b0a47e8 4101 "xbzrle" => 1,
8b8345f3
DM
4102 "x-rdma-pin-all" => 0,
4103 "zero-blocks" => 0,
b62532e4 4104 "compress" => 0
a89fded1
AD
4105 };
4106
8b8345f3 4107 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
a89fded1 4108
8b8345f3 4109 for my $supported_capability (@$supported_capabilities) {
b463a3ce
SP
4110 push @$cap_ref, {
4111 capability => $supported_capability->{capability},
22430fa2
DM
4112 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4113 };
a89fded1
AD
4114 }
4115
8b8345f3
DM
4116 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4117}
a89fded1 4118
81d95ae1 4119my $fast_plug_option = {
7498eb64 4120 'lock' => 1,
81d95ae1 4121 'name' => 1,
a1b7d579 4122 'onboot' => 1,
81d95ae1
DM
4123 'shares' => 1,
4124 'startup' => 1,
b0ec896e 4125 'description' => 1,
81d95ae1
DM
4126};
4127
3a11fadb
DM
4128# hotplug changes in [PENDING]
4129# $selection hash can be used to only apply specified options, for
4130# example: { cores => 1 } (only apply changed 'cores')
4131# $errors ref is used to return error messages
c427973b 4132sub vmconfig_hotplug_pending {
3a11fadb 4133 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
c427973b 4134
8e90138a 4135 my $defaults = load_defaults();
c427973b
DM
4136
4137 # commit values which do not have any impact on running VM first
3a11fadb
DM
4138 # Note: those option cannot raise errors, we we do not care about
4139 # $selection and always apply them.
4140
4141 my $add_error = sub {
4142 my ($opt, $msg) = @_;
4143 $errors->{$opt} = "hotplug problem - $msg";
4144 };
c427973b
DM
4145
4146 my $changes = 0;
4147 foreach my $opt (keys %{$conf->{pending}}) { # add/change
81d95ae1 4148 if ($fast_plug_option->{$opt}) {
c427973b
DM
4149 $conf->{$opt} = $conf->{pending}->{$opt};
4150 delete $conf->{pending}->{$opt};
4151 $changes = 1;
4152 }
4153 }
4154
4155 if ($changes) {
ffda963f
FG
4156 PVE::QemuConfig->write_config($vmid, $conf);
4157 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
c427973b
DM
4158 }
4159
b3c2bdd1 4160 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
c427973b 4161
3dc38fbb
WB
4162 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4163 while (my ($opt, $force) = each %$pending_delete_hash) {
3a11fadb 4164 next if $selection && !$selection->{$opt};
3a11fadb 4165 eval {
51a6f637
AD
4166 if ($opt eq 'hotplug') {
4167 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4168 } elsif ($opt eq 'tablet') {
b3c2bdd1 4169 die "skip\n" if !$hotplug_features->{usb};
3a11fadb
DM
4170 if ($defaults->{tablet}) {
4171 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4172 } else {
4173 vm_deviceunplug($vmid, $conf, $opt);
4174 }
8edc9c08 4175 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4176 die "skip\n" if !$hotplug_features->{cpu};
8edc9c08 4177 qemu_cpu_hotplug($vmid, $conf, undef);
9c2f7069 4178 } elsif ($opt eq 'balloon') {
81d95ae1
DM
4179 # enable balloon device is not hotpluggable
4180 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4181 } elsif ($fast_plug_option->{$opt}) {
4182 # do nothing
3eec5767 4183 } elsif ($opt =~ m/^net(\d+)$/) {
b3c2bdd1 4184 die "skip\n" if !$hotplug_features->{network};
3eec5767 4185 vm_deviceunplug($vmid, $conf, $opt);
74479ee9 4186 } elsif (is_valid_drivename($opt)) {
b3c2bdd1 4187 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
19120f99 4188 vm_deviceunplug($vmid, $conf, $opt);
3dc38fbb 4189 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4d3f29ed
AD
4190 } elsif ($opt =~ m/^memory$/) {
4191 die "skip\n" if !$hotplug_features->{memory};
4192 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
c8effec3
AD
4193 } elsif ($opt eq 'cpuunits') {
4194 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
58be00f1
AD
4195 } elsif ($opt eq 'cpulimit') {
4196 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3d7389fe 4197 } else {
e56beeda 4198 die "skip\n";
3d7389fe 4199 }
3a11fadb
DM
4200 };
4201 if (my $err = $@) {
e56beeda
DM
4202 &$add_error($opt, $err) if $err ne "skip\n";
4203 } else {
3a11fadb
DM
4204 # save new config if hotplug was successful
4205 delete $conf->{$opt};
4206 vmconfig_undelete_pending_option($conf, $opt);
ffda963f
FG
4207 PVE::QemuConfig->write_config($vmid, $conf);
4208 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4209 }
3d7389fe
DM
4210 }
4211
4212 foreach my $opt (keys %{$conf->{pending}}) {
3a11fadb 4213 next if $selection && !$selection->{$opt};
3d7389fe 4214 my $value = $conf->{pending}->{$opt};
3a11fadb 4215 eval {
51a6f637
AD
4216 if ($opt eq 'hotplug') {
4217 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4218 } elsif ($opt eq 'tablet') {
b3c2bdd1 4219 die "skip\n" if !$hotplug_features->{usb};
3a11fadb
DM
4220 if ($value == 1) {
4221 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4222 } elsif ($value == 0) {
4223 vm_deviceunplug($vmid, $conf, $opt);
4224 }
8edc9c08 4225 } elsif ($opt eq 'vcpus') {
b3c2bdd1 4226 die "skip\n" if !$hotplug_features->{cpu};
3a11fadb
DM
4227 qemu_cpu_hotplug($vmid, $conf, $value);
4228 } elsif ($opt eq 'balloon') {
81d95ae1 4229 # enable/disable balloning device is not hotpluggable
8fe689e7 4230 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
a1b7d579 4231 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
81d95ae1
DM
4232 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4233
3a11fadb 4234 # allow manual ballooning if shares is set to zero
4cc1efa6 4235 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
9c2f7069
AD
4236 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4237 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4238 }
a1b7d579 4239 } elsif ($opt =~ m/^net(\d+)$/) {
3eec5767 4240 # some changes can be done without hotplug
a1b7d579 4241 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
b3c2bdd1 4242 $vmid, $opt, $value);
74479ee9 4243 } elsif (is_valid_drivename($opt)) {
a05cff86 4244 # some changes can be done without hotplug
b3c2bdd1
DM
4245 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4246 $vmid, $opt, $value, 1);
4d3f29ed
AD
4247 } elsif ($opt =~ m/^memory$/) { #dimms
4248 die "skip\n" if !$hotplug_features->{memory};
4249 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
c8effec3
AD
4250 } elsif ($opt eq 'cpuunits') {
4251 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
58be00f1 4252 } elsif ($opt eq 'cpulimit') {
c6f773b8 4253 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
58be00f1 4254 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
3a11fadb 4255 } else {
e56beeda 4256 die "skip\n"; # skip non-hot-pluggable options
3d7389fe 4257 }
3a11fadb
DM
4258 };
4259 if (my $err = $@) {
e56beeda
DM
4260 &$add_error($opt, $err) if $err ne "skip\n";
4261 } else {
3a11fadb
DM
4262 # save new config if hotplug was successful
4263 $conf->{$opt} = $value;
4264 delete $conf->{pending}->{$opt};
ffda963f
FG
4265 PVE::QemuConfig->write_config($vmid, $conf);
4266 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3d7389fe 4267 }
3d7389fe 4268 }
c427973b 4269}
055d554d 4270
3dc38fbb
WB
4271sub try_deallocate_drive {
4272 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4273
4274 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4275 my $volid = $drive->{file};
4276 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4277 my $sid = PVE::Storage::parse_volume_id($volid);
4278 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
cee01bcb
WB
4279
4280 # check if the disk is really unused
cee01bcb 4281 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
77019edf 4282 if is_volume_in_use($storecfg, $conf, $key, $volid);
cee01bcb 4283 PVE::Storage::vdisk_free($storecfg, $volid);
3dc38fbb 4284 return 1;
40b977f3
WL
4285 } else {
4286 # If vm is not owner of this disk remove from config
4287 return 1;
3dc38fbb
WB
4288 }
4289 }
4290
4291 return undef;
4292}
4293
4294sub vmconfig_delete_or_detach_drive {
4295 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4296
4297 my $drive = parse_drive($opt, $conf->{$opt});
4298
4299 my $rpcenv = PVE::RPCEnvironment::get();
4300 my $authuser = $rpcenv->get_user();
4301
4302 if ($force) {
4303 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4304 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4305 } else {
4306 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4307 }
4308}
4309
055d554d 4310sub vmconfig_apply_pending {
3a11fadb 4311 my ($vmid, $conf, $storecfg) = @_;
c427973b
DM
4312
4313 # cold plug
055d554d 4314
3dc38fbb
WB
4315 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4316 while (my ($opt, $force) = each %$pending_delete_hash) {
055d554d 4317 die "internal error" if $opt =~ m/^unused/;
ffda963f 4318 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4319 if (!defined($conf->{$opt})) {
4320 vmconfig_undelete_pending_option($conf, $opt);
ffda963f 4321 PVE::QemuConfig->write_config($vmid, $conf);
74479ee9 4322 } elsif (is_valid_drivename($opt)) {
3dc38fbb 4323 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
055d554d
DM
4324 vmconfig_undelete_pending_option($conf, $opt);
4325 delete $conf->{$opt};
ffda963f 4326 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4327 } else {
4328 vmconfig_undelete_pending_option($conf, $opt);
4329 delete $conf->{$opt};
ffda963f 4330 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4331 }
4332 }
4333
ffda963f 4334 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4335
4336 foreach my $opt (keys %{$conf->{pending}}) { # add/change
ffda963f 4337 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4338
4339 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4340 # skip if nothing changed
74479ee9 4341 } elsif (is_valid_drivename($opt)) {
055d554d
DM
4342 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4343 if defined($conf->{$opt});
4344 $conf->{$opt} = $conf->{pending}->{$opt};
4345 } else {
4346 $conf->{$opt} = $conf->{pending}->{$opt};
4347 }
4348
4349 delete $conf->{pending}->{$opt};
ffda963f 4350 PVE::QemuConfig->write_config($vmid, $conf);
055d554d
DM
4351 }
4352}
4353
3eec5767
DM
4354my $safe_num_ne = sub {
4355 my ($a, $b) = @_;
4356
4357 return 0 if !defined($a) && !defined($b);
4358 return 1 if !defined($a);
4359 return 1 if !defined($b);
4360
4361 return $a != $b;
4362};
4363
4364my $safe_string_ne = sub {
4365 my ($a, $b) = @_;
4366
4367 return 0 if !defined($a) && !defined($b);
4368 return 1 if !defined($a);
4369 return 1 if !defined($b);
4370
4371 return $a ne $b;
4372};
4373
4374sub vmconfig_update_net {
b3c2bdd1 4375 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
3eec5767
DM
4376
4377 my $newnet = parse_net($value);
4378
4379 if ($conf->{$opt}) {
4380 my $oldnet = parse_net($conf->{$opt});
4381
4382 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4383 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4384 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4385 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4386
4387 # for non online change, we try to hot-unplug
7196b757 4388 die "skip\n" if !$hotplug;
3eec5767
DM
4389 vm_deviceunplug($vmid, $conf, $opt);
4390 } else {
4391
4392 die "internal error" if $opt !~ m/net(\d+)/;
4393 my $iface = "tap${vmid}i$1";
a1b7d579 4394
25088687
DM
4395 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4396 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
16d08ecf 4397 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
25088687 4398 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
3eec5767 4399 PVE::Network::tap_unplug($iface);
4f4fbeb0
WB
4400 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4401 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4402 # Rate can be applied on its own but any change above needs to
4403 # include the rate in tap_plug since OVS resets everything.
4404 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
3eec5767 4405 }
38c590d9 4406
25088687
DM
4407 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4408 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4409 }
4410
38c590d9 4411 return 1;
3eec5767
DM
4412 }
4413 }
a1b7d579 4414
7196b757 4415 if ($hotplug) {
38c590d9
DM
4416 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4417 } else {
4418 die "skip\n";
4419 }
3eec5767
DM
4420}
4421
a05cff86 4422sub vmconfig_update_disk {
b3c2bdd1 4423 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
a05cff86
DM
4424
4425 # fixme: do we need force?
4426
4427 my $drive = parse_drive($opt, $value);
4428
4429 if ($conf->{$opt}) {
4430
4431 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4432
4433 my $media = $drive->{media} || 'disk';
4434 my $oldmedia = $old_drive->{media} || 'disk';
4435 die "unable to change media type\n" if $media ne $oldmedia;
4436
4437 if (!drive_is_cdrom($old_drive)) {
4438
a1b7d579 4439 if ($drive->{file} ne $old_drive->{file}) {
a05cff86 4440
7196b757 4441 die "skip\n" if !$hotplug;
a05cff86
DM
4442
4443 # unplug and register as unused
4444 vm_deviceunplug($vmid, $conf, $opt);
4445 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
a1b7d579 4446
a05cff86
DM
4447 } else {
4448 # update existing disk
4449
4450 # skip non hotpluggable value
a1b7d579 4451 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
22de899a 4452 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
6e11f143 4453 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
a05cff86
DM
4454 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4455 die "skip\n";
4456 }
4457
4458 # apply throttle
4459 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4460 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4461 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4462 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4463 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4464 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4465 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4466 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4467 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4468 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4469 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4470 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
a1b7d579 4471
a05cff86
DM
4472 qemu_block_set_io_throttle($vmid,"drive-$opt",
4473 ($drive->{mbps} || 0)*1024*1024,
4474 ($drive->{mbps_rd} || 0)*1024*1024,
4475 ($drive->{mbps_wr} || 0)*1024*1024,
4476 $drive->{iops} || 0,
4477 $drive->{iops_rd} || 0,
4478 $drive->{iops_wr} || 0,
4479 ($drive->{mbps_max} || 0)*1024*1024,
4480 ($drive->{mbps_rd_max} || 0)*1024*1024,
4481 ($drive->{mbps_wr_max} || 0)*1024*1024,
4482 $drive->{iops_max} || 0,
4483 $drive->{iops_rd_max} || 0,
4484 $drive->{iops_wr_max} || 0);
4485
4486 }
a1b7d579 4487
a05cff86
DM
4488 return 1;
4489 }
4de1bb25
DM
4490
4491 } else { # cdrom
a1b7d579 4492
4de1bb25
DM
4493 if ($drive->{file} eq 'none') {
4494 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4495 } else {
4496 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4497 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4498 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4499 }
a1b7d579 4500
34758d66 4501 return 1;
a05cff86
DM
4502 }
4503 }
4504 }
4505
a1b7d579 4506 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4de1bb25 4507 # hotplug new disks
f7b4356f 4508 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4de1bb25 4509 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
a05cff86
DM
4510}
4511
1e3baf05 4512sub vm_start {
ba9e1000
DM
4513 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4514 $forcemachine, $spice_ticket) = @_;
1e3baf05 4515
ffda963f
FG
4516 PVE::QemuConfig->lock_config($vmid, sub {
4517 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
1e3baf05 4518
ffda963f 4519 die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
3dcb98d5 4520
ffda963f 4521 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 4522
7e8dcf2c 4523 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
1e3baf05 4524
055d554d 4525 if (!$statefile && scalar(keys %{$conf->{pending}})) {
3a11fadb 4526 vmconfig_apply_pending($vmid, $conf, $storecfg);
ffda963f 4527 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
055d554d
DM
4528 }
4529
6c47d546
DM
4530 my $defaults = load_defaults();
4531
4532 # set environment variable useful inside network script
4533 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4534
67812f9c 4535 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
6c47d546 4536
1e3baf05 4537 my $migrate_port = 0;
5bc1e039 4538 my $migrate_uri;
1e3baf05
DM
4539 if ($statefile) {
4540 if ($statefile eq 'tcp') {
5bc1e039
SP
4541 my $localip = "localhost";
4542 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
af0eba7e 4543 my $nodename = PVE::INotify::nodename();
5bc1e039 4544 if ($datacenterconf->{migration_unsecure}) {
5bc1e039 4545 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
407e0b8b 4546 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
5bc1e039 4547 }
af0eba7e
WB
4548 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4549 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
407e0b8b 4550 $migrate_uri = "tcp:${localip}:${migrate_port}";
6c47d546
DM
4551 push @$cmd, '-incoming', $migrate_uri;
4552 push @$cmd, '-S';
1e3baf05 4553 } else {
6c47d546 4554 push @$cmd, '-loadstate', $statefile;
1e3baf05 4555 }
91bd6c90
DM
4556 } elsif ($paused) {
4557 push @$cmd, '-S';
1e3baf05
DM
4558 }
4559
1e3baf05 4560 # host pci devices
040b06b7
DA
4561 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4562 my $d = parse_hostpci($conf->{"hostpci$i"});
4563 next if !$d;
b1f72af6
AD
4564 my $pcidevices = $d->{pciid};
4565 foreach my $pcidevice (@$pcidevices) {
4566 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
000fc0a2 4567
b1f72af6
AD
4568 my $info = pci_device_info("0000:$pciid");
4569 die "IOMMU not present\n" if !check_iommu_support();
4570 die "no pci device info for device '$pciid'\n" if !$info;
6ea8cd3b 4571 die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
8f3e88af 4572 die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
b1f72af6 4573 }
040b06b7 4574 }
1e3baf05
DM
4575
4576 PVE::Storage::activate_volumes($storecfg, $vollist);
4577
2b401189
AD
4578 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4579 my $cmd = [];
4580 push @$cmd, '/bin/systemctl', 'stop', "$vmid.scope";
4581 eval { run_command($cmd); };
4582 }
4583
585b6e28
DM
4584 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4585 umask => 0077); };
77cde36b
DC
4586
4587 if (my $err = $@) {
4588 # deactivate volumes if start fails
4589 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4590 die "start failed: $err";
4591 }
1e3baf05 4592
5bc1e039 4593 print "migration listens on $migrate_uri\n" if $migrate_uri;
afdb31d5 4594
8c609afd 4595 if ($statefile && $statefile ne 'tcp') {
95381ce0 4596 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
8c609afd 4597 warn $@ if $@;
62de2cbd
DM
4598 }
4599
1d794448 4600 if ($migratedfrom) {
a89fded1
AD
4601
4602 eval {
8e90138a 4603 set_migration_caps($vmid);
a89fded1 4604 };
1d794448 4605 warn $@ if $@;
a89fded1 4606
1d794448
DM
4607 if ($spice_port) {
4608 print "spice listens on port $spice_port\n";
4609 if ($spice_ticket) {
8e90138a
DM
4610 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
4611 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
95a4b4a9
AD
4612 }
4613 }
4614
1d794448 4615 } else {
4ec05c4c 4616
15b1fc93 4617 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
be190583 4618 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4ec05c4c 4619 if $conf->{balloon};
4ec05c4c 4620 }
25088687
DM
4621
4622 foreach my $opt (keys %$conf) {
4623 next if $opt !~ m/^net\d+$/;
4624 my $nicconf = parse_net($conf->{$opt});
4625 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4626 }
e18b0b99 4627 }
a1b7d579 4628
eb065317
AD
4629 vm_mon_cmd_nocheck($vmid, 'qom-set',
4630 path => "machine/peripheral/balloon0",
4631 property => "guest-stats-polling-interval",
4632 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4633
1e3baf05
DM
4634 });
4635}
4636
0eedc444
AD
4637sub vm_mon_cmd {
4638 my ($vmid, $execute, %params) = @_;
4639
26f11676
DM
4640 my $cmd = { execute => $execute, arguments => \%params };
4641 vm_qmp_command($vmid, $cmd);
0eedc444
AD
4642}
4643
4644sub vm_mon_cmd_nocheck {
4645 my ($vmid, $execute, %params) = @_;
4646
26f11676
DM
4647 my $cmd = { execute => $execute, arguments => \%params };
4648 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
4649}
4650
c971c4f2 4651sub vm_qmp_command {
c5a07de5 4652 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 4653
c971c4f2 4654 my $res;
26f11676 4655
14db5366
DM
4656 my $timeout;
4657 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4658 $timeout = $cmd->{arguments}->{timeout};
4659 delete $cmd->{arguments}->{timeout};
4660 }
be190583 4661
c971c4f2
AD
4662 eval {
4663 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
7a6c2150
DM
4664 my $sname = qmp_socket($vmid);
4665 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
c5a07de5 4666 my $qmpclient = PVE::QMPClient->new();
dab36e1e 4667
14db5366 4668 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
c5a07de5 4669 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
dab36e1e
DM
4670 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4671 if scalar(%{$cmd->{arguments}});
4672 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4673 } else {
4674 die "unable to open monitor socket\n";
4675 }
c971c4f2 4676 };
26f11676 4677 if (my $err = $@) {
c971c4f2
AD
4678 syslog("err", "VM $vmid qmp command failed - $err");
4679 die $err;
4680 }
4681
4682 return $res;
4683}
4684
9df5cbcc
DM
4685sub vm_human_monitor_command {
4686 my ($vmid, $cmdline) = @_;
4687
4688 my $res;
4689
f5eb281a 4690 my $cmd = {
9df5cbcc
DM
4691 execute => 'human-monitor-command',
4692 arguments => { 'command-line' => $cmdline},
4693 };
4694
4695 return vm_qmp_command($vmid, $cmd);
4696}
4697
1e3baf05
DM
4698sub vm_commandline {
4699 my ($storecfg, $vmid) = @_;
4700
ffda963f 4701 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05
DM
4702
4703 my $defaults = load_defaults();
4704
6b64503e 4705 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 4706
6b64503e 4707 return join(' ', @$cmd);
1e3baf05
DM
4708}
4709
4710sub vm_reset {
4711 my ($vmid, $skiplock) = @_;
4712
ffda963f 4713 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4714
ffda963f 4715 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4716
ffda963f 4717 PVE::QemuConfig->check_lock($conf) if !$skiplock;
1e3baf05 4718
816e2c4a 4719 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
4720 });
4721}
4722
4723sub get_vm_volumes {
4724 my ($conf) = @_;
1e3baf05 4725
ff1a2432 4726 my $vollist = [];
d5769dc2
DM
4727 foreach_volid($conf, sub {
4728 my ($volid, $is_cdrom) = @_;
ff1a2432 4729
d5769dc2 4730 return if $volid =~ m|^/|;
ff1a2432 4731
d5769dc2
DM
4732 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4733 return if !$sid;
ff1a2432
DM
4734
4735 push @$vollist, $volid;
1e3baf05 4736 });
ff1a2432
DM
4737
4738 return $vollist;
4739}
4740
4741sub vm_stop_cleanup {
70b04821 4742 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
ff1a2432 4743
745fed70 4744 eval {
ff1a2432 4745
254575e9
DM
4746 if (!$keepActive) {
4747 my $vollist = get_vm_volumes($conf);
4748 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4749 }
a1b7d579 4750
ab6a046f 4751 foreach my $ext (qw(mon qmp pid vnc qga)) {
961bfcb2
DM
4752 unlink "/var/run/qemu-server/${vmid}.$ext";
4753 }
a1b7d579 4754
70b04821 4755 vmconfig_apply_pending($vmid, $conf, $storecfg) if $apply_pending_changes;
745fed70
DM
4756 };
4757 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
4758}
4759
e6c3b671 4760# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
4761# We need that when migration VMs to other nodes (files already moved)
4762# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 4763sub vm_stop {
af30308f 4764 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
9269013a 4765
9269013a 4766 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 4767
af30308f
DM
4768 if ($migratedfrom){
4769 my $pid = check_running($vmid, $nocheck, $migratedfrom);
4770 kill 15, $pid if $pid;
ffda963f 4771 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
70b04821 4772 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
af30308f
DM
4773 return;
4774 }
4775
ffda963f 4776 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4777
e6c3b671 4778 my $pid = check_running($vmid, $nocheck);
ff1a2432 4779 return if !$pid;
1e3baf05 4780
ff1a2432 4781 my $conf;
e6c3b671 4782 if (!$nocheck) {
ffda963f
FG
4783 $conf = PVE::QemuConfig->load_config($vmid);
4784 PVE::QemuConfig->check_lock($conf) if !$skiplock;
7f4a5b5a 4785 if (!defined($timeout) && $shutdown && $conf->{startup}) {
38f7f26c 4786 my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
7f4a5b5a
DM
4787 $timeout = $opts->{down} if $opts->{down};
4788 }
e6c3b671 4789 }
19672434 4790
7f4a5b5a 4791 $timeout = 60 if !defined($timeout);
67fb9de6 4792
9269013a
DM
4793 eval {
4794 if ($shutdown) {
fbda7965 4795 if (defined($conf) && $conf->{agent}) {
2ea54503 4796 vm_qmp_command($vmid, { execute => "guest-shutdown" }, $nocheck);
1c0c1c17 4797 } else {
2ea54503 4798 vm_qmp_command($vmid, { execute => "system_powerdown" }, $nocheck);
1c0c1c17 4799 }
9269013a 4800 } else {
2ea54503 4801 vm_qmp_command($vmid, { execute => "quit" }, $nocheck);
afdb31d5 4802 }
9269013a 4803 };
1e3baf05
DM
4804 my $err = $@;
4805
4806 if (!$err) {
1e3baf05 4807 my $count = 0;
e6c3b671 4808 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
4809 $count++;
4810 sleep 1;
4811 }
4812
4813 if ($count >= $timeout) {
9269013a
DM
4814 if ($force) {
4815 warn "VM still running - terminating now with SIGTERM\n";
4816 kill 15, $pid;
4817 } else {
4818 die "VM quit/powerdown failed - got timeout\n";
4819 }
4820 } else {
70b04821 4821 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
9269013a 4822 return;
1e3baf05
DM
4823 }
4824 } else {
9269013a
DM
4825 if ($force) {
4826 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4827 kill 15, $pid;
4828 } else {
afdb31d5 4829 die "VM quit/powerdown failed\n";
9269013a 4830 }
1e3baf05
DM
4831 }
4832
4833 # wait again
ff1a2432 4834 $timeout = 10;
1e3baf05
DM
4835
4836 my $count = 0;
e6c3b671 4837 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
4838 $count++;
4839 sleep 1;
4840 }
4841
4842 if ($count >= $timeout) {
ff1a2432 4843 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 4844 kill 9, $pid;
ff1a2432 4845 sleep 1;
1e3baf05
DM
4846 }
4847
70b04821 4848 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
ff1a2432 4849 });
1e3baf05
DM
4850}
4851
4852sub vm_suspend {
4853 my ($vmid, $skiplock) = @_;
4854
ffda963f 4855 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4856
ffda963f 4857 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4858
e79706d4
FG
4859 PVE::QemuConfig->check_lock($conf)
4860 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
bcb7c9cf 4861
f77f91f3 4862 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
4863 });
4864}
4865
4866sub vm_resume {
289e0b85 4867 my ($vmid, $skiplock, $nocheck) = @_;
1e3baf05 4868
ffda963f 4869 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4870
289e0b85 4871 if (!$nocheck) {
1e3baf05 4872
ffda963f 4873 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4874
e79706d4
FG
4875 PVE::QemuConfig->check_lock($conf)
4876 if !($skiplock || PVE::QemuConfig->has_lock($conf, 'backup'));
289e0b85
AD
4877
4878 vm_mon_cmd($vmid, "cont");
4879
4880 } else {
4881 vm_mon_cmd_nocheck($vmid, "cont");
4882 }
1e3baf05
DM
4883 });
4884}
4885
5fdbe4f0
DM
4886sub vm_sendkey {
4887 my ($vmid, $skiplock, $key) = @_;
1e3baf05 4888
ffda963f 4889 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4890
ffda963f 4891 my $conf = PVE::QemuConfig->load_config($vmid);
f5eb281a 4892
7b7c6d1b
DM
4893 # there is no qmp command, so we use the human monitor command
4894 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
4895 });
4896}
4897
4898sub vm_destroy {
4899 my ($storecfg, $vmid, $skiplock) = @_;
4900
ffda963f 4901 PVE::QemuConfig->lock_config($vmid, sub {
1e3baf05 4902
ffda963f 4903 my $conf = PVE::QemuConfig->load_config($vmid);
1e3baf05 4904
ff1a2432 4905 if (!check_running($vmid)) {
15cc8784 4906 destroy_vm($storecfg, $vmid, undef, $skiplock);
ff1a2432
DM
4907 } else {
4908 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
4909 }
4910 });
4911}
4912
1e3baf05
DM
4913# pci helpers
4914
4915sub file_write {
4916 my ($filename, $buf) = @_;
4917
6b64503e 4918 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
4919 return undef if !$fh;
4920
4921 my $res = print $fh $buf;
4922
4923 $fh->close();
4924
4925 return $res;
4926}
4927
4928sub pci_device_info {
4929 my ($name) = @_;
4930
4931 my $res;
4932
4933 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4934 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4935
4936 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
4937 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4938
4939 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
4940 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4941
4942 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
4943 return undef if !defined($product) || $product !~ s/^0x//;
4944
4945 $res = {
4946 name => $name,
4947 vendor => $vendor,
4948 product => $product,
4949 domain => $domain,
4950 bus => $bus,
4951 slot => $slot,
4952 func => $func,
4953 irq => $irq,
4954 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
4955 };
4956
4957 return $res;
4958}
4959
4960sub pci_dev_reset {
4961 my ($dev) = @_;
4962
4963 my $name = $dev->{name};
4964
4965 my $fn = "$pcisysfs/devices/$name/reset";
4966
6b64503e 4967 return file_write($fn, "1");
1e3baf05
DM
4968}
4969
000fc0a2
SP
4970sub pci_dev_bind_to_vfio {
4971 my ($dev) = @_;
4972
4973 my $name = $dev->{name};
4974
4975 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4976
4977 if (!-d $vfio_basedir) {
4978 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4979 }
4980 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
4981
4982 my $testdir = "$vfio_basedir/$name";
4983 return 1 if -d $testdir;
4984
4985 my $data = "$dev->{vendor} $dev->{product}";
4986 return undef if !file_write("$vfio_basedir/new_id", $data);
4987
4988 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4989 if (!file_write($fn, $name)) {
4990 return undef if -f $fn;
4991 }
4992
4993 $fn = "$vfio_basedir/bind";
4994 if (! -d $testdir) {
4995 return undef if !file_write($fn, $name);
4996 }
4997
4998 return -d $testdir;
4999}
5000
5001sub pci_dev_group_bind_to_vfio {
5002 my ($pciid) = @_;
5003
5004 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5005
5006 if (!-d $vfio_basedir) {
5007 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5008 }
5009 die "Cannot find vfio-pci module!\n" if !-d $vfio_basedir;
5010
5011 # get IOMMU group devices
5012 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5013 my @devs = grep /^0000:/, readdir($D);
5014 closedir($D);
5015
5016 foreach my $pciid (@devs) {
5017 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
f8fa2ed7
SP
5018
5019 # pci bridges, switches or root ports are not supported
5020 # they have a pci_bus subdirectory so skip them
5021 next if (-e "$pcisysfs/devices/$pciid/pci_bus");
5022
000fc0a2
SP
5023 my $info = pci_device_info($1);
5024 pci_dev_bind_to_vfio($info) || die "Cannot bind $pciid to vfio\n";
5025 }
5026
5027 return 1;
5028}
5029
afdb31d5 5030sub print_pci_addr {
5bdcf937 5031 my ($id, $bridges) = @_;
6b64503e 5032
72a063e4 5033 my $res = '';
6b64503e 5034 my $devices = {
24f0d39a 5035 piix3 => { bus => 0, addr => 1 },
e5f7f8ed 5036 #addr2 : first videocard
13b5a753 5037 balloon0 => { bus => 0, addr => 3 },
0a40e8ea 5038 watchdog => { bus => 0, addr => 4 },
a1b7d579 5039 scsihw0 => { bus => 0, addr => 5 },
6731a4cf 5040 'pci.3' => { bus => 0, addr => 5 }, #can also be used for virtio-scsi-single bridge
cdd20088 5041 scsihw1 => { bus => 0, addr => 6 },
26ee04b6 5042 ahci0 => { bus => 0, addr => 7 },
ab6a046f 5043 qga0 => { bus => 0, addr => 8 },
1011b570 5044 spice => { bus => 0, addr => 9 },
6b64503e
DM
5045 virtio0 => { bus => 0, addr => 10 },
5046 virtio1 => { bus => 0, addr => 11 },
5047 virtio2 => { bus => 0, addr => 12 },
5048 virtio3 => { bus => 0, addr => 13 },
5049 virtio4 => { bus => 0, addr => 14 },
5050 virtio5 => { bus => 0, addr => 15 },
b78ebef7
DA
5051 hostpci0 => { bus => 0, addr => 16 },
5052 hostpci1 => { bus => 0, addr => 17 },
f290f8d9
DA
5053 net0 => { bus => 0, addr => 18 },
5054 net1 => { bus => 0, addr => 19 },
5055 net2 => { bus => 0, addr => 20 },
5056 net3 => { bus => 0, addr => 21 },
5057 net4 => { bus => 0, addr => 22 },
5058 net5 => { bus => 0, addr => 23 },
2fa3151e
AD
5059 vga1 => { bus => 0, addr => 24 },
5060 vga2 => { bus => 0, addr => 25 },
5061 vga3 => { bus => 0, addr => 26 },
5cffb2d2
AD
5062 hostpci2 => { bus => 0, addr => 27 },
5063 hostpci3 => { bus => 0, addr => 28 },
e5f7f8ed 5064 #addr29 : usb-host (pve-usb.cfg)
5bdcf937
AD
5065 'pci.1' => { bus => 0, addr => 30 },
5066 'pci.2' => { bus => 0, addr => 31 },
5067 'net6' => { bus => 1, addr => 1 },
5068 'net7' => { bus => 1, addr => 2 },
5069 'net8' => { bus => 1, addr => 3 },
5070 'net9' => { bus => 1, addr => 4 },
5071 'net10' => { bus => 1, addr => 5 },
5072 'net11' => { bus => 1, addr => 6 },
5073 'net12' => { bus => 1, addr => 7 },
5074 'net13' => { bus => 1, addr => 8 },
5075 'net14' => { bus => 1, addr => 9 },
5076 'net15' => { bus => 1, addr => 10 },
5077 'net16' => { bus => 1, addr => 11 },
5078 'net17' => { bus => 1, addr => 12 },
5079 'net18' => { bus => 1, addr => 13 },
5080 'net19' => { bus => 1, addr => 14 },
5081 'net20' => { bus => 1, addr => 15 },
5082 'net21' => { bus => 1, addr => 16 },
5083 'net22' => { bus => 1, addr => 17 },
5084 'net23' => { bus => 1, addr => 18 },
5085 'net24' => { bus => 1, addr => 19 },
5086 'net25' => { bus => 1, addr => 20 },
5087 'net26' => { bus => 1, addr => 21 },
5088 'net27' => { bus => 1, addr => 22 },
5089 'net28' => { bus => 1, addr => 23 },
5090 'net29' => { bus => 1, addr => 24 },
5091 'net30' => { bus => 1, addr => 25 },
5092 'net31' => { bus => 1, addr => 26 },
da8b4189 5093 'xhci' => { bus => 1, addr => 27 },
5bdcf937
AD
5094 'virtio6' => { bus => 2, addr => 1 },
5095 'virtio7' => { bus => 2, addr => 2 },
5096 'virtio8' => { bus => 2, addr => 3 },
5097 'virtio9' => { bus => 2, addr => 4 },
5098 'virtio10' => { bus => 2, addr => 5 },
5099 'virtio11' => { bus => 2, addr => 6 },
5100 'virtio12' => { bus => 2, addr => 7 },
5101 'virtio13' => { bus => 2, addr => 8 },
5102 'virtio14' => { bus => 2, addr => 9 },
5103 'virtio15' => { bus => 2, addr => 10 },
6731a4cf
AD
5104 'virtioscsi0' => { bus => 3, addr => 1 },
5105 'virtioscsi1' => { bus => 3, addr => 2 },
5106 'virtioscsi2' => { bus => 3, addr => 3 },
5107 'virtioscsi3' => { bus => 3, addr => 4 },
5108 'virtioscsi4' => { bus => 3, addr => 5 },
5109 'virtioscsi5' => { bus => 3, addr => 6 },
5110 'virtioscsi6' => { bus => 3, addr => 7 },
5111 'virtioscsi7' => { bus => 3, addr => 8 },
5112 'virtioscsi8' => { bus => 3, addr => 9 },
5113 'virtioscsi9' => { bus => 3, addr => 10 },
5114 'virtioscsi10' => { bus => 3, addr => 11 },
5115 'virtioscsi11' => { bus => 3, addr => 12 },
5116 'virtioscsi12' => { bus => 3, addr => 13 },
5117 'virtioscsi13' => { bus => 3, addr => 14 },
5118 'virtioscsi14' => { bus => 3, addr => 15 },
5119 'virtioscsi15' => { bus => 3, addr => 16 },
5120 'virtioscsi16' => { bus => 3, addr => 17 },
5121 'virtioscsi17' => { bus => 3, addr => 18 },
5122 'virtioscsi18' => { bus => 3, addr => 19 },
5123 'virtioscsi19' => { bus => 3, addr => 20 },
5124 'virtioscsi20' => { bus => 3, addr => 21 },
5125 'virtioscsi21' => { bus => 3, addr => 22 },
5126 'virtioscsi22' => { bus => 3, addr => 23 },
5127 'virtioscsi23' => { bus => 3, addr => 24 },
5128 'virtioscsi24' => { bus => 3, addr => 25 },
5129 'virtioscsi25' => { bus => 3, addr => 26 },
5130 'virtioscsi26' => { bus => 3, addr => 27 },
5131 'virtioscsi27' => { bus => 3, addr => 28 },
5132 'virtioscsi28' => { bus => 3, addr => 29 },
5133 'virtioscsi29' => { bus => 3, addr => 30 },
5134 'virtioscsi30' => { bus => 3, addr => 31 },
5135
6b64503e
DM
5136 };
5137
5138 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
72a063e4 5139 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
5bdcf937
AD
5140 my $bus = $devices->{$id}->{bus};
5141 $res = ",bus=pci.$bus,addr=$addr";
98627641 5142 $bridges->{$bus} = 1 if $bridges;
72a063e4
DA
5143 }
5144 return $res;
5145
5146}
5147
2e3b7e2a
AD
5148sub print_pcie_addr {
5149 my ($id) = @_;
5150
5151 my $res = '';
5152 my $devices = {
5153 hostpci0 => { bus => "ich9-pcie-port-1", addr => 0 },
5154 hostpci1 => { bus => "ich9-pcie-port-2", addr => 0 },
5155 hostpci2 => { bus => "ich9-pcie-port-3", addr => 0 },
5156 hostpci3 => { bus => "ich9-pcie-port-4", addr => 0 },
5157 };
5158
5159 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
5160 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
5161 my $bus = $devices->{$id}->{bus};
5162 $res = ",bus=$bus,addr=$addr";
5163 }
5164 return $res;
5165
5166}
5167
3e16d5fc
DM
5168# vzdump restore implementaion
5169
ed221350 5170sub tar_archive_read_firstfile {
3e16d5fc 5171 my $archive = shift;
afdb31d5 5172
3e16d5fc
DM
5173 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
5174
5175 # try to detect archive type first
5176 my $pid = open (TMP, "tar tf '$archive'|") ||
5177 die "unable to open file '$archive'\n";
5178 my $firstfile = <TMP>;
5179 kill 15, $pid;
5180 close TMP;
5181
5182 die "ERROR: archive contaions no data\n" if !$firstfile;
5183 chomp $firstfile;
5184
5185 return $firstfile;
5186}
5187
ed221350
DM
5188sub tar_restore_cleanup {
5189 my ($storecfg, $statfile) = @_;
3e16d5fc
DM
5190
5191 print STDERR "starting cleanup\n";
5192
5193 if (my $fd = IO::File->new($statfile, "r")) {
5194 while (defined(my $line = <$fd>)) {
5195 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5196 my $volid = $2;
5197 eval {
5198 if ($volid =~ m|^/|) {
5199 unlink $volid || die 'unlink failed\n';
5200 } else {
ed221350 5201 PVE::Storage::vdisk_free($storecfg, $volid);
3e16d5fc 5202 }
afdb31d5 5203 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
5204 };
5205 print STDERR "unable to cleanup '$volid' - $@" if $@;
5206 } else {
5207 print STDERR "unable to parse line in statfile - $line";
afdb31d5 5208 }
3e16d5fc
DM
5209 }
5210 $fd->close();
5211 }
5212}
5213
5214sub restore_archive {
a0d1b1a2 5215 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 5216
91bd6c90
DM
5217 my $format = $opts->{format};
5218 my $comp;
5219
5220 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5221 $format = 'tar' if !$format;
5222 $comp = 'gzip';
5223 } elsif ($archive =~ m/\.tar$/) {
5224 $format = 'tar' if !$format;
5225 } elsif ($archive =~ m/.tar.lzo$/) {
5226 $format = 'tar' if !$format;
5227 $comp = 'lzop';
5228 } elsif ($archive =~ m/\.vma$/) {
5229 $format = 'vma' if !$format;
5230 } elsif ($archive =~ m/\.vma\.gz$/) {
5231 $format = 'vma' if !$format;
5232 $comp = 'gzip';
5233 } elsif ($archive =~ m/\.vma\.lzo$/) {
5234 $format = 'vma' if !$format;
5235 $comp = 'lzop';
5236 } else {
5237 $format = 'vma' if !$format; # default
5238 }
5239
5240 # try to detect archive format
5241 if ($format eq 'tar') {
5242 return restore_tar_archive($archive, $vmid, $user, $opts);
5243 } else {
5244 return restore_vma_archive($archive, $vmid, $user, $opts, $comp);
5245 }
5246}
5247
5248sub restore_update_config_line {
5249 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5250
5251 return if $line =~ m/^\#qmdump\#/;
5252 return if $line =~ m/^\#vzdump\#/;
5253 return if $line =~ m/^lock:/;
5254 return if $line =~ m/^unused\d+:/;
5255 return if $line =~ m/^parent:/;
ca3e4fa4 5256 return if $line =~ m/^template:/; # restored VM is never a template
91bd6c90
DM
5257
5258 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5259 # try to convert old 1.X settings
5260 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5261 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
5262 my ($model, $macaddr) = split(/\=/, $devconfig);
5263 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $unique;
5264 my $net = {
5265 model => $model,
5266 bridge => "vmbr$ind",
5267 macaddr => $macaddr,
5268 };
5269 my $netstr = print_net($net);
5270
5271 print $outfd "net$cookie->{netcount}: $netstr\n";
5272 $cookie->{netcount}++;
5273 }
5274 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5275 my ($id, $netstr) = ($1, $2);
5276 my $net = parse_net($netstr);
5277 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
5278 $netstr = print_net($net);
5279 print $outfd "$id: $netstr\n";
5280 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5281 my $virtdev = $1;
907ea891 5282 my $value = $3;
d9faf790
WB
5283 my $di = parse_drive($virtdev, $value);
5284 if (defined($di->{backup}) && !$di->{backup}) {
91bd6c90 5285 print $outfd "#$line";
c0f7406e 5286 } elsif ($map->{$virtdev}) {
8fd57431 5287 delete $di->{format}; # format can change on restore
91bd6c90 5288 $di->{file} = $map->{$virtdev};
ed221350 5289 $value = print_drive($vmid, $di);
91bd6c90
DM
5290 print $outfd "$virtdev: $value\n";
5291 } else {
5292 print $outfd $line;
5293 }
5294 } else {
5295 print $outfd $line;
5296 }
5297}
5298
5299sub scan_volids {
5300 my ($cfg, $vmid) = @_;
5301
5302 my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
5303
5304 my $volid_hash = {};
5305 foreach my $storeid (keys %$info) {
5306 foreach my $item (@{$info->{$storeid}}) {
5307 next if !($item->{volid} && $item->{size});
5996a936 5308 $item->{path} = PVE::Storage::path($cfg, $item->{volid});
91bd6c90
DM
5309 $volid_hash->{$item->{volid}} = $item;
5310 }
5311 }
5312
5313 return $volid_hash;
5314}
5315
77019edf
WB
5316sub is_volume_in_use {
5317 my ($storecfg, $conf, $skip_drive, $volid) = @_;
a8e2f942 5318
77019edf 5319 my $path = PVE::Storage::path($storecfg, $volid);
a8e2f942
DM
5320
5321 my $scan_config = sub {
5322 my ($cref, $snapname) = @_;
5323
5324 foreach my $key (keys %$cref) {
5325 my $value = $cref->{$key};
74479ee9 5326 if (is_valid_drivename($key)) {
a8e2f942
DM
5327 next if $skip_drive && $key eq $skip_drive;
5328 my $drive = parse_drive($key, $value);
5329 next if !$drive || !$drive->{file} || drive_is_cdrom($drive);
77019edf 5330 return 1 if $volid eq $drive->{file};
a8e2f942 5331 if ($drive->{file} =~ m!^/!) {
77019edf 5332 return 1 if $drive->{file} eq $path;
a8e2f942
DM
5333 } else {
5334 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
5335 next if !$storeid;
5336 my $scfg = PVE::Storage::storage_config($storecfg, $storeid, 1);
5337 next if !$scfg;
77019edf 5338 return 1 if $path eq PVE::Storage::path($storecfg, $drive->{file}, $snapname);
a8e2f942
DM
5339 }
5340 }
5341 }
77019edf
WB
5342
5343 return 0;
a8e2f942
DM
5344 };
5345
77019edf 5346 return 1 if &$scan_config($conf);
a8e2f942
DM
5347
5348 undef $skip_drive;
5349
77019edf
WB
5350 foreach my $snapname (keys %{$conf->{snapshots}}) {
5351 return 1 if &$scan_config($conf->{snapshots}->{$snapname}, $snapname);
a8e2f942
DM
5352 }
5353
77019edf 5354 return 0;
a8e2f942
DM
5355}
5356
91bd6c90
DM
5357sub update_disksize {
5358 my ($vmid, $conf, $volid_hash) = @_;
be190583 5359
91bd6c90
DM
5360 my $changes;
5361
5362 my $used = {};
5363
5996a936
DM
5364 # Note: it is allowed to define multiple storages with same path (alias), so
5365 # we need to check both 'volid' and real 'path' (two different volid can point
5366 # to the same path).
5367
5368 my $usedpath = {};
be190583 5369
91bd6c90
DM
5370 # update size info
5371 foreach my $opt (keys %$conf) {
74479ee9 5372 if (is_valid_drivename($opt)) {
ed221350 5373 my $drive = parse_drive($opt, $conf->{$opt});
91bd6c90
DM
5374 my $volid = $drive->{file};
5375 next if !$volid;
5376
5377 $used->{$volid} = 1;
be190583 5378 if ($volid_hash->{$volid} &&
5996a936
DM
5379 (my $path = $volid_hash->{$volid}->{path})) {
5380 $usedpath->{$path} = 1;
5381 }
91bd6c90 5382
ed221350 5383 next if drive_is_cdrom($drive);
91bd6c90
DM
5384 next if !$volid_hash->{$volid};
5385
5386 $drive->{size} = $volid_hash->{$volid}->{size};
7a907ce6
DM
5387 my $new = print_drive($vmid, $drive);
5388 if ($new ne $conf->{$opt}) {
5389 $changes = 1;
5390 $conf->{$opt} = $new;
5391 }
91bd6c90
DM
5392 }
5393 }
5394
5996a936
DM
5395 # remove 'unusedX' entry if volume is used
5396 foreach my $opt (keys %$conf) {
5397 next if $opt !~ m/^unused\d+$/;
5398 my $volid = $conf->{$opt};
5399 my $path = $volid_hash->{$volid}->{path} if $volid_hash->{$volid};
be190583 5400 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5996a936
DM
5401 $changes = 1;
5402 delete $conf->{$opt};
5403 }
5404 }
5405
91bd6c90
DM
5406 foreach my $volid (sort keys %$volid_hash) {
5407 next if $volid =~ m/vm-$vmid-state-/;
5408 next if $used->{$volid};
5996a936
DM
5409 my $path = $volid_hash->{$volid}->{path};
5410 next if !$path; # just to be sure
5411 next if $usedpath->{$path};
91bd6c90 5412 $changes = 1;
8793d495 5413 PVE::QemuConfig->add_unused_volume($conf, $volid);
05937a14 5414 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
91bd6c90
DM
5415 }
5416
5417 return $changes;
5418}
5419
5420sub rescan {
5421 my ($vmid, $nolock) = @_;
5422
20519efc 5423 my $cfg = PVE::Storage::config();
91bd6c90
DM
5424
5425 my $volid_hash = scan_volids($cfg, $vmid);
5426
5427 my $updatefn = sub {
5428 my ($vmid) = @_;
5429
ffda963f 5430 my $conf = PVE::QemuConfig->load_config($vmid);
be190583 5431
ffda963f 5432 PVE::QemuConfig->check_lock($conf);
91bd6c90 5433
03da3f0d
DM
5434 my $vm_volids = {};
5435 foreach my $volid (keys %$volid_hash) {
5436 my $info = $volid_hash->{$volid};
5437 $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
5438 }
5439
5440 my $changes = update_disksize($vmid, $conf, $vm_volids);
91bd6c90 5441
ffda963f 5442 PVE::QemuConfig->write_config($vmid, $conf) if $changes;
91bd6c90
DM
5443 };
5444
5445 if (defined($vmid)) {
5446 if ($nolock) {
5447 &$updatefn($vmid);
5448 } else {
ffda963f 5449 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
91bd6c90
DM
5450 }
5451 } else {
5452 my $vmlist = config_list();
5453 foreach my $vmid (keys %$vmlist) {
5454 if ($nolock) {
5455 &$updatefn($vmid);
5456 } else {
ffda963f 5457 PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
be190583 5458 }
91bd6c90
DM
5459 }
5460 }
5461}
5462
5463sub restore_vma_archive {
5464 my ($archive, $vmid, $user, $opts, $comp) = @_;
5465
5466 my $input = $archive eq '-' ? "<&STDIN" : undef;
5467 my $readfrom = $archive;
5468
5469 my $uncomp = '';
5470 if ($comp) {
5471 $readfrom = '-';
5472 my $qarchive = PVE::Tools::shellquote($archive);
5473 if ($comp eq 'gzip') {
5474 $uncomp = "zcat $qarchive|";
5475 } elsif ($comp eq 'lzop') {
5476 $uncomp = "lzop -d -c $qarchive|";
5477 } else {
5478 die "unknown compression method '$comp'\n";
5479 }
be190583 5480
91bd6c90
DM
5481 }
5482
5483 my $tmpdir = "/var/tmp/vzdumptmp$$";
5484 rmtree $tmpdir;
5485
5486 # disable interrupts (always do cleanups)
5487 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
5488 warn "got interrupt - ignored\n";
5489 };
5490
5491 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5492 POSIX::mkfifo($mapfifo, 0600);
5493 my $fifofh;
5494
5495 my $openfifo = sub {
5496 open($fifofh, '>', $mapfifo) || die $!;
5497 };
5498
5499 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5500
5501 my $oldtimeout;
5502 my $timeout = 5;
5503
5504 my $devinfo = {};
5505
5506 my $rpcenv = PVE::RPCEnvironment::get();
5507
ffda963f 5508 my $conffile = PVE::QemuConfig->config_file($vmid);
91bd6c90
DM
5509 my $tmpfn = "$conffile.$$.tmp";
5510
ed221350 5511 # Note: $oldconf is undef if VM does not exists
ffda963f
FG
5512 my $cfs_path = PVE::QemuConfig->cfs_config_path($vmid);
5513 my $oldconf = PVE::Cluster::cfs_read_file($cfs_path);
ed221350 5514
91bd6c90
DM
5515 my $print_devmap = sub {
5516 my $virtdev_hash = {};
5517
5518 my $cfgfn = "$tmpdir/qemu-server.conf";
5519
5520 # we can read the config - that is already extracted
5521 my $fh = IO::File->new($cfgfn, "r") ||
5522 "unable to read qemu-server.conf - $!\n";
5523
6738ab9c 5524 my $fwcfgfn = "$tmpdir/qemu-server.fw";
3457d090
WL
5525 if (-f $fwcfgfn) {
5526 my $pve_firewall_dir = '/etc/pve/firewall';
5527 mkdir $pve_firewall_dir; # make sure the dir exists
5528 PVE::Tools::file_copy($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5529 }
6738ab9c 5530
91bd6c90
DM
5531 while (defined(my $line = <$fh>)) {
5532 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5533 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5534 die "archive does not contain data for drive '$virtdev'\n"
5535 if !$devinfo->{$devname};
5536 if (defined($opts->{storage})) {
5537 $storeid = $opts->{storage} || 'local';
5538 } elsif (!$storeid) {
5539 $storeid = 'local';
5540 }
5541 $format = 'raw' if !$format;
5542 $devinfo->{$devname}->{devname} = $devname;
5543 $devinfo->{$devname}->{virtdev} = $virtdev;
5544 $devinfo->{$devname}->{format} = $format;
5545 $devinfo->{$devname}->{storeid} = $storeid;
5546
be190583 5547 # check permission on storage
91bd6c90
DM
5548 my $pool = $opts->{pool}; # todo: do we need that?
5549 if ($user ne 'root@pam') {
5550 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5551 }
5552
5553 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5554 }
5555 }
5556
5557 foreach my $devname (keys %$devinfo) {
be190583
DM
5558 die "found no device mapping information for device '$devname'\n"
5559 if !$devinfo->{$devname}->{virtdev};
91bd6c90
DM
5560 }
5561
20519efc 5562 my $cfg = PVE::Storage::config();
ed221350
DM
5563
5564 # create empty/temp config
be190583 5565 if ($oldconf) {
ed221350
DM
5566 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
5567 foreach_drive($oldconf, sub {
5568 my ($ds, $drive) = @_;
5569
5570 return if drive_is_cdrom($drive);
5571
5572 my $volid = $drive->{file};
5573
5574 return if !$volid || $volid =~ m|^/|;
5575
5576 my ($path, $owner) = PVE::Storage::path($cfg, $volid);
5577 return if !$path || !$owner || ($owner != $vmid);
5578
5579 # Note: only delete disk we want to restore
5580 # other volumes will become unused
5581 if ($virtdev_hash->{$ds}) {
5582 PVE::Storage::vdisk_free($cfg, $volid);
5583 }
5584 });
381b8fae
DC
5585
5586 # delete vmstate files
5587 # since after the restore we have no snapshots anymore
5588 foreach my $snapname (keys %{$oldconf->{snapshots}}) {
5589 my $snap = $oldconf->{snapshots}->{$snapname};
5590 if ($snap->{vmstate}) {
5591 eval { PVE::Storage::vdisk_free($cfg, $snap->{vmstate}); };
5592 if (my $err = $@) {
5593 warn $err;
5594 }
5595 }
5596 }
ed221350
DM
5597 }
5598
5599 my $map = {};
91bd6c90
DM
5600 foreach my $virtdev (sort keys %$virtdev_hash) {
5601 my $d = $virtdev_hash->{$virtdev};
5602 my $alloc_size = int(($d->{size} + 1024 - 1)/1024);
5603 my $scfg = PVE::Storage::storage_config($cfg, $d->{storeid});
8fd57431
DM
5604
5605 # test if requested format is supported
5606 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($cfg, $d->{storeid});
5607 my $supported = grep { $_ eq $d->{format} } @$validFormats;
5608 $d->{format} = $defFormat if !$supported;
5609
91bd6c90
DM
5610 my $volid = PVE::Storage::vdisk_alloc($cfg, $d->{storeid}, $vmid,
5611 $d->{format}, undef, $alloc_size);
5612 print STDERR "new volume ID is '$volid'\n";
5613 $d->{volid} = $volid;
5614 my $path = PVE::Storage::path($cfg, $volid);
5615
5f96f4df
WL
5616 PVE::Storage::activate_volumes($cfg,[$volid]);
5617
91bd6c90 5618 my $write_zeros = 1;
88240a83 5619 if (PVE::Storage::volume_has_feature($cfg, 'sparseinit', $volid)) {
91bd6c90
DM
5620 $write_zeros = 0;
5621 }
5622
3c525055 5623 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
91bd6c90
DM
5624
5625 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5626 $map->{$virtdev} = $volid;
5627 }
5628
5629 $fh->seek(0, 0) || die "seek failed - $!\n";
5630
5631 my $outfd = new IO::File ($tmpfn, "w") ||
5632 die "unable to write config for VM $vmid\n";
5633
5634 my $cookie = { netcount => 0 };
5635 while (defined(my $line = <$fh>)) {
be190583 5636 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
91bd6c90
DM
5637 }
5638
5639 $fh->close();
5640 $outfd->close();
5641 };
5642
5643 eval {
5644 # enable interrupts
5645 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
5646 die "interrupted by signal\n";
5647 };
5648 local $SIG{ALRM} = sub { die "got timeout\n"; };
5649
5650 $oldtimeout = alarm($timeout);
5651
5652 my $parser = sub {
5653 my $line = shift;
5654
5655 print "$line\n";
5656
5657 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5658 my ($dev_id, $size, $devname) = ($1, $2, $3);
5659 $devinfo->{$devname} = { size => $size, dev_id => $dev_id };
5660 } elsif ($line =~ m/^CTIME: /) {
46f58b5f 5661 # we correctly received the vma config, so we can disable
3cf90d7a
DM
5662 # the timeout now for disk allocation (set to 10 minutes, so
5663 # that we always timeout if something goes wrong)
5664 alarm(600);
91bd6c90
DM
5665 &$print_devmap();
5666 print $fifofh "done\n";
5667 my $tmp = $oldtimeout || 0;
5668 $oldtimeout = undef;
5669 alarm($tmp);
5670 close($fifofh);
5671 }
5672 };
be190583 5673
91bd6c90
DM
5674 print "restore vma archive: $cmd\n";
5675 run_command($cmd, input => $input, outfunc => $parser, afterfork => $openfifo);
5676 };
5677 my $err = $@;
5678
5679 alarm($oldtimeout) if $oldtimeout;
5680
5f96f4df
WL
5681 my $vollist = [];
5682 foreach my $devname (keys %$devinfo) {
5683 my $volid = $devinfo->{$devname}->{volid};
5684 push @$vollist, $volid if $volid;
5685 }
5686
20519efc 5687 my $cfg = PVE::Storage::config();
5f96f4df
WL
5688 PVE::Storage::deactivate_volumes($cfg, $vollist);
5689
91bd6c90
DM
5690 unlink $mapfifo;
5691
5692 if ($err) {
5693 rmtree $tmpdir;
5694 unlink $tmpfn;
5695
91bd6c90
DM
5696 foreach my $devname (keys %$devinfo) {
5697 my $volid = $devinfo->{$devname}->{volid};
5698 next if !$volid;
5699 eval {
5700 if ($volid =~ m|^/|) {
5701 unlink $volid || die 'unlink failed\n';
5702 } else {
5703 PVE::Storage::vdisk_free($cfg, $volid);
5704 }
5705 print STDERR "temporary volume '$volid' sucessfuly removed\n";
5706 };
5707 print STDERR "unable to cleanup '$volid' - $@" if $@;
5708 }
5709 die $err;
5710 }
5711
5712 rmtree $tmpdir;
ed221350
DM
5713
5714 rename($tmpfn, $conffile) ||
91bd6c90
DM
5715 die "unable to commit configuration file '$conffile'\n";
5716
ed221350
DM
5717 PVE::Cluster::cfs_update(); # make sure we read new file
5718
91bd6c90
DM
5719 eval { rescan($vmid, 1); };
5720 warn $@ if $@;
5721}
5722
5723sub restore_tar_archive {
5724 my ($archive, $vmid, $user, $opts) = @_;
5725
9c502e26 5726 if ($archive ne '-') {
ed221350 5727 my $firstfile = tar_archive_read_firstfile($archive);
9c502e26
DM
5728 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5729 if $firstfile ne 'qemu-server.conf';
5730 }
3e16d5fc 5731
20519efc 5732 my $storecfg = PVE::Storage::config();
ebb55558 5733
ed221350 5734 # destroy existing data - keep empty config
ffda963f 5735 my $vmcfgfn = PVE::QemuConfig->config_file($vmid);
ebb55558 5736 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
ed221350 5737
3e16d5fc
DM
5738 my $tocmd = "/usr/lib/qemu-server/qmextract";
5739
2415a446 5740 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 5741 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
5742 $tocmd .= ' --prealloc' if $opts->{prealloc};
5743 $tocmd .= ' --info' if $opts->{info};
5744
a0d1b1a2 5745 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 5746 # so we pipe to zcat
2415a446
DM
5747 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
5748 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
5749
5750 my $tmpdir = "/var/tmp/vzdumptmp$$";
5751 mkpath $tmpdir;
5752
5753 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
5754 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 5755 local $ENV{VZDUMP_USER} = $user;
3e16d5fc 5756
ffda963f 5757 my $conffile = PVE::QemuConfig->config_file($vmid);
3e16d5fc
DM
5758 my $tmpfn = "$conffile.$$.tmp";
5759
5760 # disable interrupts (always do cleanups)
5761 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
5762 print STDERR "got interrupt - ignored\n";
5763 };
5764
afdb31d5 5765 eval {
3e16d5fc
DM
5766 # enable interrupts
5767 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
5768 die "interrupted by signal\n";
5769 };
5770
9c502e26
DM
5771 if ($archive eq '-') {
5772 print "extracting archive from STDIN\n";
5773 run_command($cmd, input => "<&STDIN");
5774 } else {
5775 print "extracting archive '$archive'\n";
5776 run_command($cmd);
5777 }
3e16d5fc
DM
5778
5779 return if $opts->{info};
5780
5781 # read new mapping
5782 my $map = {};
5783 my $statfile = "$tmpdir/qmrestore.stat";
5784 if (my $fd = IO::File->new($statfile, "r")) {
5785 while (defined (my $line = <$fd>)) {
5786 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5787 $map->{$1} = $2 if $1;
5788 } else {
5789 print STDERR "unable to parse line in statfile - $line\n";
5790 }
5791 }
5792 $fd->close();
5793 }
5794
5795 my $confsrc = "$tmpdir/qemu-server.conf";
5796
5797 my $srcfd = new IO::File($confsrc, "r") ||
5798 die "unable to open file '$confsrc'\n";
5799
5800 my $outfd = new IO::File ($tmpfn, "w") ||
5801 die "unable to write config for VM $vmid\n";
5802
91bd6c90 5803 my $cookie = { netcount => 0 };
3e16d5fc 5804 while (defined (my $line = <$srcfd>)) {
be190583 5805 restore_update_config_line($outfd, $cookie, $vmid, $map, $line, $opts->{unique});
3e16d5fc
DM
5806 }
5807
5808 $srcfd->close();
5809 $outfd->close();
5810 };
5811 my $err = $@;
5812
afdb31d5 5813 if ($err) {
3e16d5fc
DM
5814
5815 unlink $tmpfn;
5816
ed221350 5817 tar_restore_cleanup($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 5818
3e16d5fc 5819 die $err;
afdb31d5 5820 }
3e16d5fc
DM
5821
5822 rmtree $tmpdir;
5823
5824 rename $tmpfn, $conffile ||
5825 die "unable to commit configuration file '$conffile'\n";
91bd6c90 5826
ed221350
DM
5827 PVE::Cluster::cfs_update(); # make sure we read new file
5828
91bd6c90
DM
5829 eval { rescan($vmid, 1); };
5830 warn $@ if $@;
3e16d5fc
DM
5831};
5832
18bfb361
DM
5833sub foreach_writable_storage {
5834 my ($conf, $func) = @_;
5835
5836 my $sidhash = {};
5837
5838 foreach my $ds (keys %$conf) {
74479ee9 5839 next if !is_valid_drivename($ds);
18bfb361
DM
5840
5841 my $drive = parse_drive($ds, $conf->{$ds});
5842 next if !$drive;
5843 next if drive_is_cdrom($drive);
5844
5845 my $volid = $drive->{file};
5846
5847 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
be190583 5848 $sidhash->{$sid} = $sid if $sid;
18bfb361
DM
5849 }
5850
5851 foreach my $sid (sort keys %$sidhash) {
5852 &$func($sid);
5853 }
5854}
5855
e5eaa028
WL
5856sub do_snapshots_with_qemu {
5857 my ($storecfg, $volid) = @_;
5858
5859 my $storage_name = PVE::Storage::parse_volume_id($volid);
5860
116da784
WL
5861 if ($qemu_snap_storage->{$storecfg->{ids}->{$storage_name}->{type}}
5862 && !$storecfg->{ids}->{$storage_name}->{krbd}){
e5eaa028
WL
5863 return 1;
5864 }
5865
5866 if ($volid =~ m/\.(qcow2|qed)$/){
5867 return 1;
5868 }
5869
5870 return undef;
5871}
5872
4dcc780c
WL
5873sub qga_check_running {
5874 my ($vmid) = @_;
5875
5876 eval { vm_mon_cmd($vmid, "guest-ping", timeout => 3); };
5877 if ($@) {
5878 warn "Qemu Guest Agent are not running - $@";
5879 return 0;
5880 }
5881 return 1;
5882}
5883
04a69bb4
AD
5884sub template_create {
5885 my ($vmid, $conf, $disk) = @_;
5886
04a69bb4 5887 my $storecfg = PVE::Storage::config();
04a69bb4 5888
9cd07842
DM
5889 foreach_drive($conf, sub {
5890 my ($ds, $drive) = @_;
5891
5892 return if drive_is_cdrom($drive);
5893 return if $disk && $ds ne $disk;
5894
5895 my $volid = $drive->{file};
bbd56097 5896 return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
9cd07842 5897
04a69bb4
AD
5898 my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
5899 $drive->{file} = $voliddst;
152fe752 5900 $conf->{$ds} = print_drive($vmid, $drive);
ffda963f 5901 PVE::QemuConfig->write_config($vmid, $conf);
04a69bb4 5902 });
04a69bb4
AD
5903}
5904
5133de42 5905sub qemu_img_convert {
988e2714 5906 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5133de42
AD
5907
5908 my $storecfg = PVE::Storage::config();
5909 my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
5910 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
5911
5912 if ($src_storeid && $dst_storeid) {
6bb91c17
DM
5913
5914 PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
5915
5133de42
AD
5916 my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
5917 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
5918
5919 my $src_format = qemu_img_format($src_scfg, $src_volname);
5920 my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
5921
5922 my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
5923 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
5924
5925 my $cmd = [];
71ddbff9 5926 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5133de42 5927 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
988e2714
WB
5928 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5929 if ($is_zero_initialized) {
5930 push @$cmd, "zeroinit:$dst_path";
5931 } else {
5932 push @$cmd, $dst_path;
5933 }
5133de42
AD
5934
5935 my $parser = sub {
5936 my $line = shift;
5937 if($line =~ m/\((\S+)\/100\%\)/){
5938 my $percent = $1;
5939 my $transferred = int($size * $percent / 100);
5940 my $remaining = $size - $transferred;
5941
5942 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5943 }
5944
5945 };
5946
5947 eval { run_command($cmd, timeout => undef, outfunc => $parser); };
5948 my $err = $@;
5949 die "copy failed: $err" if $err;
5950 }
5951}
5952
5953sub qemu_img_format {
5954 my ($scfg, $volname) = @_;
5955
d81f0f09 5956 if ($scfg->{path} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5133de42 5957 return $1;
be190583 5958 } else {
5133de42 5959 return "raw";
5133de42
AD
5960 }
5961}
5962
cfad42af 5963sub qemu_drive_mirror {
988e2714 5964 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
cfad42af 5965
cfad42af 5966 my $storecfg = PVE::Storage::config();
08ac653f 5967 my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid);
152fe752 5968
08ac653f 5969 my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
cfad42af 5970
d81f0f09 5971 my $format = qemu_img_format($dst_scfg, $dst_volname);
21ccdb50 5972
08ac653f 5973 my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
21ccdb50 5974
988e2714
WB
5975 my $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
5976
5977 my $opts = { timeout => 10, device => "drive-$drive", mode => "existing", sync => "full", target => $qemu_target };
88383920
DM
5978 $opts->{format} = $format if $format;
5979
22967505 5980 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
21ccdb50 5981
2e953867
WB
5982 my $finish_job = sub {
5983 while (1) {
5984 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
5985 my $stat = @$stats[0];
5986 last if !$stat;
5987 sleep 1;
5988 }
5989 };
5990
08ac653f 5991 eval {
22967505 5992 vm_mon_cmd($vmid, "drive-mirror", %$opts);
08ac653f
DM
5993 while (1) {
5994 my $stats = vm_mon_cmd($vmid, "query-block-jobs");
5995 my $stat = @$stats[0];
5996 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5997 die "error job is not mirroring" if $stat->{type} ne "mirror";
5998
08ac653f 5999 my $busy = $stat->{busy};
ad123d97 6000 my $ready = $stat->{ready};
08ac653f 6001
6f708643
DM
6002 if (my $total = $stat->{len}) {
6003 my $transferred = $stat->{offset} || 0;
6004 my $remaining = $total - $transferred;
6005 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
67fb9de6 6006
ad123d97 6007 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6f708643 6008 }
f34ebd52 6009
08ac653f 6010
ad123d97 6011 if ($stat->{ready} eq 'true') {
f34ebd52 6012
ad123d97 6013 last if $vmiddst != $vmid;
b467f79a 6014
ad123d97
AD
6015 # try to switch the disk if source and destination are on the same guest
6016 eval { vm_mon_cmd($vmid, "block-job-complete", device => "drive-$drive") };
2e953867
WB
6017 if (!$@) {
6018 &$finish_job();
6019 last;
6020 }
ad123d97 6021 die $@ if $@ !~ m/cannot be completed/;
08ac653f 6022 }
08ac653f 6023 sleep 1;
cfad42af
AD
6024 }
6025
08ac653f
DM
6026
6027 };
88383920 6028 my $err = $@;
08ac653f 6029
88383920 6030 my $cancel_job = sub {
08ac653f 6031 vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$drive");
2e953867 6032 &$finish_job();
88383920
DM
6033 };
6034
6035 if ($err) {
f34ebd52 6036 eval { &$cancel_job(); };
88383920
DM
6037 die "mirroring error: $err";
6038 }
6039
6040 if ($vmiddst != $vmid) {
6041 # if we clone a disk for a new target vm, we don't switch the disk
6042 &$cancel_job(); # so we call block-job-cancel
cfad42af
AD
6043 }
6044}
6045
152fe752 6046sub clone_disk {
be190583 6047 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
152fe752
DM
6048 $newvmid, $storage, $format, $full, $newvollist) = @_;
6049
6050 my $newvolid;
6051
6052 if (!$full) {
6053 print "create linked clone of drive $drivename ($drive->{file})\n";
258e646c 6054 $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid, $snapname);
152fe752
DM
6055 push @$newvollist, $newvolid;
6056 } else {
6057 my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});
6058 $storeid = $storage if $storage;
6059
1377d7b0
DM
6060 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
6061 if (!$format) {
d81f0f09
DM
6062 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
6063 $format = qemu_img_format($scfg, $volname);
152fe752
DM
6064 }
6065
1377d7b0
DM
6066 # test if requested format is supported - else use default
6067 my $supported = grep { $_ eq $format } @$validFormats;
6068 $format = $defFormat if !$supported;
6069
152fe752
DM
6070 my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3);
6071
6072 print "create full clone of drive $drivename ($drive->{file})\n";
6073 $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6074 push @$newvollist, $newvolid;
6075
1dbd6d30
WL
6076 PVE::Storage::activate_volumes($storecfg, $newvollist);
6077
988e2714 6078 my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
152fe752 6079 if (!$running || $snapname) {
988e2714 6080 qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit);
152fe752 6081 } else {
988e2714 6082 qemu_drive_mirror($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
be190583 6083 }
152fe752
DM
6084 }
6085
6086 my ($size) = PVE::Storage::volume_size_info($storecfg, $newvolid, 3);
6087
6088 my $disk = $drive;
6089 $disk->{format} = undef;
6090 $disk->{file} = $newvolid;
6091 $disk->{size} = $size;
6092
6093 return $disk;
6094}
6095
ff556cf2
DM
6096# this only works if VM is running
6097sub get_current_qemu_machine {
6098 my ($vmid) = @_;
6099
6100 my $cmd = { execute => 'query-machines', arguments => {} };
8e90138a 6101 my $res = vm_qmp_command($vmid, $cmd);
ff556cf2
DM
6102
6103 my ($current, $default);
6104 foreach my $e (@$res) {
6105 $default = $e->{name} if $e->{'is-default'};
6106 $current = $e->{name} if $e->{'is-current'};
6107 }
6108
6109 # fallback to the default machine if current is not supported by qemu
6110 return $current || $default || 'pc';
6111}
6112
23f73120
AD
6113sub qemu_machine_feature_enabled {
6114 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6115
6116 my $current_major;
6117 my $current_minor;
6118
6119 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6120
6121 $current_major = $3;
6122 $current_minor = $4;
6123
6124 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6125
6126 $current_major = $1;
6127 $current_minor = $2;
6128 }
6129
6130 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6131
6132
6133}
6134
42dbd2ee
AD
6135sub qemu_machine_pxe {
6136 my ($vmid, $conf, $machine) = @_;
6137
6138 $machine = PVE::QemuServer::get_current_qemu_machine($vmid) if !$machine;
6139
6140 foreach my $opt (keys %$conf) {
6141 next if $opt !~ m/^net(\d+)$/;
6142 my $net = PVE::QemuServer::parse_net($conf->{$opt});
6143 next if !$net;
6144 my $romfile = PVE::QemuServer::vm_mon_cmd_nocheck($vmid, 'qom-get', path => $opt, property => 'romfile');
6145 return $machine.".pxe" if $romfile =~ m/pxe/;
6146 last;
6147 }
6148
d1363934 6149 return $machine;
42dbd2ee
AD
6150}
6151
249c4a6c
AD
6152sub qemu_use_old_bios_files {
6153 my ($machine_type) = @_;
6154
6155 return if !$machine_type;
6156
6157 my $use_old_bios_files = undef;
6158
6159 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6160 $machine_type = $1;
6161 $use_old_bios_files = 1;
6162 } else {
74cc511f 6163 my $kvmver = kvm_user_version();
249c4a6c
AD
6164 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6165 # load new efi bios files on migration. So this hack is required to allow
6166 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6167 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
74cc511f 6168 $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 4);
249c4a6c
AD
6169 }
6170
6171 return ($use_old_bios_files, $machine_type);
6172}
6173
4543ecf0
AD
6174sub lspci {
6175
6176 my $devices = {};
6177
6178 dir_glob_foreach("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6179 my (undef, $id, $function) = @_;
6180 my $res = { id => $id, function => $function};
6181 push @{$devices->{$id}}, $res;
6182 });
6183
6184 return $devices;
6185}
6186
22de899a
AD
6187sub vm_iothreads_list {
6188 my ($vmid) = @_;
6189
6190 my $res = vm_mon_cmd($vmid, 'query-iothreads');
6191
6192 my $iothreads = {};
6193 foreach my $iothread (@$res) {
6194 $iothreads->{ $iothread->{id} } = $iothread->{"thread-id"};
6195 }
6196
6197 return $iothreads;
6198}
6199
ee034f5c
AD
6200sub scsihw_infos {
6201 my ($conf, $drive) = @_;
6202
6203 my $maxdev = 0;
6204
6205 if ($conf->{scsihw} && ($conf->{scsihw} =~ m/^lsi/)) {
6206 $maxdev = 7;
a1511b3c 6207 } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
ee034f5c
AD
6208 $maxdev = 1;
6209 } else {
6210 $maxdev = 256;
6211 }
6212
6213 my $controller = int($drive->{index} / $maxdev);
a1511b3c 6214 my $controller_prefix = ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') ? "virtioscsi" : "scsihw";
ee034f5c
AD
6215
6216 return ($maxdev, $controller, $controller_prefix);
6217}
a1511b3c 6218
65e866e5
DM
6219# bash completion helper
6220
6221sub complete_backup_archives {
6222 my ($cmdname, $pname, $cvalue) = @_;
6223
6224 my $cfg = PVE::Storage::config();
6225
6226 my $storeid;
6227
6228 if ($cvalue =~ m/^([^:]+):/) {
6229 $storeid = $1;
6230 }
6231
6232 my $data = PVE::Storage::template_list($cfg, $storeid, 'backup');
6233
6234 my $res = [];
6235 foreach my $id (keys %$data) {
6236 foreach my $item (@{$data->{$id}}) {
6237 next if $item->{format} !~ m/^vma\.(gz|lzo)$/;
6238 push @$res, $item->{volid} if defined($item->{volid});
6239 }
6240 }
6241
6242 return $res;
6243}
6244
6245my $complete_vmid_full = sub {
6246 my ($running) = @_;
6247
6248 my $idlist = vmstatus();
6249
6250 my $res = [];
6251
6252 foreach my $id (keys %$idlist) {
6253 my $d = $idlist->{$id};
6254 if (defined($running)) {
6255 next if $d->{template};
6256 next if $running && $d->{status} ne 'running';
6257 next if !$running && $d->{status} eq 'running';
6258 }
6259 push @$res, $id;
6260
6261 }
6262 return $res;
6263};
6264
6265sub complete_vmid {
6266 return &$complete_vmid_full();
6267}
6268
6269sub complete_vmid_stopped {
6270 return &$complete_vmid_full(0);
6271}
6272
6273sub complete_vmid_running {
6274 return &$complete_vmid_full(1);
6275}
6276
335af808
DM
6277sub complete_storage {
6278
6279 my $cfg = PVE::Storage::config();
6280 my $ids = $cfg->{ids};
6281
6282 my $res = [];
6283 foreach my $sid (keys %$ids) {
6284 next if !PVE::Storage::storage_check_enabled($cfg, $sid, undef, 1);
c4c844ef 6285 next if !$ids->{$sid}->{content}->{images};
335af808
DM
6286 push @$res, $sid;
6287 }
6288
6289 return $res;
6290}
6291
1e3baf05 62921;