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