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