]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
new option for vmstatus to query $full informations from KVM using qmp
[qemu-server.git] / PVE / QemuServer.pm
CommitLineData
1e3baf05
DM
1package PVE::QemuServer;
2
3use strict;
4use POSIX;
5use IO::Handle;
6use IO::Select;
7use IO::File;
8use IO::Dir;
9use IO::Socket::UNIX;
10use File::Basename;
11use File::Path;
12use File::stat;
13use Getopt::Long;
fc1ddcdc 14use Digest::SHA;
1e3baf05
DM
15use Fcntl ':flock';
16use Cwd 'abs_path';
17use IPC::Open3;
c971c4f2 18use JSON;
1e3baf05
DM
19use Fcntl;
20use PVE::SafeSyslog;
21use Storable qw(dclone);
22use PVE::Exception qw(raise raise_param_exc);
23use PVE::Storage;
24use PVE::Tools qw(run_command lock_file file_read_firstline);
25use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
26use PVE::INotify;
27use PVE::ProcFSTools;
26f11676 28use PVE::QMPClient;
6b64503e 29use Time::HiRes qw(gettimeofday);
1e3baf05 30
7f0b5beb 31my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
1e3baf05 32
19672434 33# Note about locking: we use flock on the config file protect
1e3baf05
DM
34# against concurent actions.
35# Aditionaly, we have a 'lock' setting in the config file. This
36# can be set to 'migrate' or 'backup'. Most actions are not
37# allowed when such lock is set. But you can ignore this kind of
38# lock with the --skiplock flag.
39
97d62eb7 40cfs_register_file('/qemu-server/',
1858638f
DM
41 \&parse_vm_config,
42 \&write_vm_config);
1e3baf05 43
3ea94c60
DM
44PVE::JSONSchema::register_standard_option('skiplock', {
45 description => "Ignore locks - only root is allowed to use this option.",
afdb31d5 46 type => 'boolean',
3ea94c60
DM
47 optional => 1,
48});
49
50PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
51 description => "Some command save/restore state from this location.",
52 type => 'string',
53 maxLength => 128,
54 optional => 1,
55});
56
1e3baf05
DM
57#no warnings 'redefine';
58
59unless(defined(&_VZSYSCALLS_H_)) {
60 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_);
61 require 'sys/syscall.ph';
62 if(defined(&__x86_64__)) {
63 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus);
64 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod);
65 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod);
66 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt);
67 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr);
68 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate);
69 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid);
70 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit);
71 }
72 elsif(defined( &__i386__) ) {
73 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod);
74 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod);
75 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt);
76 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr);
77 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate);
78 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus);
79 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid);
80 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit);
81 } else {
82 die("no fairsched syscall for this arch");
83 }
84 require 'asm/ioctl.ph';
85 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION);
86}
87
88sub fairsched_mknod {
89 my ($parent, $weight, $desired) = @_;
90
6b64503e 91 return syscall(&__NR_fairsched_mknod, int($parent), int($weight), int($desired));
1e3baf05
DM
92}
93
94sub fairsched_rmnod {
95 my ($id) = @_;
96
6b64503e 97 return syscall(&__NR_fairsched_rmnod, int($id));
1e3baf05
DM
98}
99
100sub fairsched_mvpr {
101 my ($pid, $newid) = @_;
102
6b64503e 103 return syscall(&__NR_fairsched_mvpr, int($pid), int($newid));
1e3baf05
DM
104}
105
106sub fairsched_vcpus {
107 my ($id, $vcpus) = @_;
108
6b64503e 109 return syscall(&__NR_fairsched_vcpus, int($id), int($vcpus));
1e3baf05
DM
110}
111
112sub fairsched_rate {
113 my ($id, $op, $rate) = @_;
114
6b64503e 115 return syscall(&__NR_fairsched_rate, int($id), int($op), int($rate));
1e3baf05
DM
116}
117
118use constant FAIRSCHED_SET_RATE => 0;
119use constant FAIRSCHED_DROP_RATE => 1;
120use constant FAIRSCHED_GET_RATE => 2;
121
122sub fairsched_cpulimit {
123 my ($id, $limit) = @_;
124
6b64503e 125 my $cpulim1024 = int($limit * 1024 / 100);
1e3baf05
DM
126 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
127
6b64503e 128 return fairsched_rate($id, $op, $cpulim1024);
1e3baf05
DM
129}
130
131my $nodename = PVE::INotify::nodename();
132
133mkdir "/etc/pve/nodes/$nodename";
134my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
135mkdir $confdir;
136
137my $var_run_tmpdir = "/var/run/qemu-server";
138mkdir $var_run_tmpdir;
139
140my $lock_dir = "/var/lock/qemu-server";
141mkdir $lock_dir;
142
143my $pcisysfs = "/sys/bus/pci";
144
1e3baf05
DM
145my $confdesc = {
146 onboot => {
147 optional => 1,
148 type => 'boolean',
149 description => "Specifies whether a VM will be started during system bootup.",
150 default => 0,
151 },
152 autostart => {
153 optional => 1,
154 type => 'boolean',
155 description => "Automatic restart after crash (currently ignored).",
156 default => 0,
157 },
2ff09f52
DA
158 hotplug => {
159 optional => 1,
e8b9c17c 160 type => 'boolean',
2ff09f52
DA
161 description => "Activate hotplug for disk and network device",
162 default => 0,
163 },
1e3baf05
DM
164 reboot => {
165 optional => 1,
166 type => 'boolean',
167 description => "Allow reboot. If set to '0' the VM exit on reboot.",
168 default => 1,
169 },
170 lock => {
171 optional => 1,
172 type => 'string',
173 description => "Lock/unlock the VM.",
174 enum => [qw(migrate backup)],
175 },
176 cpulimit => {
177 optional => 1,
178 type => 'integer',
179 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.",
180 minimum => 0,
181 default => 0,
182 },
183 cpuunits => {
184 optional => 1,
185 type => 'integer',
186 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.",
187 minimum => 0,
188 maximum => 500000,
189 default => 1000,
190 },
191 memory => {
192 optional => 1,
193 type => 'integer',
7878afeb 194 description => "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
1e3baf05
DM
195 minimum => 16,
196 default => 512,
197 },
13a48620
DA
198 balloon => {
199 optional => 1,
200 type => 'integer',
201 description => "Amount of target RAM for the VM in MB.",
7878afeb 202 minimum => 16,
13a48620 203 },
1e3baf05
DM
204 keyboard => {
205 optional => 1,
206 type => 'string',
207 description => "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
e95fe75f 208 enum => PVE::Tools::kvmkeymaplist(),
1e3baf05
DM
209 default => 'en-us',
210 },
211 name => {
212 optional => 1,
7fabe17d 213 type => 'string', format => 'dns-name',
1e3baf05
DM
214 description => "Set a name for the VM. Only used on the configuration web interface.",
215 },
216 description => {
217 optional => 1,
218 type => 'string',
0581fe4f 219 description => "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
1e3baf05
DM
220 },
221 ostype => {
222 optional => 1,
223 type => 'string',
224 enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26)],
225 description => <<EODESC,
226Used to enable special optimization/features for specific
227operating systems:
228
229other => unspecified OS
230wxp => Microsoft Windows XP
231w2k => Microsoft Windows 2000
232w2k3 => Microsoft Windows 2003
233w2k8 => Microsoft Windows 2008
234wvista => Microsoft Windows Vista
235win7 => Microsoft Windows 7
236l24 => Linux 2.4 Kernel
237l26 => Linux 2.6/3.X Kernel
238
239other|l24|l26 ... no special behaviour
240wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
241EODESC
242 },
243 boot => {
244 optional => 1,
245 type => 'string',
246 description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
247 pattern => '[acdn]{1,4}',
32baffb4 248 default => 'cdn',
1e3baf05
DM
249 },
250 bootdisk => {
251 optional => 1,
252 type => 'string', format => 'pve-qm-bootdisk',
253 description => "Enable booting from specified disk.",
254 pattern => '(ide|scsi|virtio)\d+',
255 },
256 smp => {
257 optional => 1,
258 type => 'integer',
259 description => "The number of CPUs. Please use option -sockets instead.",
260 minimum => 1,
261 default => 1,
262 },
263 sockets => {
264 optional => 1,
265 type => 'integer',
266 description => "The number of CPU sockets.",
267 minimum => 1,
268 default => 1,
269 },
270 cores => {
271 optional => 1,
272 type => 'integer',
273 description => "The number of cores per socket.",
274 minimum => 1,
275 default => 1,
276 },
277 acpi => {
278 optional => 1,
279 type => 'boolean',
280 description => "Enable/disable ACPI.",
281 default => 1,
282 },
283 kvm => {
284 optional => 1,
285 type => 'boolean',
286 description => "Enable/disable KVM hardware virtualization.",
287 default => 1,
288 },
289 tdf => {
290 optional => 1,
291 type => 'boolean',
da21653b 292 description => "Enable/disable time drift fix. This is ignored for kvm versions newer that 1.0 (not needed anymore).",
1e3baf05
DM
293 default => 1,
294 },
19672434 295 localtime => {
1e3baf05
DM
296 optional => 1,
297 type => 'boolean',
298 description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
299 },
300 freeze => {
301 optional => 1,
302 type => 'boolean',
303 description => "Freeze CPU at startup (use 'c' monitor command to start execution).",
304 },
305 vga => {
306 optional => 1,
307 type => 'string',
308 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 win7/w2k8, and 'cirrur' for other OS types",
309 enum => [qw(std cirrus vmware)],
310 },
0ea9541d
DM
311 watchdog => {
312 optional => 1,
313 type => 'string', format => 'pve-qm-watchdog',
314 typetext => '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
315 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)",
316 },
1e3baf05
DM
317 startdate => {
318 optional => 1,
19672434 319 type => 'string',
1e3baf05
DM
320 typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
321 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'.",
322 pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
323 default => 'now',
324 },
59411c4e
DM
325 startup => {
326 optional => 1,
327 type => 'string', format => 'pve-qm-startup',
328 typetext => '[[order=]\d+] [,up=\d+] [,down=\d+] ',
329 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.",
330 },
1e3baf05
DM
331 args => {
332 optional => 1,
333 type => 'string',
334 description => <<EODESCR,
335Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
336
337args: -no-reboot -no-hpet
338EODESCR
339 },
340 tablet => {
341 optional => 1,
342 type => 'boolean',
343 default => 1,
344 description => "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. 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.",
345 },
346 migrate_speed => {
347 optional => 1,
348 type => 'integer',
349 description => "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
350 minimum => 0,
351 default => 0,
352 },
353 migrate_downtime => {
354 optional => 1,
355 type => 'integer',
356 description => "Set maximum tolerated downtime (in seconds) for migrations.",
357 minimum => 0,
358 default => 1,
359 },
360 cdrom => {
361 optional => 1,
362 type => 'string', format => 'pve-qm-drive',
363 typetext => 'volume',
364 description => "This is an alias for option -ide2",
365 },
366 cpu => {
367 optional => 1,
368 description => "Emulated CPU type.",
369 type => 'string',
5b805e50 370 enum => [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom cpu64-rhel6 cpu64-rhel5 Conroe Penryn Nehalem Westmere Opteron_G1 Opteron_G2 Opteron_G3 host) ],
1e3baf05
DM
371 default => 'qemu64',
372 },
373};
374
375# what about other qemu settings ?
376#cpu => 'string',
377#machine => 'string',
378#fda => 'file',
379#fdb => 'file',
380#mtdblock => 'file',
381#sd => 'file',
382#pflash => 'file',
383#snapshot => 'bool',
384#bootp => 'file',
385##tftp => 'dir',
386##smb => 'dir',
387#kernel => 'file',
388#append => 'string',
389#initrd => 'file',
390##soundhw => 'string',
391
392while (my ($k, $v) = each %$confdesc) {
393 PVE::JSONSchema::register_standard_option("pve-qm-$k", $v);
394}
395
396my $MAX_IDE_DISKS = 4;
f62db2a4
DA
397my $MAX_SCSI_DISKS = 14;
398my $MAX_VIRTIO_DISKS = 6;
cdb0931f 399my $MAX_SATA_DISKS = 6;
1e3baf05 400my $MAX_USB_DEVICES = 5;
f62db2a4 401my $MAX_NETS = 6;
1e3baf05 402my $MAX_UNUSED_DISKS = 8;
040b06b7 403my $MAX_HOSTPCI_DEVICES = 2;
bae179aa 404my $MAX_SERIAL_PORTS = 4;
1989a89c 405my $MAX_PARALLEL_PORTS = 3;
1e3baf05
DM
406
407my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
408 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
6b64503e 409my $nic_model_list_txt = join(' ', sort @$nic_model_list);
1e3baf05
DM
410
411# fixme:
412my $netdesc = {
413 optional => 1,
414 type => 'string', format => 'pve-qm-net',
5070f384 415 typetext => "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
1e3baf05 416 description => <<EODESCR,
19672434 417Specify network devices.
1e3baf05
DM
418
419MODEL is one of: $nic_model_list_txt
420
19672434 421XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
1e3baf05
DM
422automatically generated if not specified.
423
424The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
425
426Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
427
428If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
429
43010.0.2.2 Gateway
43110.0.2.3 DNS Server
43210.0.2.4 SMB Server
433
434The DHCP server assign addresses to the guest starting from 10.0.2.15.
435
436EODESCR
437};
438PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
439
440for (my $i = 0; $i < $MAX_NETS; $i++) {
441 $confdesc->{"net$i"} = $netdesc;
442}
443
444my $drivename_hash;
19672434 445
1e3baf05
DM
446my $idedesc = {
447 optional => 1,
448 type => 'string', format => 'pve-qm-drive',
e482cec3 449 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]',
1e3baf05
DM
450 description => "Use volume as IDE hard disk or CD-ROM (n is 0 to 3).",
451};
452PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc);
453
454my $scsidesc = {
455 optional => 1,
456 type => 'string', format => 'pve-qm-drive',
e482cec3 457 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]',
2fe1a152 458 description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13).",
1e3baf05
DM
459};
460PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
461
cdb0931f
DA
462my $satadesc = {
463 optional => 1,
464 type => 'string', format => 'pve-qm-drive',
e482cec3 465 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]',
cdb0931f
DA
466 description => "Use volume as SATA hard disk or CD-ROM (n is 0 to 5).",
467};
468PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
469
1e3baf05
DM
470my $virtiodesc = {
471 optional => 1,
472 type => 'string', format => 'pve-qm-drive',
e482cec3 473 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]',
2fe1a152 474 description => "Use volume as VIRTIO hard disk (n is 0 to 5).",
1e3baf05
DM
475};
476PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
477
478my $usbdesc = {
479 optional => 1,
480 type => 'string', format => 'pve-qm-usb-device',
481 typetext => 'host=HOSTUSBDEVICE',
482 description => <<EODESCR,
2fe1a152 483Configure an USB device (n is 0 to 4). This can be used to
1e3baf05
DM
484pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
485
19672434 486'bus-port(.port)*' (decimal numbers) or
1e3baf05
DM
487'vendor_id:product_id' (hexadeciaml numbers)
488
19672434 489You can use the 'lsusb -t' command to list existing usb devices.
1e3baf05
DM
490
491Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
492
493EODESCR
494};
495PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc);
496
040b06b7
DA
497my $hostpcidesc = {
498 optional => 1,
499 type => 'string', format => 'pve-qm-hostpci',
500 typetext => "HOSTPCIDEVICE",
501 description => <<EODESCR,
502Map host pci devices. HOSTPCIDEVICE syntax is:
503
504'bus:dev.func' (hexadecimal numbers)
505
506You can us the 'lspci' command to list existing pci devices.
507
508Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
509
510Experimental: user reported problems with this option.
511EODESCR
512};
513PVE::JSONSchema::register_standard_option("pve-qm-hostpci", $hostpcidesc);
514
bae179aa
DA
515my $serialdesc = {
516 optional => 1,
ca0cef26 517 type => 'string',
2fe1a152 518 pattern => '/dev/ttyS\d+',
bae179aa 519 description => <<EODESCR,
19672434 520Map host serial devices (n is 0 to 3).
bae179aa
DA
521
522Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
523
524Experimental: user reported problems with this option.
525EODESCR
526};
bae179aa 527
1989a89c
DA
528my $paralleldesc= {
529 optional => 1,
ca0cef26 530 type => 'string',
2fe1a152 531 pattern => '/dev/parport\d+',
1989a89c 532 description => <<EODESCR,
19672434 533Map host parallel devices (n is 0 to 2).
1989a89c
DA
534
535Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
536
537Experimental: user reported problems with this option.
538EODESCR
539};
1989a89c
DA
540
541for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
542 $confdesc->{"parallel$i"} = $paralleldesc;
543}
544
bae179aa
DA
545for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
546 $confdesc->{"serial$i"} = $serialdesc;
547}
548
040b06b7
DA
549for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
550 $confdesc->{"hostpci$i"} = $hostpcidesc;
551}
1e3baf05
DM
552
553for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
554 $drivename_hash->{"ide$i"} = 1;
555 $confdesc->{"ide$i"} = $idedesc;
556}
557
cdb0931f
DA
558for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
559 $drivename_hash->{"sata$i"} = 1;
560 $confdesc->{"sata$i"} = $satadesc;
561}
562
1e3baf05
DM
563for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
564 $drivename_hash->{"scsi$i"} = 1;
565 $confdesc->{"scsi$i"} = $scsidesc ;
566}
567
568for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
569 $drivename_hash->{"virtio$i"} = 1;
570 $confdesc->{"virtio$i"} = $virtiodesc;
571}
572
573for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
574 $confdesc->{"usb$i"} = $usbdesc;
575}
576
577my $unuseddesc = {
578 optional => 1,
579 type => 'string', format => 'pve-volume-id',
580 description => "Reference to unused volumes.",
581};
582
583for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
584 $confdesc->{"unused$i"} = $unuseddesc;
585}
586
587my $kvm_api_version = 0;
588
589sub kvm_version {
590
591 return $kvm_api_version if $kvm_api_version;
592
6b64503e 593 my $fh = IO::File->new("</dev/kvm") ||
1e3baf05
DM
594 return 0;
595
6b64503e 596 if (my $v = $fh->ioctl(KVM_GET_API_VERSION(), 0)) {
1e3baf05
DM
597 $kvm_api_version = $v;
598 }
599
600 $fh->close();
601
602 return $kvm_api_version;
603}
604
605my $kvm_user_version;
606
607sub kvm_user_version {
608
609 return $kvm_user_version if $kvm_user_version;
610
611 $kvm_user_version = 'unknown';
612
613 my $tmp = `kvm -help 2>/dev/null`;
19672434 614
a3c52213 615 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) /) {
1e3baf05
DM
616 $kvm_user_version = $2;
617 }
618
619 return $kvm_user_version;
620
621}
622
623my $kernel_has_vhost_net = -c '/dev/vhost-net';
624
625sub disknames {
626 # order is important - used to autoselect boot disk
19672434 627 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1e3baf05 628 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
cdb0931f
DA
629 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
630 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1e3baf05
DM
631}
632
633sub valid_drivename {
634 my $dev = shift;
635
6b64503e 636 return defined($drivename_hash->{$dev});
1e3baf05
DM
637}
638
639sub option_exists {
640 my $key = shift;
641 return defined($confdesc->{$key});
19672434 642}
1e3baf05
DM
643
644sub nic_models {
645 return $nic_model_list;
646}
647
648sub os_list_description {
649
650 return {
651 other => 'Other',
652 wxp => 'Windows XP',
653 w2k => 'Windows 2000',
654 w2k3 =>, 'Windows 2003',
655 w2k8 => 'Windows 2008',
656 wvista => 'Windows Vista',
657 win7 => 'Windows 7',
658 l24 => 'Linux 2.4',
659 l26 => 'Linux 2.6',
19672434 660 };
1e3baf05
DM
661}
662
1e3baf05
DM
663sub disk_devive_info {
664 my $dev = shift;
665
666 die "unknown disk device format '$dev'" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/;
667
668 my $bus = $1;
669 my $index = $2;
670 my $maxdev = 1024;
671
672 if ($bus eq 'ide') {
673 $maxdev = 2;
674 } elsif ($bus eq 'scsi') {
f62db2a4 675 $maxdev = 7;
1e3baf05
DM
676 }
677
6b64503e 678 my $controller = int($index / $maxdev);
1e3baf05
DM
679 my $unit = $index % $maxdev;
680
681
682 return { bus => $bus, desc => uc($bus) . " $controller:$unit",
683 controller => $controller, unit => $unit, index => $index };
684
685}
686
687sub qemu_drive_name {
19672434 688 my ($dev, $media) = @_;
1e3baf05 689
6b64503e 690 my $info = disk_devive_info($dev);
1e3baf05
DM
691 my $mediastr = '';
692
693 if (($info->{bus} eq 'ide') || ($info->{bus} eq 'scsi')) {
694 $mediastr = ($media eq 'cdrom') ? "-cd" : "-hd";
19672434 695 return sprintf("%s%i%s%i", $info->{bus}, $info->{controller},
1e3baf05
DM
696 $mediastr, $info->{unit});
697 } else {
19672434 698 return sprintf("%s%i", $info->{bus}, $info->{index});
1e3baf05
DM
699 }
700}
701
702my $cdrom_path;
703
704sub get_cdrom_path {
705
706 return $cdrom_path if $cdrom_path;
707
708 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
709 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
710 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
711}
712
713sub get_iso_path {
714 my ($storecfg, $vmid, $cdrom) = @_;
715
716 if ($cdrom eq 'cdrom') {
717 return get_cdrom_path();
718 } elsif ($cdrom eq 'none') {
719 return '';
720 } elsif ($cdrom =~ m|^/|) {
721 return $cdrom;
722 } else {
6b64503e 723 return PVE::Storage::path($storecfg, $cdrom);
1e3baf05
DM
724 }
725}
726
727# try to convert old style file names to volume IDs
728sub filename_to_volume_id {
729 my ($vmid, $file, $media) = @_;
730
731 if (!($file eq 'none' || $file eq 'cdrom' ||
732 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
19672434 733
1e3baf05 734 return undef if $file =~ m|/|;
19672434 735
1e3baf05
DM
736 if ($media && $media eq 'cdrom') {
737 $file = "local:iso/$file";
738 } else {
739 $file = "local:$vmid/$file";
740 }
741 }
742
743 return $file;
744}
745
746sub verify_media_type {
747 my ($opt, $vtype, $media) = @_;
748
749 return if !$media;
750
751 my $etype;
752 if ($media eq 'disk') {
a125592c 753 $etype = 'images';
1e3baf05
DM
754 } elsif ($media eq 'cdrom') {
755 $etype = 'iso';
756 } else {
757 die "internal error";
758 }
759
760 return if ($vtype eq $etype);
19672434 761
1e3baf05
DM
762 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
763}
764
765sub cleanup_drive_path {
766 my ($opt, $storecfg, $drive) = @_;
767
768 # try to convert filesystem paths to volume IDs
769
770 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
771 ($drive->{file} !~ m|^/dev/.+|) &&
772 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
19672434 773 ($drive->{file} !~ m/^\d+$/)) {
1e3baf05
DM
774 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
775 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
776 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
777 verify_media_type($opt, $vtype, $drive->{media});
778 $drive->{file} = $volid;
779 }
780
781 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
782}
783
784sub create_conf_nolock {
785 my ($vmid, $settings) = @_;
786
6b64503e 787 my $filename = config_file($vmid);
1e3baf05
DM
788
789 die "configuration file '$filename' already exists\n" if -f $filename;
19672434 790
1e3baf05
DM
791 my $defaults = load_defaults();
792
793 $settings->{name} = "vm$vmid" if !$settings->{name};
794 $settings->{memory} = $defaults->{memory} if !$settings->{memory};
795
796 my $data = '';
797 foreach my $opt (keys %$settings) {
798 next if !$confdesc->{$opt};
799
800 my $value = $settings->{$opt};
801 next if !$value;
802
803 $data .= "$opt: $value\n";
804 }
805
806 PVE::Tools::file_set_contents($filename, $data);
807}
808
809# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
810# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
036e0e2b 811# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1e3baf05
DM
812# [,aio=native|threads]
813
814sub parse_drive {
815 my ($key, $data) = @_;
816
817 my $res = {};
19672434 818
1e3baf05
DM
819 # $key may be undefined - used to verify JSON parameters
820 if (!defined($key)) {
821 $res->{interface} = 'unknown'; # should not harm when used to verify parameters
822 $res->{index} = 0;
823 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
824 $res->{interface} = $1;
825 $res->{index} = $2;
826 } else {
827 return undef;
828 }
829
830 foreach my $p (split (/,/, $data)) {
831 next if $p =~ m/^\s*$/;
832
affd2f88 833 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|bps_rd|bps_wr|iops|iops_rd|iops_wr)=(.+)$/) {
1e3baf05
DM
834 my ($k, $v) = ($1, $2);
835
836 $k = 'file' if $k eq 'volume';
837
838 return undef if defined $res->{$k};
19672434 839
1e3baf05
DM
840 $res->{$k} = $v;
841 } else {
842 if (!$res->{file} && $p !~ m/=/) {
843 $res->{file} = $p;
844 } else {
845 return undef;
846 }
847 }
848 }
849
850 return undef if !$res->{file};
851
19672434 852 return undef if $res->{cache} &&
e482cec3 853 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
1e3baf05
DM
854 return undef if $res->{snapshot} && $res->{snapshot} !~ m/^(on|off)$/;
855 return undef if $res->{cyls} && $res->{cyls} !~ m/^\d+$/;
856 return undef if $res->{heads} && $res->{heads} !~ m/^\d+$/;
857 return undef if $res->{secs} && $res->{secs} !~ m/^\d+$/;
858 return undef if $res->{media} && $res->{media} !~ m/^(disk|cdrom)$/;
859 return undef if $res->{trans} && $res->{trans} !~ m/^(none|lba|auto)$/;
860 return undef if $res->{format} && $res->{format} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
861 return undef if $res->{rerror} && $res->{rerror} !~ m/^(ignore|report|stop)$/;
862 return undef if $res->{werror} && $res->{werror} !~ m/^(enospc|ignore|report|stop)$/;
863 return undef if $res->{backup} && $res->{backup} !~ m/^(yes|no)$/;
864 return undef if $res->{aio} && $res->{aio} !~ m/^(native|threads)$/;
865
affd2f88
AD
866 return undef if $res->{bps_rd} && $res->{bps};
867 return undef if $res->{bps_wr} && $res->{bps};
868 return undef if $res->{iops_rd} && $res->{iops};
869 return undef if $res->{iops_wr} && $res->{iops};
870
871 return undef if $res->{bps} && $res->{bps} !~ m/^\d+$/;
872 return undef if $res->{bps_rd} && $res->{bps_rd} !~ m/^\d+$/;
873 return undef if $res->{bps_wr} && $res->{bps_wr} !~ m/^\d+$/;
874 return undef if $res->{iops} && $res->{iops} !~ m/^\d+$/;
875 return undef if $res->{iops_rd} && $res->{iops_rd} !~ m/^\d+$/;
876 return undef if $res->{iops_wr} && $res->{iops_wr} !~ m/^\d+$/;
877
878
1e3baf05
DM
879 if ($res->{media} && ($res->{media} eq 'cdrom')) {
880 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
19672434 881 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
1e3baf05
DM
882 return undef if $res->{interface} eq 'virtio';
883 }
884
885 # rerror does not work with scsi drives
886 if ($res->{rerror}) {
887 return undef if $res->{interface} eq 'scsi';
888 }
889
890 return $res;
891}
892
affd2f88 893my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio bps bps_rd bps_wr iops iops_rd iops_wr);
1e3baf05
DM
894
895sub print_drive {
896 my ($vmid, $drive) = @_;
897
898 my $opts = '';
899 foreach my $o (@qemu_drive_options, 'backup') {
900 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
901 }
902
903 return "$drive->{file}$opts";
904}
905
28ef82d3
DM
906sub scsi_inquiry {
907 my($fh, $noerr) = @_;
908
909 my $SG_IO = 0x2285;
910 my $SG_GET_VERSION_NUM = 0x2282;
911
912 my $versionbuf = "\x00" x 8;
913 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
914 if (!$ret) {
915 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
916 return undef;
917 }
97d62eb7 918 my $version = unpack("I", $versionbuf);
28ef82d3
DM
919 if ($version < 30000) {
920 die "scsi generic interface too old\n" if !$noerr;
921 return undef;
922 }
97d62eb7 923
28ef82d3
DM
924 my $buf = "\x00" x 36;
925 my $sensebuf = "\x00" x 8;
926 my $cmd = pack("C x3 C x11", 0x12, 36);
97d62eb7 927
28ef82d3
DM
928 # see /usr/include/scsi/sg.h
929 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";
930
97d62eb7
DM
931 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
932 length($sensebuf), 0, length($buf), $buf,
28ef82d3
DM
933 $cmd, $sensebuf, 6000);
934
935 $ret = ioctl($fh, $SG_IO, $packet);
936 if (!$ret) {
937 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
938 return undef;
939 }
97d62eb7 940
28ef82d3
DM
941 my @res = unpack($sg_io_hdr_t, $packet);
942 if ($res[17] || $res[18]) {
943 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
944 return undef;
945 }
946
947 my $res = {};
948 ($res->{device}, $res->{removable}, $res->{venodor},
949 $res->{product}, $res->{revision}) = unpack("C C x6 A8 A16 A4", $buf);
950
951 return $res;
952}
953
954sub path_is_scsi {
955 my ($path) = @_;
956
957 my $fh = IO::File->new("+<$path") || return undef;
958 my $res = scsi_inquiry($fh, 1);
959 close($fh);
960
961 return $res;
962}
963
ca916ecc
DA
964sub print_drivedevice_full {
965 my ($storecfg, $vmid, $drive) = @_;
966
967 my $device = '';
968 my $maxdev = 0;
19672434 969
ca916ecc 970 if ($drive->{interface} eq 'virtio') {
2ed36a41
DM
971 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}");
972 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
973 } elsif ($drive->{interface} eq 'scsi') {
974 $maxdev = 7;
975 my $controller = int($drive->{index} / $maxdev);
976 my $unit = $drive->{index} % $maxdev;
977 my $devicetype = 'hd';
231f2e13
DA
978 my $path = '';
979 if (drive_is_cdrom($drive)) {
980 $devicetype = 'cd';
981 } else {
982 if ($drive->{file} =~ m|^/|) {
983 $path = $drive->{file};
984 } else {
985 $path = PVE::Storage::path($storecfg, $drive->{file});
986 }
28ef82d3 987 $devicetype = 'block' if path_is_scsi($path);
231f2e13 988 }
ca916ecc 989
7ebe888a 990 $device = "scsi-$devicetype,bus=lsi$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
991 } elsif ($drive->{interface} eq 'ide'){
992 $maxdev = 2;
993 my $controller = int($drive->{index} / $maxdev);
994 my $unit = $drive->{index} % $maxdev;
995 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
996
7ebe888a 997 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
cdb0931f
DA
998 } elsif ($drive->{interface} eq 'sata'){
999 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1000 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1001 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
2ed36a41
DM
1002 } elsif ($drive->{interface} eq 'usb') {
1003 die "implement me";
1004 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1005 } else {
1006 die "unsupported interface type";
ca916ecc
DA
1007 }
1008
3b408e82
DM
1009 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
1010
ca916ecc
DA
1011 return $device;
1012}
1013
1e3baf05
DM
1014sub print_drive_full {
1015 my ($storecfg, $vmid, $drive) = @_;
1016
1017 my $opts = '';
1018 foreach my $o (@qemu_drive_options) {
3b408e82 1019 next if $o eq 'bootindex';
1e3baf05 1020 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
19672434 1021 }
1e3baf05
DM
1022
1023 # use linux-aio by default (qemu default is threads)
19672434 1024 $opts .= ",aio=native" if !$drive->{aio};
1e3baf05
DM
1025
1026 my $path;
1027 my $volid = $drive->{file};
6b64503e
DM
1028 if (drive_is_cdrom($drive)) {
1029 $path = get_iso_path($storecfg, $vmid, $volid);
1e3baf05
DM
1030 } else {
1031 if ($volid =~ m|^/|) {
1032 $path = $volid;
1033 } else {
6b64503e 1034 $path = PVE::Storage::path($storecfg, $volid);
1e3baf05 1035 }
2b556977
DM
1036 if (!$drive->{cache} && ($path =~ m|^/dev/| || $path =~ m|\.raw$|)) {
1037 $opts .= ",cache=none";
1038 }
1e3baf05
DM
1039 }
1040
1041 my $pathinfo = $path ? "file=$path," : '';
1042
3ebfcc86 1043 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1e3baf05
DM
1044}
1045
cc4d6182
DA
1046sub print_netdevice_full {
1047 my ($vmid, $conf, $net, $netid) = @_;
1048
1049 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
1050
1051 my $device = $net->{model};
1052 if ($net->{model} eq 'virtio') {
1053 $device = 'virtio-net-pci';
1054 };
1055
1056 # qemu > 0.15 always try to boot from network - we disable that by
1057 # not loading the pxe rom file
1058 my $extra = ($bootorder !~ m/n/) ? "romfile=," : '';
1059 my $pciaddr = print_pci_addr("$netid");
1060 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1061 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ;
1062 return $tmpstr;
1063}
1064
1065sub print_netdev_full {
1066 my ($vmid, $conf, $net, $netid) = @_;
1067
1068 my $i = '';
1069 if ($netid =~ m/^net(\d+)$/) {
1070 $i = int($1);
1071 }
1072
1073 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
1074
1075 my $ifname = "tap${vmid}i$i";
1076
1077 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1078 die "interface name '$ifname' is too long (max 15 character)\n"
1079 if length($ifname) >= 16;
1080
1081 my $vhostparam = '';
1082 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model} eq 'virtio';
1083
1084 my $vmname = $conf->{name} || "vm$vmid";
1085
1086 if ($net->{bridge}) {
1087 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1088 } else {
1089 return "type=user,id=$netid,hostname=$vmname";
1090 }
1091}
1e3baf05
DM
1092
1093sub drive_is_cdrom {
1094 my ($drive) = @_;
1095
1096 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
1097
1098}
1099
040b06b7
DA
1100sub parse_hostpci {
1101 my ($value) = @_;
1102
1103 return undef if !$value;
1104
1105 my $res = {};
1106
1107 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1108 $res->{pciid} = $value;
1109 } else {
1110 return undef;
1111 }
1112
1113 return $res;
1114}
1115
1e3baf05
DM
1116# netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1117sub parse_net {
1118 my ($data) = @_;
1119
1120 my $res = {};
1121
6b64503e 1122 foreach my $kvp (split(/,/, $data)) {
1e3baf05
DM
1123
1124 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
6b64503e 1125 my $model = lc($1);
9f91ff02 1126 my $mac = uc($3) || PVE::Tools::random_ether_addr();
1e3baf05
DM
1127 $res->{model} = $model;
1128 $res->{macaddr} = $mac;
1129 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1130 $res->{bridge} = $1;
1131 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1132 $res->{rate} = $1;
5070f384
DA
1133 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1134 $res->{tag} = $1;
1e3baf05
DM
1135 } else {
1136 return undef;
1137 }
19672434 1138
1e3baf05
DM
1139 }
1140
1141 return undef if !$res->{model};
1142
1143 return $res;
1144}
1145
1146sub print_net {
1147 my $net = shift;
1148
1149 my $res = "$net->{model}";
1150 $res .= "=$net->{macaddr}" if $net->{macaddr};
1151 $res .= ",bridge=$net->{bridge}" if $net->{bridge};
1152 $res .= ",rate=$net->{rate}" if $net->{rate};
18744ba3 1153 $res .= ",tag=$net->{tag}" if $net->{tag};
1e3baf05
DM
1154
1155 return $res;
1156}
1157
1158sub add_random_macs {
1159 my ($settings) = @_;
1160
1161 foreach my $opt (keys %$settings) {
1162 next if $opt !~ m/^net(\d+)$/;
1163 my $net = parse_net($settings->{$opt});
1164 next if !$net;
1165 $settings->{$opt} = print_net($net);
1166 }
1167}
1168
1169sub add_unused_volume {
1858638f 1170 my ($config, $volid) = @_;
1e3baf05
DM
1171
1172 my $key;
1173 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1174 my $test = "unused$ind";
1175 if (my $vid = $config->{$test}) {
1176 return if $vid eq $volid; # do not add duplicates
1177 } else {
1178 $key = $test;
19672434 1179 }
1e3baf05
DM
1180 }
1181
1182 die "To many unused volume - please delete them first.\n" if !$key;
97d62eb7 1183
1858638f 1184 $config->{$key} = $volid;
1e3baf05 1185
1858638f 1186 return $key;
1e3baf05
DM
1187}
1188
1189# fixme: remove all thos $noerr parameters?
1190
1191PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1192sub verify_bootdisk {
1193 my ($value, $noerr) = @_;
1194
19672434 1195 return $value if valid_drivename($value);
1e3baf05
DM
1196
1197 return undef if $noerr;
1198
1199 die "invalid boot disk '$value'\n";
1200}
1201
1202PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
1203sub verify_net {
1204 my ($value, $noerr) = @_;
1205
1206 return $value if parse_net($value);
1207
1208 return undef if $noerr;
19672434 1209
1e3baf05
DM
1210 die "unable to parse network options\n";
1211}
1212
1213PVE::JSONSchema::register_format('pve-qm-drive', \&verify_drive);
1214sub verify_drive {
1215 my ($value, $noerr) = @_;
1216
6b64503e 1217 return $value if parse_drive(undef, $value);
1e3baf05
DM
1218
1219 return undef if $noerr;
19672434 1220
1e3baf05
DM
1221 die "unable to parse drive options\n";
1222}
1223
1224PVE::JSONSchema::register_format('pve-qm-hostpci', \&verify_hostpci);
1225sub verify_hostpci {
1226 my ($value, $noerr) = @_;
1227
040b06b7
DA
1228 return $value if parse_hostpci($value);
1229
1230 return undef if $noerr;
1231
1232 die "unable to parse pci id\n";
1e3baf05
DM
1233}
1234
0ea9541d
DM
1235PVE::JSONSchema::register_format('pve-qm-watchdog', \&verify_watchdog);
1236sub verify_watchdog {
1237 my ($value, $noerr) = @_;
1238
1239 return $value if parse_watchdog($value);
1240
1241 return undef if $noerr;
19672434 1242
0ea9541d
DM
1243 die "unable to parse watchdog options\n";
1244}
1245
1246sub parse_watchdog {
1247 my ($value) = @_;
1248
1249 return undef if !$value;
1250
1251 my $res = {};
1252
6b64503e 1253 foreach my $p (split(/,/, $value)) {
0ea9541d
DM
1254 next if $p =~ m/^\s*$/;
1255
1256 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1257 $res->{model} = $2;
1258 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1259 $res->{action} = $2;
1260 } else {
1261 return undef;
1262 }
1263 }
1264
1265 return $res;
1266}
1267
59411c4e
DM
1268PVE::JSONSchema::register_format('pve-qm-startup', \&verify_startup);
1269sub verify_startup {
1270 my ($value, $noerr) = @_;
1271
1272 return $value if parse_startup($value);
1273
1274 return undef if $noerr;
1275
1276 die "unable to parse startup options\n";
1277}
1278
1279sub parse_startup {
1280 my ($value) = @_;
1281
1282 return undef if !$value;
1283
1284 my $res = {};
1285
1286 foreach my $p (split(/,/, $value)) {
1287 next if $p =~ m/^\s*$/;
1288
1289 if ($p =~ m/^(order=)?(\d+)$/) {
1290 $res->{order} = $2;
1291 } elsif ($p =~ m/^up=(\d+)$/) {
1292 $res->{up} = $1;
1293 } elsif ($p =~ m/^down=(\d+)$/) {
1294 $res->{down} = $1;
1295 } else {
1296 return undef;
1297 }
1298 }
1299
1300 return $res;
1301}
1302
1e3baf05
DM
1303sub parse_usb_device {
1304 my ($value) = @_;
1305
1306 return undef if !$value;
1307
6b64503e 1308 my @dl = split(/,/, $value);
1e3baf05
DM
1309 my $found;
1310
1311 my $res = {};
1312 foreach my $v (@dl) {
036e0e2b 1313 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1e3baf05 1314 $found = 1;
036e0e2b
DM
1315 $res->{vendorid} = $2;
1316 $res->{productid} = $4;
1e3baf05
DM
1317 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1318 $found = 1;
1319 $res->{hostbus} = $1;
1320 $res->{hostport} = $2;
1321 } else {
1322 return undef;
1323 }
1324 }
1325 return undef if !$found;
1326
1327 return $res;
1328}
19672434 1329
1e3baf05
DM
1330PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
1331sub verify_usb_device {
1332 my ($value, $noerr) = @_;
1333
1334 return $value if parse_usb_device($value);
1335
1336 return undef if $noerr;
19672434 1337
1e3baf05
DM
1338 die "unable to parse usb device\n";
1339}
1340
1e3baf05
DM
1341# add JSON properties for create and set function
1342sub json_config_properties {
1343 my $prop = shift;
1344
1345 foreach my $opt (keys %$confdesc) {
1346 $prop->{$opt} = $confdesc->{$opt};
1347 }
1348
1349 return $prop;
1350}
1351
1352sub check_type {
1353 my ($key, $value) = @_;
1354
1355 die "unknown setting '$key'\n" if !$confdesc->{$key};
1356
1357 my $type = $confdesc->{$key}->{type};
1358
6b64503e 1359 if (!defined($value)) {
1e3baf05
DM
1360 die "got undefined value\n";
1361 }
1362
1363 if ($value =~ m/[\n\r]/) {
1364 die "property contains a line feed\n";
1365 }
1366
1367 if ($type eq 'boolean') {
19672434
DM
1368 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1369 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1370 die "type check ('boolean') failed - got '$value'\n";
1e3baf05
DM
1371 } elsif ($type eq 'integer') {
1372 return int($1) if $value =~ m/^(\d+)$/;
1373 die "type check ('integer') failed - got '$value'\n";
1374 } elsif ($type eq 'string') {
1375 if (my $fmt = $confdesc->{$key}->{format}) {
1376 if ($fmt eq 'pve-qm-drive') {
1377 # special case - we need to pass $key to parse_drive()
6b64503e 1378 my $drive = parse_drive($key, $value);
1e3baf05
DM
1379 return $value if $drive;
1380 die "unable to parse drive options\n";
1381 }
1382 PVE::JSONSchema::check_format($fmt, $value);
19672434
DM
1383 return $value;
1384 }
1e3baf05 1385 $value =~ s/^\"(.*)\"$/$1/;
19672434 1386 return $value;
1e3baf05
DM
1387 } else {
1388 die "internal error"
1389 }
1390}
1391
191435c6
DM
1392sub lock_config_full {
1393 my ($vmid, $timeout, $code, @param) = @_;
1e3baf05 1394
6b64503e 1395 my $filename = config_file_lock($vmid);
1e3baf05 1396
191435c6 1397 my $res = lock_file($filename, $timeout, $code, @param);
1e3baf05
DM
1398
1399 die $@ if $@;
5fdbe4f0
DM
1400
1401 return $res;
1e3baf05
DM
1402}
1403
191435c6
DM
1404sub lock_config {
1405 my ($vmid, $code, @param) = @_;
1406
1407 return lock_config_full($vmid, 10, $code, @param);
1408}
1409
1e3baf05 1410sub cfs_config_path {
a78ccf26 1411 my ($vmid, $node) = @_;
1e3baf05 1412
a78ccf26
DM
1413 $node = $nodename if !$node;
1414 return "nodes/$node/qemu-server/$vmid.conf";
1e3baf05
DM
1415}
1416
040b06b7
DA
1417sub check_iommu_support{
1418 #fixme : need to check IOMMU support
1419 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1420
1421 my $iommu=1;
1422 return $iommu;
1423
1424}
1425
1e3baf05 1426sub config_file {
a78ccf26 1427 my ($vmid, $node) = @_;
1e3baf05 1428
a78ccf26 1429 my $cfspath = cfs_config_path($vmid, $node);
1e3baf05
DM
1430 return "/etc/pve/$cfspath";
1431}
1432
1433sub config_file_lock {
1434 my ($vmid) = @_;
1435
1436 return "$lock_dir/lock-$vmid.conf";
1437}
1438
1439sub touch_config {
1440 my ($vmid) = @_;
1441
6b64503e 1442 my $conf = config_file($vmid);
1e3baf05
DM
1443 utime undef, undef, $conf;
1444}
1445
1e3baf05 1446sub destroy_vm {
a6af7b3e 1447 my ($storecfg, $vmid, $keep_empty_config) = @_;
1e3baf05 1448
6b64503e 1449 my $conffile = config_file($vmid);
1e3baf05 1450
6b64503e 1451 my $conf = load_config($vmid);
1e3baf05 1452
6b64503e 1453 check_lock($conf);
1e3baf05 1454
19672434 1455 # only remove disks owned by this VM
1e3baf05
DM
1456 foreach_drive($conf, sub {
1457 my ($ds, $drive) = @_;
1458
6b64503e 1459 return if drive_is_cdrom($drive);
1e3baf05
DM
1460
1461 my $volid = $drive->{file};
ff1a2432 1462 return if !$volid || $volid =~ m|^/|;
1e3baf05 1463
6b64503e 1464 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
ff1a2432 1465 return if !$path || !$owner || ($owner != $vmid);
1e3baf05 1466
6b64503e 1467 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 1468 });
19672434 1469
a6af7b3e 1470 if ($keep_empty_config) {
9c502e26 1471 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
a6af7b3e
DM
1472 } else {
1473 unlink $conffile;
1474 }
1e3baf05
DM
1475
1476 # also remove unused disk
1477 eval {
6b64503e 1478 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
1479
1480 eval {
6b64503e 1481 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 1482 my ($volid, $sid, $volname, $d) = @_;
6b64503e 1483 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
1484 });
1485 };
1486 warn $@ if $@;
1487
1488 };
1489 warn $@ if $@;
1490}
1491
1492# fixme: remove?
1493sub load_diskinfo_old {
1494 my ($storecfg, $vmid, $conf) = @_;
1495
1496 my $info = {};
1497 my $res = {};
1498 my $vollist;
1499
1500 foreach_drive($conf, sub {
1501 my ($ds, $di) = @_;
1502
1503 $res->{$ds} = $di;
1504
6b64503e 1505 return if drive_is_cdrom($di);
1e3baf05
DM
1506
1507 if ($di->{file} =~ m|^/dev/.+|) {
6b64503e 1508 $info->{$di->{file}}->{size} = PVE::Storage::file_size_info($di->{file});
1e3baf05
DM
1509 } else {
1510 push @$vollist, $di->{file};
1511 }
1512 });
1513
1514 eval {
6b64503e 1515 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid, $vollist);
1e3baf05 1516
6b64503e 1517 PVE::Storage::foreach_volid($dl, sub {
1e3baf05
DM
1518 my ($volid, $sid, $volname, $d) = @_;
1519 $info->{$volid} = $d;
1520 });
1521 };
1522 warn $@ if $@;
1523
1524 foreach my $ds (keys %$res) {
1525 my $di = $res->{$ds};
1526
19672434 1527 $res->{$ds}->{disksize} = $info->{$di->{file}} ?
1e3baf05
DM
1528 $info->{$di->{file}}->{size} / (1024*1024) : 0;
1529 }
1530
1531 return $res;
1532}
1533
1534sub load_config {
1535 my ($vmid) = @_;
1536
1537 my $cfspath = cfs_config_path($vmid);
1538
1539 my $conf = PVE::Cluster::cfs_read_file($cfspath);
1540
1541 die "no such VM ('$vmid')\n" if !defined($conf);
1542
1543 return $conf;
19672434 1544}
1e3baf05
DM
1545
1546sub parse_vm_config {
1547 my ($filename, $raw) = @_;
1548
1549 return undef if !defined($raw);
1550
554ac7e7 1551 my $res = {
fc1ddcdc 1552 digest => Digest::SHA::sha1_hex($raw),
554ac7e7 1553 };
1e3baf05 1554
19672434 1555 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
1556 || die "got strange filename '$filename'";
1557
1558 my $vmid = $1;
1559
0581fe4f
DM
1560 my $descr = '';
1561
1e3baf05
DM
1562 while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
1563 my $line = $1;
19672434 1564
1e3baf05
DM
1565 next if $line =~ m/^\s*$/;
1566
0581fe4f
DM
1567 if ($line =~ m/^\#(.*)\s*$/) {
1568 $descr .= PVE::Tools::decode_text($1) . "\n";
1569 next;
1570 }
1571
1e3baf05 1572 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
0581fe4f 1573 $descr .= PVE::Tools::decode_text($2);
1e3baf05
DM
1574 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1575 my $key = $1;
1576 my $value = $2;
1577 $res->{$key} = $value;
1578 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1579 my $key = $1;
1580 my $value = $2;
1581 eval { $value = check_type($key, $value); };
1582 if ($@) {
1583 warn "vm $vmid - unable to parse value of '$key' - $@";
1584 } else {
1585 my $fmt = $confdesc->{$key}->{format};
1586 if ($fmt && $fmt eq 'pve-qm-drive') {
1587 my $v = parse_drive($key, $value);
1588 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
1589 $v->{file} = $volid;
6b64503e 1590 $value = print_drive($vmid, $v);
1e3baf05
DM
1591 } else {
1592 warn "vm $vmid - unable to parse value of '$key'\n";
1593 next;
1594 }
1595 }
1596
1597 if ($key eq 'cdrom') {
1598 $res->{ide2} = $value;
1599 } else {
1600 $res->{$key} = $value;
1601 }
1602 }
1603 }
1604 }
1605
0581fe4f
DM
1606 $res->{description} = $descr if $descr;
1607
1e3baf05
DM
1608 # convert old smp to sockets
1609 if ($res->{smp} && !$res->{sockets}) {
1610 $res->{sockets} = $res->{smp};
19672434 1611 }
1e3baf05
DM
1612 delete $res->{smp};
1613
1614 return $res;
1615}
1616
1858638f
DM
1617sub write_vm_config {
1618 my ($filename, $conf) = @_;
1e3baf05 1619
1858638f
DM
1620 if ($conf->{cdrom}) {
1621 die "option ide2 conflicts with cdrom\n" if $conf->{ide2};
1622 $conf->{ide2} = $conf->{cdrom};
1623 delete $conf->{cdrom};
1624 }
1e3baf05
DM
1625
1626 # we do not use 'smp' any longer
1858638f
DM
1627 if ($conf->{sockets}) {
1628 delete $conf->{smp};
1629 } elsif ($conf->{smp}) {
1630 $conf->{sockets} = $conf->{smp};
1631 delete $conf->{cores};
1632 delete $conf->{smp};
1e3baf05
DM
1633 }
1634
1635 my $new_volids = {};
1858638f 1636 foreach my $key (keys %$conf) {
0581fe4f 1637 next if $key eq 'digest' || $key eq 'description';
1858638f 1638 my $value = $conf->{$key};
1e3baf05
DM
1639 eval { $value = check_type($key, $value); };
1640 die "unable to parse value of '$key' - $@" if $@;
1858638f
DM
1641
1642 $conf->{$key} = $value;
1643
1e3baf05
DM
1644 if (valid_drivename($key)) {
1645 my $drive = PVE::QemuServer::parse_drive($key, $value);
1646 $new_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1647 }
1648 }
1649
1858638f
DM
1650 # remove 'unusedX' settings if we re-add a volume
1651 foreach my $key (keys %$conf) {
1652 my $value = $conf->{$key};
1653 if ($key =~ m/^unused/ && $new_volids->{$value}) {
1654 delete $conf->{$key};
1e3baf05 1655 }
1858638f 1656 }
1e3baf05 1657
1858638f
DM
1658 # gererate RAW data
1659 my $raw = '';
0581fe4f
DM
1660
1661 # add description as comment to top of file
1662 my $descr = $conf->{description} || '';
1663 foreach my $cl (split(/\n/, $descr)) {
1664 $raw .= '#' . PVE::Tools::encode_text($cl) . "\n";
1665 }
1666
1858638f 1667 foreach my $key (sort keys %$conf) {
0581fe4f 1668 next if $key eq 'digest' || $key eq 'description';
1858638f
DM
1669 $raw .= "$key: $conf->{$key}\n";
1670 }
1e3baf05 1671
1858638f
DM
1672 return $raw;
1673}
1e3baf05 1674
1858638f
DM
1675sub update_config_nolock {
1676 my ($vmid, $conf, $skiplock) = @_;
1e3baf05 1677
1858638f 1678 check_lock($conf) if !$skiplock;
97d62eb7 1679
1858638f 1680 my $cfspath = cfs_config_path($vmid);
1e3baf05 1681
1858638f
DM
1682 PVE::Cluster::cfs_write_file($cfspath, $conf);
1683}
1e3baf05 1684
1858638f
DM
1685sub update_config {
1686 my ($vmid, $conf, $skiplock) = @_;
1e3baf05 1687
1858638f 1688 lock_config($vmid, &update_config_nolock, $conf, $skiplock);
1e3baf05
DM
1689}
1690
19672434 1691sub load_defaults {
1e3baf05
DM
1692
1693 my $res = {};
1694
1695 # we use static defaults from our JSON schema configuration
1696 foreach my $key (keys %$confdesc) {
1697 if (defined(my $default = $confdesc->{$key}->{default})) {
1698 $res->{$key} = $default;
1699 }
1700 }
19672434 1701
1e3baf05
DM
1702 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
1703 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
1704
1705 return $res;
1706}
1707
1708sub config_list {
1709 my $vmlist = PVE::Cluster::get_vmlist();
1710 my $res = {};
1711 return $res if !$vmlist || !$vmlist->{ids};
1712 my $ids = $vmlist->{ids};
1713
1e3baf05
DM
1714 foreach my $vmid (keys %$ids) {
1715 my $d = $ids->{$vmid};
1716 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 1717 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
1718 $res->{$vmid}->{exists} = 1;
1719 }
1720 return $res;
1721}
1722
64e13401
DM
1723# test if VM uses local resources (to prevent migration)
1724sub check_local_resources {
1725 my ($conf, $noerr) = @_;
1726
1727 my $loc_res = 0;
19672434 1728
e0ab7331
DM
1729 $loc_res = 1 if $conf->{hostusb}; # old syntax
1730 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 1731
0d29ab3b 1732 foreach my $k (keys %$conf) {
2fe1a152 1733 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
1734 }
1735
1736 die "VM uses local resources\n" if $loc_res && !$noerr;
1737
1738 return $loc_res;
1739}
1740
47152e2e
DM
1741# check is used storages are available on all nodes (use by migrate)
1742sub check_storage_availability {
1743 my ($storecfg, $conf, $node) = @_;
1744
1745 foreach_drive($conf, sub {
1746 my ($ds, $drive) = @_;
1747
1748 my $volid = $drive->{file};
1749 return if !$volid;
1750
1751 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
1752 return if !$sid;
1753
1754 # check if storage is available on both nodes
1755 my $scfg = PVE::Storage::storage_check_node($storecfg, $sid);
1756 PVE::Storage::storage_check_node($storecfg, $sid, $node);
1757 });
1758}
1759
1e3baf05
DM
1760sub check_lock {
1761 my ($conf) = @_;
1762
1763 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1764}
1765
1766sub check_cmdline {
1767 my ($pidfile, $pid) = @_;
1768
6b64503e
DM
1769 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1770 if (defined($fh)) {
1e3baf05
DM
1771 my $line = <$fh>;
1772 $fh->close;
1773 return undef if !$line;
6b64503e 1774 my @param = split(/\0/, $line);
1e3baf05
DM
1775
1776 my $cmd = $param[0];
1777 return if !$cmd || ($cmd !~ m|kvm$|);
1778
1779 for (my $i = 0; $i < scalar (@param); $i++) {
1780 my $p = $param[$i];
1781 next if !$p;
1782 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1783 my $p = $param[$i+1];
1784 return 1 if $p && ($p eq $pidfile);
1785 return undef;
1786 }
1787 }
1788 }
1789 return undef;
1790}
1791
1792sub check_running {
e6c3b671 1793 my ($vmid, $nocheck) = @_;
1e3baf05 1794
e6c3b671 1795 my $filename = config_file($vmid);
1e3baf05
DM
1796
1797 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 1798 if !$nocheck && ! -f $filename;
1e3baf05 1799
e6c3b671 1800 my $pidfile = pidfile_name($vmid);
1e3baf05 1801
e6c3b671
DM
1802 if (my $fd = IO::File->new("<$pidfile")) {
1803 my $st = stat($fd);
1e3baf05 1804 my $line = <$fd>;
6b64503e 1805 close($fd);
1e3baf05
DM
1806
1807 my $mtime = $st->mtime;
1808 if ($mtime > time()) {
1809 warn "file '$filename' modified in future\n";
1810 }
1811
1812 if ($line =~ m/^(\d+)$/) {
1813 my $pid = $1;
e6c3b671
DM
1814 if (check_cmdline($pidfile, $pid)) {
1815 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1816 return $pid;
1817 }
1818 }
1e3baf05
DM
1819 }
1820 }
1821
1822 return undef;
1823}
1824
1825sub vzlist {
19672434 1826
1e3baf05
DM
1827 my $vzlist = config_list();
1828
6b64503e 1829 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 1830
19672434 1831 while (defined(my $de = $fd->read)) {
1e3baf05
DM
1832 next if $de !~ m/^(\d+)\.pid$/;
1833 my $vmid = $1;
6b64503e
DM
1834 next if !defined($vzlist->{$vmid});
1835 if (my $pid = check_running($vmid)) {
1e3baf05
DM
1836 $vzlist->{$vmid}->{pid} = $pid;
1837 }
1838 }
1839
1840 return $vzlist;
1841}
1842
1843my $storage_timeout_hash = {};
1844
1845sub disksize {
1846 my ($storecfg, $conf) = @_;
1847
1848 my $bootdisk = $conf->{bootdisk};
1849 return undef if !$bootdisk;
1850 return undef if !valid_drivename($bootdisk);
1851
1852 return undef if !$conf->{$bootdisk};
1853
1854 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
1855 return undef if !defined($drive);
1856
1857 return undef if drive_is_cdrom($drive);
1858
1859 my $volid = $drive->{file};
1860 return undef if !$volid;
1861
1862 my $path;
1863 my $storeid;
1864 my $timeoutid;
1865
1866 if ($volid =~ m|^/|) {
1867 $path = $timeoutid = $volid;
1868 } else {
f0cab979
DM
1869 eval {
1870 $storeid = $timeoutid = PVE::Storage::parse_volume_id($volid);
1871 $path = PVE::Storage::path($storecfg, $volid);
1872 };
1873 if (my $err = $@) {
1874 warn $err;
1875 return undef;
1876 }
1e3baf05
DM
1877 }
1878
1879 my $last_timeout = $storage_timeout_hash->{$timeoutid};
1880 if ($last_timeout) {
1881 if ((time() - $last_timeout) < 30) {
1882 # skip storage with errors
1883 return undef ;
1884 }
1885 delete $storage_timeout_hash->{$timeoutid};
1886 }
1887
1888 my ($size, $format, $used);
1889
1890 ($size, $format, $used) = PVE::Storage::file_size_info($path, 1);
1891
1892 if (!defined($format)) {
1893 # got timeout
1894 $storage_timeout_hash->{$timeoutid} = time();
1895 return undef;
1896 }
1897
1898 return wantarray ? ($size, $used) : $size;
1899}
1900
1901my $last_proc_pid_stat;
1902
03a33f30
DM
1903# get VM status information
1904# This must be fast and should not block ($full == false)
1905# We only query KVM using QMP if $full == true (this can be slow)
1e3baf05 1906sub vmstatus {
03a33f30 1907 my ($opt_vmid, $full) = @_;
1e3baf05
DM
1908
1909 my $res = {};
1910
19672434 1911 my $storecfg = PVE::Storage::config();
1e3baf05
DM
1912
1913 my $list = vzlist();
694fcad4 1914 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05 1915
ae4915a2
DM
1916 my $cpucount = $cpuinfo->{cpus} || 1;
1917
1e3baf05
DM
1918 foreach my $vmid (keys %$list) {
1919 next if $opt_vmid && ($vmid ne $opt_vmid);
1920
1921 my $cfspath = cfs_config_path($vmid);
1922 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
1923
1924 my $d = {};
1925 $d->{pid} = $list->{$vmid}->{pid};
1926
1927 # fixme: better status?
1928 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
1929
1930 my ($size, $used) = disksize($storecfg, $conf);
1931 if (defined($size) && defined($used)) {
1932 $d->{disk} = $used;
1933 $d->{maxdisk} = $size;
1934 } else {
1935 $d->{disk} = 0;
1936 $d->{maxdisk} = 0;
1937 }
1938
1939 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
ae4915a2
DM
1940 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
1941
1e3baf05 1942 $d->{name} = $conf->{name} || "VM $vmid";
19672434 1943 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1e3baf05 1944
1e3baf05
DM
1945 $d->{uptime} = 0;
1946 $d->{cpu} = 0;
1e3baf05
DM
1947 $d->{mem} = 0;
1948
1949 $d->{netout} = 0;
1950 $d->{netin} = 0;
1951
1952 $d->{diskread} = 0;
1953 $d->{diskwrite} = 0;
1954
1955 $res->{$vmid} = $d;
1956 }
1957
1958 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
1959 foreach my $dev (keys %$netdev) {
1960 next if $dev !~ m/^tap([1-9]\d*)i/;
1961 my $vmid = $1;
1962 my $d = $res->{$vmid};
1963 next if !$d;
19672434 1964
1e3baf05
DM
1965 $d->{netout} += $netdev->{$dev}->{receive};
1966 $d->{netin} += $netdev->{$dev}->{transmit};
1967 }
1968
1e3baf05
DM
1969 my $ctime = gettimeofday;
1970
1971 foreach my $vmid (keys %$list) {
1972
1973 my $d = $res->{$vmid};
1974 my $pid = $d->{pid};
1975 next if !$pid;
1976
694fcad4
DM
1977 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
1978 next if !$pstat; # not running
19672434 1979
694fcad4 1980 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05 1981
694fcad4 1982 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 1983
694fcad4 1984 if ($pstat->{vsize}) {
6b64503e 1985 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
1986 }
1987
1988 my $old = $last_proc_pid_stat->{$pid};
1989 if (!$old) {
19672434
DM
1990 $last_proc_pid_stat->{$pid} = {
1991 time => $ctime,
1e3baf05
DM
1992 used => $used,
1993 cpu => 0,
1e3baf05
DM
1994 };
1995 next;
1996 }
1997
7f0b5beb 1998 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
1999
2000 if ($dtime > 1000) {
2001 my $dutime = $used - $old->{used};
2002
ae4915a2 2003 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1e3baf05 2004 $last_proc_pid_stat->{$pid} = {
19672434 2005 time => $ctime,
1e3baf05
DM
2006 used => $used,
2007 cpu => $d->{cpu},
1e3baf05
DM
2008 };
2009 } else {
2010 $d->{cpu} = $old->{cpu};
1e3baf05
DM
2011 }
2012 }
2013
03a33f30
DM
2014 return $res if !$full;
2015
2016 my $qmpclient = PVE::QMPClient->new();
2017
2018 my $blockstatscb = sub {
2019 my ($vmid, $resp) = @_;
2020 my $data = $resp->{'return'} || [];
2021 my $totalrdbytes = 0;
2022 my $totalwrbytes = 0;
2023 for my $blockstat (@$data) {
2024 $totalrdbytes = $totalrdbytes + $blockstat->{stats}->{rd_bytes};
2025 $totalwrbytes = $totalwrbytes + $blockstat->{stats}->{wr_bytes};
2026 }
2027 $res->{$vmid}->{diskread} = $totalrdbytes;
2028 $res->{$vmid}->{diskwrite} = $totalwrbytes;
2029 };
2030
2031 my $statuscb = sub {
2032 my ($vmid, $resp) = @_;
2033 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2034
2035 my $status = 'unknown';
2036 if (!defined($status = $resp->{'return'}->{status})) {
2037 warn "unable to get VM status\n";
2038 return;
2039 }
2040
2041 $res->{$vmid}->{qmpstatus} = $resp->{'return'}->{status};
2042 };
2043
2044 foreach my $vmid (keys %$list) {
2045 next if $opt_vmid && ($vmid ne $opt_vmid);
2046 next if !$res->{$vmid}->{pid}; # not running
2047 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2048 }
2049
2050 $qmpclient->queue_execute();
2051
2052 foreach my $vmid (keys %$list) {
2053 next if $opt_vmid && ($vmid ne $opt_vmid);
2054 $res->{$vmid}->{qmpstatus} = $res->{$vmid}->{status} if !$res->{$vmid}->{qmpstatus};
2055 }
2056
1e3baf05
DM
2057 return $res;
2058}
2059
2060sub foreach_drive {
2061 my ($conf, $func) = @_;
2062
2063 foreach my $ds (keys %$conf) {
2064 next if !valid_drivename($ds);
2065
6b64503e 2066 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
2067 next if !$drive;
2068
2069 &$func($ds, $drive);
2070 }
2071}
2072
2073sub config_to_command {
2074 my ($storecfg, $vmid, $conf, $defaults, $migrate_uri) = @_;
2075
2076 my $cmd = [];
b78ebef7 2077 my $pciaddr = '';
1e3baf05
DM
2078 my $kvmver = kvm_user_version();
2079 my $vernum = 0; # unknown
a3c52213
DM
2080 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2081 $vernum = $1*1000000+$2*1000;
2082 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1e3baf05
DM
2083 $vernum = $1*1000000+$2*1000+$3;
2084 }
2085
a3c52213 2086 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1e3baf05
DM
2087
2088 my $have_ovz = -f '/proc/vz/vestat';
2089
2090 push @$cmd, '/usr/bin/kvm';
2091
2092 push @$cmd, '-id', $vmid;
2093
2094 my $use_virtio = 0;
2095
c971c4f2
AD
2096 my $qmpsocket = qmp_socket($vmid);
2097 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2098 push @$cmd, '-mon', "chardev=qmp,mode=control";
2099
7b7c6d1b 2100 my $socket = vnc_socket($vmid);
1e3baf05
DM
2101 push @$cmd, '-vnc', "unix:$socket,x509,password";
2102
6b64503e 2103 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 2104
1e3baf05
DM
2105 push @$cmd, '-daemonize';
2106
2107 push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
2108
1c060867
DM
2109 my $use_usb2 = 0;
2110 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2111 next if !$conf->{"usb$i"};
2112 $use_usb2 = 1;
2113 }
1e3baf05 2114 # include usb device config
1c060867 2115 push @$cmd, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
19672434 2116
1e3baf05 2117 # enable absolute mouse coordinates (needed by vnc)
6b64503e 2118 my $tablet = defined($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
1c060867
DM
2119 if ($tablet) {
2120 if ($use_usb2) {
2121 push @$cmd, '-device', 'usb-tablet,bus=ehci.0,port=6';
2122 } else {
2123 push @$cmd, '-usbdevice', 'tablet';
2124 }
2125 }
1e3baf05
DM
2126
2127 # host pci devices
040b06b7
DA
2128 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2129 my $d = parse_hostpci($conf->{"hostpci$i"});
2130 next if !$d;
b78ebef7
DA
2131 $pciaddr = print_pci_addr("hostpci$i");
2132 push @$cmd, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
1e3baf05
DM
2133 }
2134
2135 # usb devices
2136 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2137 my $d = parse_usb_device($conf->{"usb$i"});
2138 next if !$d;
2139 if ($d->{vendorid} && $d->{productid}) {
036e0e2b 2140 push @$cmd, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
1e3baf05
DM
2141 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
2142 push @$cmd, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2143 }
2144 }
2145
1e3baf05 2146 # serial devices
bae179aa 2147 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 2148 if (my $path = $conf->{"serial$i"}) {
19672434 2149 die "no such serial device\n" if ! -c $path;
34978be3
DM
2150 push @$cmd, '-chardev', "tty,id=serial$i,path=$path";
2151 push @$cmd, '-device', "isa-serial,chardev=serial$i";
2152 }
1e3baf05
DM
2153 }
2154
2155 # parallel devices
1989a89c 2156 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 2157 if (my $path = $conf->{"parallel$i"}) {
19672434 2158 die "no such parallel device\n" if ! -c $path;
34978be3
DM
2159 push @$cmd, '-chardev', "parport,id=parallel$i,path=$path";
2160 push @$cmd, '-device', "isa-parallel,chardev=parallel$i";
2161 }
1e3baf05
DM
2162 }
2163
2164 my $vmname = $conf->{name} || "vm$vmid";
2165
2166 push @$cmd, '-name', $vmname;
19672434 2167
1e3baf05
DM
2168 my $sockets = 1;
2169 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2170 $sockets = $conf->{sockets} if $conf->{sockets};
2171
2172 my $cores = $conf->{cores} || 1;
2173
1e3baf05
DM
2174 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2175
2176 push @$cmd, '-cpu', $conf->{cpu} if $conf->{cpu};
2177
1e3baf05
DM
2178 push @$cmd, '-nodefaults';
2179
32baffb4 2180 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
3b408e82 2181
0888fdce
DM
2182 my $bootindex_hash = {};
2183 my $i = 1;
2184 foreach my $o (split(//, $bootorder)) {
2185 $bootindex_hash->{$o} = $i*100;
2186 $i++;
afdb31d5 2187 }
3b408e82
DM
2188
2189 push @$cmd, '-boot', "menu=on";
1e3baf05 2190
6b64503e 2191 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 2192
6b64503e 2193 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05
DM
2194
2195 my $vga = $conf->{vga};
2196 if (!$vga) {
2197 if ($conf->{ostype} && ($conf->{ostype} eq 'win7' || $conf->{ostype} eq 'w2k8')) {
2198 $vga = 'std';
2199 } else {
2200 $vga = 'cirrus';
2201 }
2202 }
19672434 2203
1e3baf05
DM
2204 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2205
2206 # time drift fix
6b64503e 2207 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
da21653b
DM
2208 # ignore - no longer supported by newer kvm
2209 # push @$cmd, '-tdf' if $tdf;
1e3baf05 2210
6b64503e 2211 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
1e3baf05
DM
2212
2213 if (my $ost = $conf->{ostype}) {
2214 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2215
2216 if ($ost =~ m/^w/) { # windows
6b64503e 2217 push @$cmd, '-localtime' if !defined($conf->{localtime});
1e3baf05
DM
2218
2219 # use rtc-td-hack when acpi is enabled
6b64503e 2220 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
1e3baf05
DM
2221 push @$cmd, '-rtc-td-hack';
2222 }
2223 }
2224
b7e0c8bf
DM
2225 if ($ost eq 'win7' || $ost eq 'w2k8' || $ost eq 'wvista') {
2226 push @$cmd, '-no-kvm-pit-reinjection';
2227 push @$cmd, '-no-hpet';
2228 }
2229
1e3baf05 2230 # -tdf ?
19672434
DM
2231 # -no-acpi
2232 # -no-kvm
1e3baf05
DM
2233 # -win2k-hack ?
2234 }
2235
7f0b5beb
DM
2236 if ($nokvm) {
2237 push @$cmd, '-no-kvm';
2238 } else {
2239 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2240 }
1e3baf05
DM
2241
2242 push @$cmd, '-localtime' if $conf->{localtime};
2243
2244 push @$cmd, '-startdate', $conf->{startdate} if $conf->{startdate};
2245
2246 push @$cmd, '-S' if $conf->{freeze};
2247
2248 # set keyboard layout
2249 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2250 push @$cmd, '-k', $kb if $kb;
2251
2252 # enable sound
2253 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2254 #push @$cmd, '-soundhw', 'es1370';
2255 #push @$cmd, '-soundhw', $soundhw if $soundhw;
b78ebef7 2256 $pciaddr = print_pci_addr("balloon0");
13b5a753 2257 push @$cmd, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon};
1e3baf05 2258
0ea9541d
DM
2259 if ($conf->{watchdog}) {
2260 my $wdopts = parse_watchdog($conf->{watchdog});
0a40e8ea
DA
2261 $pciaddr = print_pci_addr("watchdog");
2262 my $watchdog = $wdopts->{model} || 'i6300esb';
2263 push @$cmd, '-device', "$watchdog$pciaddr";
0ea9541d
DM
2264 push @$cmd, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
2265 }
2266
1e3baf05 2267 my $vollist = [];
941e0c42 2268 my $scsicontroller = {};
26ee04b6 2269 my $ahcicontroller = {};
1e3baf05
DM
2270
2271 foreach_drive($conf, sub {
2272 my ($ds, $drive) = @_;
2273
ff1a2432 2274 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
1e3baf05 2275 push @$vollist, $drive->{file};
ff1a2432 2276 }
afdb31d5 2277
1e3baf05 2278 $use_virtio = 1 if $ds =~ m/^virtio/;
3b408e82
DM
2279
2280 if (drive_is_cdrom ($drive)) {
2281 if ($bootindex_hash->{d}) {
2282 $drive->{bootindex} = $bootindex_hash->{d};
2283 $bootindex_hash->{d} += 1;
2284 }
2285 } else {
2286 if ($bootindex_hash->{c}) {
2287 $drive->{bootindex} = $bootindex_hash->{c} if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2288 $bootindex_hash->{c} += 1;
2289 }
2290 }
2291
941e0c42
DA
2292 if ($drive->{interface} eq 'scsi') {
2293 my $maxdev = 7;
6b64503e 2294 my $controller = int($drive->{index} / $maxdev);
69b6ae0c
DA
2295 $pciaddr = print_pci_addr("lsi$controller");
2296 push @$cmd, '-device', "lsi,id=lsi$controller$pciaddr" if !$scsicontroller->{$controller};
58dc808d 2297 $scsicontroller->{$controller}=1;
941e0c42 2298 }
3b408e82 2299
26ee04b6
DA
2300 if ($drive->{interface} eq 'sata') {
2301 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2302 $pciaddr = print_pci_addr("ahci$controller");
2303 push @$cmd, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2304 $ahcicontroller->{$controller}=1;
2305 }
2306
2307 push @$cmd, '-drive',print_drive_full($storecfg, $vmid, $drive);
6b64503e 2308 push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
1e3baf05
DM
2309 });
2310
2311 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
19672434 2312
cc4d6182 2313 for (my $i = 0; $i < $MAX_NETS; $i++) {
5f0c4c32 2314 next if !$conf->{"net$i"};
cc4d6182
DA
2315 my $d = parse_net($conf->{"net$i"});
2316 next if !$d;
1e3baf05 2317
cc4d6182 2318 $use_virtio = 1 if $d->{model} eq 'virtio';
1e3baf05 2319
cc4d6182
DA
2320 if ($bootindex_hash->{n}) {
2321 $d->{bootindex} = $bootindex_hash->{n};
2322 $bootindex_hash->{n} += 1;
2323 }
1e3baf05 2324
cc4d6182
DA
2325 my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i");
2326 push @$cmd, '-netdev', $netdevfull;
1e3baf05 2327
cc4d6182
DA
2328 my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i");
2329 push @$cmd, '-device', $netdevicefull;
19672434
DM
2330 }
2331
1e3baf05
DM
2332
2333 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2334 # when the VM uses virtio devices.
19672434
DM
2335 if (!$use_virtio && $have_ovz) {
2336
6b64503e 2337 my $cpuunits = defined($conf->{cpuunits}) ?
1e3baf05
DM
2338 $conf->{cpuunits} : $defaults->{cpuunits};
2339
2340 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2341
2342 # fixme: cpulimit is currently ignored
2343 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2344 }
2345
2346 # add custom args
2347 if ($conf->{args}) {
3ada46c9 2348 my $aa = PVE::Tools::split_args($conf->{args});
1e3baf05
DM
2349 push @$cmd, @$aa;
2350 }
2351
2352 return wantarray ? ($cmd, $vollist) : $cmd;
2353}
19672434 2354
1e3baf05
DM
2355sub vnc_socket {
2356 my ($vmid) = @_;
2357 return "${var_run_tmpdir}/$vmid.vnc";
2358}
2359
c971c4f2
AD
2360sub qmp_socket {
2361 my ($vmid) = @_;
2362 return "${var_run_tmpdir}/$vmid.qmp";
2363}
2364
1e3baf05
DM
2365sub pidfile_name {
2366 my ($vmid) = @_;
2367 return "${var_run_tmpdir}/$vmid.pid";
2368}
2369
1e3baf05
DM
2370sub next_migrate_port {
2371
2372 for (my $p = 60000; $p < 60010; $p++) {
2373
6b64503e
DM
2374 my $sock = IO::Socket::INET->new(Listen => 5,
2375 LocalAddr => 'localhost',
2376 LocalPort => $p,
2377 ReuseAddr => 1,
2378 Proto => 0);
1e3baf05
DM
2379
2380 if ($sock) {
6b64503e 2381 close($sock);
1e3baf05
DM
2382 return $p;
2383 }
2384 }
2385
2386 die "unable to find free migration port";
2387}
2388
86fdcfb2
DA
2389sub vm_devices_list {
2390 my ($vmid) = @_;
2391
ceea9078
DM
2392 my $res = vm_mon_cmd($vmid, 'query-pci');
2393
2394 my $devices = {};
2395 foreach my $pcibus (@$res) {
2396 foreach my $device (@{$pcibus->{devices}}) {
2397 next if !$device->{'qdev_id'};
2398 $devices->{$device->{'qdev_id'}} = $device;
1dc4f496
DM
2399 }
2400 }
86fdcfb2 2401
1dc4f496 2402 return $devices;
86fdcfb2
DA
2403}
2404
ec21aa11 2405sub vm_deviceplug {
f19d1c47 2406 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
ae57f6b3 2407
2630d2a9 2408 return 1 if !check_running($vmid) || !$conf->{hotplug};
afdb31d5 2409
95d6343b
DA
2410 my $devices_list = vm_devices_list($vmid);
2411 return 1 if defined($devices_list->{$deviceid});
2412
5e5dcb73
DA
2413 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2414 return undef if !qemu_driveadd($storecfg, $vmid, $device);
1dc4f496 2415 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
5e5dcb73
DA
2416 qemu_deviceadd($vmid, $devicefull);
2417 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2418 qemu_drivedel($vmid, $deviceid);
2419 return undef;
2420 }
f19d1c47 2421 }
cfc817c7
DA
2422
2423 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2424 my $pciaddr = print_pci_addr($deviceid);
2425 my $devicefull = "lsi,id=$deviceid$pciaddr";
2426 qemu_deviceadd($vmid, $devicefull);
2427 return undef if(!qemu_deviceaddverify($vmid, $deviceid));
2428 }
2429
a4f091a0
DA
2430 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2431 return undef if !qemu_findorcreatelsi($storecfg,$conf, $vmid, $device);
2432 return undef if !qemu_driveadd($storecfg, $vmid, $device);
2433 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
2434 if(!qemu_deviceadd($vmid, $devicefull)) {
2435 qemu_drivedel($vmid, $deviceid);
2436 return undef;
2437 }
2438 }
2439
2630d2a9
DA
2440 if ($deviceid =~ m/^(net)(\d+)$/) {
2441 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
2442 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
2443 qemu_deviceadd($vmid, $netdevicefull);
2444 if(!qemu_deviceaddverify($vmid, $deviceid)) {
2445 qemu_netdevdel($vmid, $deviceid);
2446 return undef;
2447 }
2448 }
2449
5e5dcb73 2450 return 1;
a4dea331
DA
2451}
2452
ec21aa11 2453sub vm_deviceunplug {
f19d1c47 2454 my ($vmid, $conf, $deviceid) = @_;
873c2d69 2455
5e5dcb73 2456 return 1 if !check_running ($vmid) || !$conf->{hotplug};
873c2d69 2457
95d6343b
DA
2458 my $devices_list = vm_devices_list($vmid);
2459 return 1 if !defined($devices_list->{$deviceid});
2460
ae57f6b3 2461 die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
f19d1c47 2462
5e5dcb73
DA
2463 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2464 return undef if !qemu_drivedel($vmid, $deviceid);
2465 qemu_devicedel($vmid, $deviceid);
2466 return undef if !qemu_devicedelverify($vmid, $deviceid);
2467 }
cfc817c7
DA
2468
2469 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2470 return undef if !qemu_devicedel($vmid, $deviceid);
2471 }
2472
a4f091a0
DA
2473 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2474 return undef if !qemu_devicedel($vmid, $deviceid);
2475 return undef if !qemu_drivedel($vmid, $deviceid);
2476 }
2477
2630d2a9
DA
2478 if ($deviceid =~ m/^(net)(\d+)$/) {
2479 return undef if !qemu_netdevdel($vmid, $deviceid);
2480 qemu_devicedel($vmid, $deviceid);
2481 return undef if !qemu_devicedelverify($vmid, $deviceid);
2482 }
2483
5e5dcb73
DA
2484 return 1;
2485}
2486
2487sub qemu_deviceadd {
2488 my ($vmid, $devicefull) = @_;
873c2d69 2489
7b7c6d1b 2490 my $ret = vm_human_monitor_command($vmid, "device_add $devicefull");
5e5dcb73 2491 $ret =~ s/^\s+//;
afdb31d5 2492 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
5e5dcb73
DA
2493 return 1 if $ret eq "";
2494 syslog("err", "error on hotplug device : $ret");
2495 return undef;
f19d1c47 2496
5e5dcb73 2497}
afdb31d5 2498
5e5dcb73
DA
2499sub qemu_devicedel {
2500 my($vmid, $deviceid) = @_;
f19d1c47 2501
7b7c6d1b 2502 my $ret = vm_human_monitor_command($vmid, "device_del $deviceid");
5e5dcb73
DA
2503 $ret =~ s/^\s+//;
2504 return 1 if $ret eq "";
2505 syslog("err", "detaching device $deviceid failed : $ret");
2506 return undef;
2507}
2508
2509sub qemu_driveadd {
2510 my($storecfg, $vmid, $device) = @_;
2511
2512 my $drive = print_drive_full($storecfg, $vmid, $device);
7b7c6d1b 2513 my $ret = vm_human_monitor_command($vmid, "drive_add auto $drive");
5e5dcb73
DA
2514 # If the command succeeds qemu prints: "OK"
2515 if ($ret !~ m/OK/s) {
2516 syslog("err", "adding drive failed: $ret");
2517 return undef;
f19d1c47 2518 }
5e5dcb73
DA
2519 return 1;
2520}
afdb31d5 2521
5e5dcb73
DA
2522sub qemu_drivedel {
2523 my($vmid, $deviceid) = @_;
873c2d69 2524
7b7c6d1b 2525 my $ret = vm_human_monitor_command($vmid, "drive_del drive-$deviceid");
5e5dcb73
DA
2526 $ret =~ s/^\s+//;
2527 if ($ret =~ m/Device \'.*?\' not found/s) {
afdb31d5 2528 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
5e5dcb73
DA
2529 }
2530 elsif ($ret ne "") {
2531 syslog("err", "deleting drive $deviceid failed : $ret");
2532 return undef;
873c2d69 2533 }
5e5dcb73
DA
2534 return 1;
2535}
f19d1c47 2536
5e5dcb73
DA
2537sub qemu_deviceaddverify {
2538 my ($vmid,$deviceid) = @_;
873c2d69 2539
5e5dcb73
DA
2540 for (my $i = 0; $i <= 5; $i++) {
2541 my $devices_list = vm_devices_list($vmid);
2542 return 1 if defined($devices_list->{$deviceid});
2543 sleep 1;
afdb31d5 2544 }
5e5dcb73
DA
2545 syslog("err", "error on hotplug device $deviceid");
2546 return undef;
2547}
afdb31d5 2548
5e5dcb73
DA
2549
2550sub qemu_devicedelverify {
2551 my ($vmid,$deviceid) = @_;
2552
2553 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2554 for (my $i = 0; $i <= 5; $i++) {
2555 my $devices_list = vm_devices_list($vmid);
2556 return 1 if !defined($devices_list->{$deviceid});
2557 sleep 1;
afdb31d5 2558 }
5e5dcb73
DA
2559 syslog("err", "error on hot-unplugging device $deviceid");
2560 return undef;
873c2d69
DA
2561}
2562
cfc817c7
DA
2563sub qemu_findorcreatelsi {
2564 my ($storecfg, $conf, $vmid, $device) = @_;
2565
2566 my $maxdev = 7;
2567 my $controller = int($device->{index} / $maxdev);
2568 my $lsiid="lsi$controller";
2569 my $devices_list = vm_devices_list($vmid);
2570
2571 if(!defined($devices_list->{$lsiid})) {
2572 return undef if !vm_deviceplug($storecfg, $conf, $vmid, $lsiid);
2573 }
2574 return 1;
2575}
2576
2630d2a9
DA
2577sub qemu_netdevadd {
2578 my ($vmid, $conf, $device, $deviceid) = @_;
2579
2580 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
7b7c6d1b 2581 my $ret = vm_human_monitor_command($vmid, "netdev_add $netdev");
2630d2a9
DA
2582 $ret =~ s/^\s+//;
2583
97d62eb7 2584 #if the command succeeds, no output is sent. So any non-empty string shows an error
2630d2a9
DA
2585 return 1 if $ret eq "";
2586 syslog("err", "adding netdev failed: $ret");
2587 return undef;
2588}
2589
2590sub qemu_netdevdel {
2591 my ($vmid, $deviceid) = @_;
2592
7b7c6d1b 2593 my $ret = vm_human_monitor_command($vmid, "netdev_del $deviceid");
2630d2a9 2594 $ret =~ s/^\s+//;
97d62eb7 2595 #if the command succeeds, no output is sent. So any non-empty string shows an error
2630d2a9
DA
2596 return 1 if $ret eq "";
2597 syslog("err", "deleting netdev failed: $ret");
2598 return undef;
2599}
2600
affd2f88
AD
2601sub qemu_block_set_io_throttle {
2602 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2603
2604 $bps = 0 if !$bps;
2605 $bps_rd = 0 if !$bps_rd;
2606 $bps_wr = 0 if !$bps_wr;
2607 $iops = 0 if !$iops;
2608 $iops_rd = 0 if !$iops_rd;
2609 $iops_wr = 0 if !$iops_wr;
2610
6f1dbbea 2611 my $ret = vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid, bps => $bps, bps_rd => $bps_rd, bps_wr => $bps_wr, iops => $iops, iops_rd => $iops_rd, iops_wr => $iops_wr);
affd2f88
AD
2612 $ret =~ s/^\s+//;
2613 return 1 if $ret eq "";
2614 syslog("err", "error setting block_set_io_throttle: $ret");
2615 return undef;
2616}
2617
1e3baf05
DM
2618sub vm_start {
2619 my ($storecfg, $vmid, $statefile, $skiplock) = @_;
2620
6b64503e
DM
2621 lock_config($vmid, sub {
2622 my $conf = load_config($vmid);
1e3baf05 2623
6b64503e 2624 check_lock($conf) if !$skiplock;
1e3baf05 2625
ff1a2432 2626 die "VM $vmid already running\n" if check_running($vmid);
1e3baf05
DM
2627
2628 my $migrate_uri;
2629 my $migrate_port = 0;
2630
2631 if ($statefile) {
2632 if ($statefile eq 'tcp') {
2633 $migrate_port = next_migrate_port();
2634 $migrate_uri = "tcp:localhost:${migrate_port}";
2635 } else {
2636 if (-f $statefile) {
2637 $migrate_uri = "exec:cat $statefile";
2638 } else {
2639 warn "state file '$statefile' does not exist - doing normal startup\n";
2640 }
2641 }
2642 }
2643
2644 my $defaults = load_defaults();
2645
e6c3b671 2646 my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $migrate_uri);
1e3baf05 2647 # host pci devices
040b06b7
DA
2648 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2649 my $d = parse_hostpci($conf->{"hostpci$i"});
2650 next if !$d;
2651 my $info = pci_device_info("0000:$d->{pciid}");
2652 die "IOMMU not present\n" if !check_iommu_support();
2653 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2654 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
2655 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
2656 }
1e3baf05
DM
2657
2658 PVE::Storage::activate_volumes($storecfg, $vollist);
2659
6b64503e 2660 eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
1e3baf05 2661 my $err = $@;
ff1a2432 2662 die "start failed: $err" if $err;
1e3baf05
DM
2663
2664 if ($statefile) {
2665
2666 if ($statefile eq 'tcp') {
2667 print "migration listens on port $migrate_port\n";
2668 } else {
2669 unlink $statefile;
2670 # fixme: send resume - is that necessary ?
60816474 2671 eval { vm_mon_cmd($vmid, "cont"); };
1e3baf05
DM
2672 }
2673 }
afdb31d5 2674
48e1a963
DM
2675 # always set migrate speed (overwrite kvm default of 32m)
2676 # we set a very hight default of 8192m which is basically unlimited
2677 my $migrate_speed = $defaults->{migrate_speed} || 8192;
2678 $migrate_speed = $conf->{migrate_speed} || $migrate_speed;
2f674c7a 2679 $migrate_speed = $migrate_speed * 1048576;
afdb31d5 2680 eval {
2f674c7a 2681 vm_mon_cmd($vmid, "migrate_set_speed", value => $migrate_speed);
48e1a963 2682 };
1e3baf05 2683
71c11a83
DM
2684 my $migrate_downtime = $defaults->{migrate_downtime};
2685 $migrate_downtime = $conf->{migrate_downtime} if defined($conf->{migrate_downtime});
2686 if (defined($migrate_downtime)) {
bcb7c9cf 2687 eval { vm_mon_cmd($vmid, "migrate_set_downtime", value => $migrate_downtime); };
1e3baf05 2688 }
e6c3b671 2689
7878afeb 2690 vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
ce332eeb 2691
1e3baf05
DM
2692 });
2693}
2694
0eedc444
AD
2695sub vm_mon_cmd {
2696 my ($vmid, $execute, %params) = @_;
2697
26f11676
DM
2698 my $cmd = { execute => $execute, arguments => \%params };
2699 vm_qmp_command($vmid, $cmd);
0eedc444
AD
2700}
2701
2702sub vm_mon_cmd_nocheck {
2703 my ($vmid, $execute, %params) = @_;
2704
26f11676
DM
2705 my $cmd = { execute => $execute, arguments => \%params };
2706 vm_qmp_command($vmid, $cmd, 1);
0eedc444
AD
2707}
2708
c971c4f2 2709sub vm_qmp_command {
d967756b 2710 my ($vmid, $cmd, $nocheck) = @_;
97d62eb7 2711
c971c4f2 2712 my $res;
26f11676 2713
c971c4f2
AD
2714 eval {
2715 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
2716
26f11676 2717 my $qmpclient = PVE::QMPClient->new();
c971c4f2 2718
26f11676 2719 $res = $qmpclient->cmd($vmid, $cmd);
c971c4f2 2720
c971c4f2 2721 };
26f11676 2722 if (my $err = $@) {
c971c4f2
AD
2723 syslog("err", "VM $vmid qmp command failed - $err");
2724 die $err;
2725 }
2726
2727 return $res;
2728}
2729
9df5cbcc
DM
2730sub vm_human_monitor_command {
2731 my ($vmid, $cmdline) = @_;
2732
2733 my $res;
2734
2735 my $cmd = {
2736 execute => 'human-monitor-command',
2737 arguments => { 'command-line' => $cmdline},
2738 };
2739
2740 return vm_qmp_command($vmid, $cmd);
2741}
2742
1e3baf05
DM
2743sub vm_commandline {
2744 my ($storecfg, $vmid) = @_;
2745
6b64503e 2746 my $conf = load_config($vmid);
1e3baf05
DM
2747
2748 my $defaults = load_defaults();
2749
6b64503e 2750 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 2751
6b64503e 2752 return join(' ', @$cmd);
1e3baf05
DM
2753}
2754
2755sub vm_reset {
2756 my ($vmid, $skiplock) = @_;
2757
6b64503e 2758 lock_config($vmid, sub {
1e3baf05 2759
6b64503e 2760 my $conf = load_config($vmid);
1e3baf05 2761
6b64503e 2762 check_lock($conf) if !$skiplock;
1e3baf05 2763
816e2c4a 2764 vm_mon_cmd($vmid, "system_reset");
ff1a2432
DM
2765 });
2766}
2767
2768sub get_vm_volumes {
2769 my ($conf) = @_;
1e3baf05 2770
ff1a2432
DM
2771 my $vollist = [];
2772 foreach_drive($conf, sub {
2773 my ($ds, $drive) = @_;
2774
2775 my ($sid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
2776 return if !$sid;
2777
2778 my $volid = $drive->{file};
2779 return if !$volid || $volid =~ m|^/|;
2780
2781 push @$vollist, $volid;
1e3baf05 2782 });
ff1a2432
DM
2783
2784 return $vollist;
2785}
2786
2787sub vm_stop_cleanup {
254575e9 2788 my ($storecfg, $vmid, $conf, $keepActive) = @_;
ff1a2432 2789
745fed70
DM
2790 eval {
2791 fairsched_rmnod($vmid); # try to destroy group
ff1a2432 2792
254575e9
DM
2793 if (!$keepActive) {
2794 my $vollist = get_vm_volumes($conf);
2795 PVE::Storage::deactivate_volumes($storecfg, $vollist);
2796 }
961bfcb2
DM
2797
2798 foreach my $ext (qw(mon pid vnc)) {
2799 unlink "/var/run/qemu-server/${vmid}.$ext";
2800 }
745fed70
DM
2801 };
2802 warn $@ if $@; # avoid errors - just warn
1e3baf05
DM
2803}
2804
e6c3b671 2805# Note: use $nockeck to skip tests if VM configuration file exists.
254575e9
DM
2806# We need that when migration VMs to other nodes (files already moved)
2807# Note: we set $keepActive in vzdump stop mode - volumes need to stay active
1e3baf05 2808sub vm_stop {
254575e9 2809 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive) = @_;
9269013a
DM
2810
2811 $timeout = 60 if !defined($timeout);
ff1a2432 2812
9269013a 2813 $force = 1 if !defined($force) && !$shutdown;
1e3baf05 2814
e6c3b671 2815 lock_config($vmid, sub {
1e3baf05 2816
e6c3b671 2817 my $pid = check_running($vmid, $nocheck);
ff1a2432 2818 return if !$pid;
1e3baf05 2819
ff1a2432 2820 my $conf;
e6c3b671 2821 if (!$nocheck) {
ff1a2432 2822 $conf = load_config($vmid);
e6c3b671
DM
2823 check_lock($conf) if !$skiplock;
2824 }
19672434 2825
9269013a
DM
2826 eval {
2827 if ($shutdown) {
988903ca 2828 $nocheck ? vm_mon_cmd_nocheck($vmid, "system_powerdown") : vm_mon_cmd($vmid, "system_powerdown");
bcb7c9cf 2829
9269013a 2830 } else {
988903ca 2831 $nocheck ? vm_mon_cmd_nocheck($vmid, "quit") : vm_mon_cmd($vmid, "quit");
afdb31d5 2832 }
9269013a 2833 };
1e3baf05
DM
2834 my $err = $@;
2835
2836 if (!$err) {
1e3baf05 2837 my $count = 0;
e6c3b671 2838 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
2839 $count++;
2840 sleep 1;
2841 }
2842
2843 if ($count >= $timeout) {
9269013a
DM
2844 if ($force) {
2845 warn "VM still running - terminating now with SIGTERM\n";
2846 kill 15, $pid;
2847 } else {
2848 die "VM quit/powerdown failed - got timeout\n";
2849 }
2850 } else {
254575e9 2851 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
9269013a 2852 return;
1e3baf05
DM
2853 }
2854 } else {
9269013a
DM
2855 if ($force) {
2856 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
2857 kill 15, $pid;
2858 } else {
afdb31d5 2859 die "VM quit/powerdown failed\n";
9269013a 2860 }
1e3baf05
DM
2861 }
2862
2863 # wait again
ff1a2432 2864 $timeout = 10;
1e3baf05
DM
2865
2866 my $count = 0;
e6c3b671 2867 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
2868 $count++;
2869 sleep 1;
2870 }
2871
2872 if ($count >= $timeout) {
ff1a2432 2873 warn "VM still running - terminating now with SIGKILL\n";
1e3baf05 2874 kill 9, $pid;
ff1a2432 2875 sleep 1;
1e3baf05
DM
2876 }
2877
254575e9 2878 vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive) if $conf;
ff1a2432 2879 });
1e3baf05
DM
2880}
2881
2882sub vm_suspend {
2883 my ($vmid, $skiplock) = @_;
2884
6b64503e 2885 lock_config($vmid, sub {
1e3baf05 2886
6b64503e 2887 my $conf = load_config($vmid);
1e3baf05 2888
6b64503e 2889 check_lock($conf) if !$skiplock;
bcb7c9cf 2890
f77f91f3 2891 vm_mon_cmd($vmid, "stop");
1e3baf05
DM
2892 });
2893}
2894
2895sub vm_resume {
2896 my ($vmid, $skiplock) = @_;
2897
6b64503e 2898 lock_config($vmid, sub {
1e3baf05 2899
6b64503e 2900 my $conf = load_config($vmid);
1e3baf05 2901
6b64503e 2902 check_lock($conf) if !$skiplock;
1e3baf05 2903
12060fe8 2904 vm_mon_cmd($vmid, "cont");
1e3baf05
DM
2905 });
2906}
2907
5fdbe4f0
DM
2908sub vm_sendkey {
2909 my ($vmid, $skiplock, $key) = @_;
1e3baf05 2910
6b64503e 2911 lock_config($vmid, sub {
1e3baf05 2912
6b64503e 2913 my $conf = load_config($vmid);
7b7c6d1b
DM
2914
2915 # there is no qmp command, so we use the human monitor command
2916 vm_human_monitor_command($vmid, "sendkey $key");
1e3baf05
DM
2917 });
2918}
2919
2920sub vm_destroy {
2921 my ($storecfg, $vmid, $skiplock) = @_;
2922
6b64503e 2923 lock_config($vmid, sub {
1e3baf05 2924
6b64503e 2925 my $conf = load_config($vmid);
1e3baf05 2926
6b64503e 2927 check_lock($conf) if !$skiplock;
1e3baf05 2928
ff1a2432
DM
2929 if (!check_running($vmid)) {
2930 fairsched_rmnod($vmid); # try to destroy group
2931 destroy_vm($storecfg, $vmid);
2932 } else {
2933 die "VM $vmid is running - destroy failed\n";
1e3baf05
DM
2934 }
2935 });
2936}
2937
1e3baf05
DM
2938# pci helpers
2939
2940sub file_write {
2941 my ($filename, $buf) = @_;
2942
6b64503e 2943 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
2944 return undef if !$fh;
2945
2946 my $res = print $fh $buf;
2947
2948 $fh->close();
2949
2950 return $res;
2951}
2952
2953sub pci_device_info {
2954 my ($name) = @_;
2955
2956 my $res;
2957
2958 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
2959 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
2960
2961 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
2962 return undef if !defined($irq) || $irq !~ m/^\d+$/;
2963
2964 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
2965 return undef if !defined($vendor) || $vendor !~ s/^0x//;
2966
2967 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
2968 return undef if !defined($product) || $product !~ s/^0x//;
2969
2970 $res = {
2971 name => $name,
2972 vendor => $vendor,
2973 product => $product,
2974 domain => $domain,
2975 bus => $bus,
2976 slot => $slot,
2977 func => $func,
2978 irq => $irq,
2979 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
2980 };
2981
2982 return $res;
2983}
2984
2985sub pci_dev_reset {
2986 my ($dev) = @_;
2987
2988 my $name = $dev->{name};
2989
2990 my $fn = "$pcisysfs/devices/$name/reset";
2991
6b64503e 2992 return file_write($fn, "1");
1e3baf05
DM
2993}
2994
2995sub pci_dev_bind_to_stub {
2996 my ($dev) = @_;
2997
2998 my $name = $dev->{name};
2999
3000 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3001 return 1 if -d $testdir;
3002
3003 my $data = "$dev->{vendor} $dev->{product}";
6b64503e 3004 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
1e3baf05
DM
3005
3006 my $fn = "$pcisysfs/devices/$name/driver/unbind";
6b64503e 3007 if (!file_write($fn, $name)) {
1e3baf05
DM
3008 return undef if -f $fn;
3009 }
3010
3011 $fn = "$pcisysfs/drivers/pci-stub/bind";
3012 if (! -d $testdir) {
6b64503e 3013 return undef if !file_write($fn, $name);
1e3baf05
DM
3014 }
3015
3016 return -d $testdir;
3017}
3018
afdb31d5 3019sub print_pci_addr {
72a063e4 3020 my ($id) = @_;
6b64503e 3021
72a063e4 3022 my $res = '';
6b64503e 3023 my $devices = {
e5f7f8ed
DA
3024 #addr1 : ide,parallel,serial (motherboard)
3025 #addr2 : first videocard
13b5a753 3026 balloon0 => { bus => 0, addr => 3 },
0a40e8ea 3027 watchdog => { bus => 0, addr => 4 },
69b6ae0c
DA
3028 lsi0 => { bus => 0, addr => 5 },
3029 lsi1 => { bus => 0, addr => 6 },
26ee04b6 3030 ahci0 => { bus => 0, addr => 7 },
6b64503e
DM
3031 virtio0 => { bus => 0, addr => 10 },
3032 virtio1 => { bus => 0, addr => 11 },
3033 virtio2 => { bus => 0, addr => 12 },
3034 virtio3 => { bus => 0, addr => 13 },
3035 virtio4 => { bus => 0, addr => 14 },
3036 virtio5 => { bus => 0, addr => 15 },
b78ebef7
DA
3037 hostpci0 => { bus => 0, addr => 16 },
3038 hostpci1 => { bus => 0, addr => 17 },
f290f8d9
DA
3039 net0 => { bus => 0, addr => 18 },
3040 net1 => { bus => 0, addr => 19 },
3041 net2 => { bus => 0, addr => 20 },
3042 net3 => { bus => 0, addr => 21 },
3043 net4 => { bus => 0, addr => 22 },
3044 net5 => { bus => 0, addr => 23 },
e5f7f8ed 3045 #addr29 : usb-host (pve-usb.cfg)
6b64503e
DM
3046 };
3047
3048 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
72a063e4
DA
3049 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
3050 $res = ",bus=pci.$devices->{$id}->{bus},addr=$addr";
3051 }
3052 return $res;
3053
3054}
3055
13a48620 3056sub vm_balloonset {
7878afeb 3057 my ($vmid, $value) = @_;
13a48620 3058
2d23ddc5 3059 vm_mon_cmd($vmid, "balloon", value => $value);
13a48620
DA
3060}
3061
3e16d5fc
DM
3062# vzdump restore implementaion
3063
3064sub archive_read_firstfile {
3065 my $archive = shift;
afdb31d5 3066
3e16d5fc
DM
3067 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
3068
3069 # try to detect archive type first
3070 my $pid = open (TMP, "tar tf '$archive'|") ||
3071 die "unable to open file '$archive'\n";
3072 my $firstfile = <TMP>;
3073 kill 15, $pid;
3074 close TMP;
3075
3076 die "ERROR: archive contaions no data\n" if !$firstfile;
3077 chomp $firstfile;
3078
3079 return $firstfile;
3080}
3081
3082sub restore_cleanup {
3083 my $statfile = shift;
3084
3085 print STDERR "starting cleanup\n";
3086
3087 if (my $fd = IO::File->new($statfile, "r")) {
3088 while (defined(my $line = <$fd>)) {
3089 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3090 my $volid = $2;
3091 eval {
3092 if ($volid =~ m|^/|) {
3093 unlink $volid || die 'unlink failed\n';
3094 } else {
3095 my $cfg = cfs_read_file('storage.cfg');
3096 PVE::Storage::vdisk_free($cfg, $volid);
3097 }
afdb31d5 3098 print STDERR "temporary volume '$volid' sucessfuly removed\n";
3e16d5fc
DM
3099 };
3100 print STDERR "unable to cleanup '$volid' - $@" if $@;
3101 } else {
3102 print STDERR "unable to parse line in statfile - $line";
afdb31d5 3103 }
3e16d5fc
DM
3104 }
3105 $fd->close();
3106 }
3107}
3108
3109sub restore_archive {
a0d1b1a2 3110 my ($archive, $vmid, $user, $opts) = @_;
3e16d5fc 3111
9c502e26
DM
3112 if ($archive ne '-') {
3113 my $firstfile = archive_read_firstfile($archive);
3114 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3115 if $firstfile ne 'qemu-server.conf';
3116 }
3e16d5fc
DM
3117
3118 my $tocmd = "/usr/lib/qemu-server/qmextract";
3119
2415a446 3120 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
a0d1b1a2 3121 $tocmd .= " --pool " . PVE::Tools::shellquote($opts->{pool}) if $opts->{pool};
3e16d5fc
DM
3122 $tocmd .= ' --prealloc' if $opts->{prealloc};
3123 $tocmd .= ' --info' if $opts->{info};
3124
a0d1b1a2 3125 # tar option "xf" does not autodetect compression when read from STDIN,
9c502e26 3126 # so we pipe to zcat
2415a446
DM
3127 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
3128 PVE::Tools::shellquote("--to-command=$tocmd");
3e16d5fc
DM
3129
3130 my $tmpdir = "/var/tmp/vzdumptmp$$";
3131 mkpath $tmpdir;
3132
3133 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
3134 local $ENV{VZDUMP_VMID} = $vmid;
a0d1b1a2 3135 local $ENV{VZDUMP_USER} = $user;
3e16d5fc
DM
3136
3137 my $conffile = PVE::QemuServer::config_file($vmid);
3138 my $tmpfn = "$conffile.$$.tmp";
3139
3140 # disable interrupts (always do cleanups)
3141 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
3142 print STDERR "got interrupt - ignored\n";
3143 };
3144
afdb31d5 3145 eval {
3e16d5fc
DM
3146 # enable interrupts
3147 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
3148 die "interrupted by signal\n";
3149 };
3150
9c502e26
DM
3151 if ($archive eq '-') {
3152 print "extracting archive from STDIN\n";
3153 run_command($cmd, input => "<&STDIN");
3154 } else {
3155 print "extracting archive '$archive'\n";
3156 run_command($cmd);
3157 }
3e16d5fc
DM
3158
3159 return if $opts->{info};
3160
3161 # read new mapping
3162 my $map = {};
3163 my $statfile = "$tmpdir/qmrestore.stat";
3164 if (my $fd = IO::File->new($statfile, "r")) {
3165 while (defined (my $line = <$fd>)) {
3166 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3167 $map->{$1} = $2 if $1;
3168 } else {
3169 print STDERR "unable to parse line in statfile - $line\n";
3170 }
3171 }
3172 $fd->close();
3173 }
3174
3175 my $confsrc = "$tmpdir/qemu-server.conf";
3176
3177 my $srcfd = new IO::File($confsrc, "r") ||
3178 die "unable to open file '$confsrc'\n";
3179
3180 my $outfd = new IO::File ($tmpfn, "w") ||
3181 die "unable to write config for VM $vmid\n";
3182
51586c3a
DM
3183 my $netcount = 0;
3184
3e16d5fc
DM
3185 while (defined (my $line = <$srcfd>)) {
3186 next if $line =~ m/^\#vzdump\#/;
3187 next if $line =~ m/^lock:/;
3188 next if $line =~ m/^unused\d+:/;
3189
51586c3a
DM
3190 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3191 # try to convert old 1.X settings
3192 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3193 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3194 my ($model, $macaddr) = split(/\=/, $devconfig);
3195 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $opts->{unique};
3196 my $net = {
3197 model => $model,
3198 bridge => "vmbr$ind",
3199 macaddr => $macaddr,
3200 };
3201 my $netstr = print_net($net);
3202 print $outfd "net${netcount}: $netstr\n";
3203 $netcount++;
3204 }
3205 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && ($opts->{unique})) {
3206 my ($id, $netstr) = ($1, $2);
3207 my $net = parse_net($netstr);
3208 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3209 $netstr = print_net($net);
afdb31d5 3210 print $outfd "$id: $netstr\n";
51586c3a 3211 } elsif ($line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/) {
3e16d5fc
DM
3212 my $virtdev = $1;
3213 my $value = $2;
3214 if ($line =~ m/backup=no/) {
3215 print $outfd "#$line";
3216 } elsif ($virtdev && $map->{$virtdev}) {
3217 my $di = PVE::QemuServer::parse_drive($virtdev, $value);
3218 $di->{file} = $map->{$virtdev};
3219 $value = PVE::QemuServer::print_drive($vmid, $di);
3220 print $outfd "$virtdev: $value\n";
3221 } else {
3222 print $outfd $line;
3223 }
3224 } else {
3225 print $outfd $line;
3226 }
3227 }
3228
3229 $srcfd->close();
3230 $outfd->close();
3231 };
3232 my $err = $@;
3233
afdb31d5 3234 if ($err) {
3e16d5fc
DM
3235
3236 unlink $tmpfn;
3237
3238 restore_cleanup("$tmpdir/qmrestore.stat") if !$opts->{info};
afdb31d5 3239
3e16d5fc 3240 die $err;
afdb31d5 3241 }
3e16d5fc
DM
3242
3243 rmtree $tmpdir;
3244
3245 rename $tmpfn, $conffile ||
3246 die "unable to commit configuration file '$conffile'\n";
3247};
3248
1e3baf05 32491;