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