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