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