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