]> git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer.pm
e0ec830e0d92d12b1b99d74310c7f7f6b5297c97
[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 => 'boolean',
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|unsafe] [,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|block] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,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|unsafe] [,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 sub disk_devive_info {
641 my $dev = shift;
642
643 die "unknown disk device format '$dev'" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/;
644
645 my $bus = $1;
646 my $index = $2;
647 my $maxdev = 1024;
648
649 if ($bus eq 'ide') {
650 $maxdev = 2;
651 } elsif ($bus eq 'scsi') {
652 $maxdev = 7;
653 }
654
655 my $controller = int($index / $maxdev);
656 my $unit = $index % $maxdev;
657
658
659 return { bus => $bus, desc => uc($bus) . " $controller:$unit",
660 controller => $controller, unit => $unit, index => $index };
661
662 }
663
664 sub qemu_drive_name {
665 my ($dev, $media) = @_;
666
667 my $info = disk_devive_info($dev);
668 my $mediastr = '';
669
670 if (($info->{bus} eq 'ide') || ($info->{bus} eq 'scsi')) {
671 $mediastr = ($media eq 'cdrom') ? "-cd" : "-hd";
672 return sprintf("%s%i%s%i", $info->{bus}, $info->{controller},
673 $mediastr, $info->{unit});
674 } else {
675 return sprintf("%s%i", $info->{bus}, $info->{index});
676 }
677 }
678
679 my $cdrom_path;
680
681 sub get_cdrom_path {
682
683 return $cdrom_path if $cdrom_path;
684
685 return $cdrom_path = "/dev/cdrom" if -l "/dev/cdrom";
686 return $cdrom_path = "/dev/cdrom1" if -l "/dev/cdrom1";
687 return $cdrom_path = "/dev/cdrom2" if -l "/dev/cdrom2";
688 }
689
690 sub get_iso_path {
691 my ($storecfg, $vmid, $cdrom) = @_;
692
693 if ($cdrom eq 'cdrom') {
694 return get_cdrom_path();
695 } elsif ($cdrom eq 'none') {
696 return '';
697 } elsif ($cdrom =~ m|^/|) {
698 return $cdrom;
699 } else {
700 return PVE::Storage::path($storecfg, $cdrom);
701 }
702 }
703
704 # try to convert old style file names to volume IDs
705 sub filename_to_volume_id {
706 my ($vmid, $file, $media) = @_;
707
708 if (!($file eq 'none' || $file eq 'cdrom' ||
709 $file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
710
711 return undef if $file =~ m|/|;
712
713 if ($media && $media eq 'cdrom') {
714 $file = "local:iso/$file";
715 } else {
716 $file = "local:$vmid/$file";
717 }
718 }
719
720 return $file;
721 }
722
723 sub verify_media_type {
724 my ($opt, $vtype, $media) = @_;
725
726 return if !$media;
727
728 my $etype;
729 if ($media eq 'disk') {
730 $etype = 'image';
731 } elsif ($media eq 'cdrom') {
732 $etype = 'iso';
733 } else {
734 die "internal error";
735 }
736
737 return if ($vtype eq $etype);
738
739 raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
740 }
741
742 sub cleanup_drive_path {
743 my ($opt, $storecfg, $drive) = @_;
744
745 # try to convert filesystem paths to volume IDs
746
747 if (($drive->{file} !~ m/^(cdrom|none)$/) &&
748 ($drive->{file} !~ m|^/dev/.+|) &&
749 ($drive->{file} !~ m/^([^:]+):(.+)$/) &&
750 ($drive->{file} !~ m/^\d+$/)) {
751 my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
752 raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
753 $drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
754 verify_media_type($opt, $vtype, $drive->{media});
755 $drive->{file} = $volid;
756 }
757
758 $drive->{media} = 'cdrom' if !$drive->{media} && $drive->{file} =~ m/^(cdrom|none)$/;
759 }
760
761 sub create_conf_nolock {
762 my ($vmid, $settings) = @_;
763
764 my $filename = config_file($vmid);
765
766 die "configuration file '$filename' already exists\n" if -f $filename;
767
768 my $defaults = load_defaults();
769
770 $settings->{name} = "vm$vmid" if !$settings->{name};
771 $settings->{memory} = $defaults->{memory} if !$settings->{memory};
772
773 my $data = '';
774 foreach my $opt (keys %$settings) {
775 next if !$confdesc->{$opt};
776
777 my $value = $settings->{$opt};
778 next if !$value;
779
780 $data .= "$opt: $value\n";
781 }
782
783 PVE::Tools::file_set_contents($filename, $data);
784 }
785
786 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
787 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
788 # [,aio=native|threads]
789
790 sub parse_drive {
791 my ($key, $data) = @_;
792
793 my $res = {};
794
795 # $key may be undefined - used to verify JSON parameters
796 if (!defined($key)) {
797 $res->{interface} = 'unknown'; # should not harm when used to verify parameters
798 $res->{index} = 0;
799 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
800 $res->{interface} = $1;
801 $res->{index} = $2;
802 } else {
803 return undef;
804 }
805
806 foreach my $p (split (/,/, $data)) {
807 next if $p =~ m/^\s*$/;
808
809 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/) {
810 my ($k, $v) = ($1, $2);
811
812 $k = 'file' if $k eq 'volume';
813
814 return undef if defined $res->{$k};
815
816 $res->{$k} = $v;
817 } else {
818 if (!$res->{file} && $p !~ m/=/) {
819 $res->{file} = $p;
820 } else {
821 return undef;
822 }
823 }
824 }
825
826 return undef if !$res->{file};
827
828 return undef if $res->{cache} &&
829 $res->{cache} !~ m/^(off|none|writethrough|writeback|unsafe)$/;
830 return undef if $res->{snapshot} && $res->{snapshot} !~ m/^(on|off)$/;
831 return undef if $res->{cyls} && $res->{cyls} !~ m/^\d+$/;
832 return undef if $res->{heads} && $res->{heads} !~ m/^\d+$/;
833 return undef if $res->{secs} && $res->{secs} !~ m/^\d+$/;
834 return undef if $res->{media} && $res->{media} !~ m/^(disk|cdrom)$/;
835 return undef if $res->{trans} && $res->{trans} !~ m/^(none|lba|auto)$/;
836 return undef if $res->{format} && $res->{format} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
837 return undef if $res->{rerror} && $res->{rerror} !~ m/^(ignore|report|stop)$/;
838 return undef if $res->{werror} && $res->{werror} !~ m/^(enospc|ignore|report|stop)$/;
839 return undef if $res->{backup} && $res->{backup} !~ m/^(yes|no)$/;
840 return undef if $res->{aio} && $res->{aio} !~ m/^(native|threads)$/;
841
842 if ($res->{media} && ($res->{media} eq 'cdrom')) {
843 return undef if $res->{snapshot} || $res->{trans} || $res->{format};
844 return undef if $res->{heads} || $res->{secs} || $res->{cyls};
845 return undef if $res->{interface} eq 'virtio';
846 }
847
848 # rerror does not work with scsi drives
849 if ($res->{rerror}) {
850 return undef if $res->{interface} eq 'scsi';
851 }
852
853 return $res;
854 }
855
856 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio);
857
858 sub print_drive {
859 my ($vmid, $drive) = @_;
860
861 my $opts = '';
862 foreach my $o (@qemu_drive_options, 'backup') {
863 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
864 }
865
866 return "$drive->{file}$opts";
867 }
868
869 sub print_drivedevice_full {
870 my ($storecfg, $vmid, $drive) = @_;
871
872 my $device = '';
873 my $maxdev = 0;
874
875 if ($drive->{interface} eq 'virtio') {
876 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}");
877 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
878 } elsif ($drive->{interface} eq 'scsi') {
879 $maxdev = 7;
880 my $controller = int($drive->{index} / $maxdev);
881 my $unit = $drive->{index} % $maxdev;
882 my $devicetype = 'hd';
883 if ($drive->{media}) {
884 if($drive->{media} eq 'cdrom') {
885 $devicetype = 'cd';
886 } elsif ($drive->{media} eq 'block') {
887 $devicetype = 'block';
888 }
889 }
890
891 $device = "scsi-$devicetype,bus=scsi$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=device-$drive->{interface}$drive->{index}";
892 } elsif ($drive->{interface} eq 'ide'){
893 $maxdev = 2;
894 my $controller = int($drive->{index} / $maxdev);
895 my $unit = $drive->{index} % $maxdev;
896 my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
897
898 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=device-$drive->{interface}$drive->{index}";
899 } elsif ($drive->{interface} eq 'usb') {
900 die "implement me";
901 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
902 } else {
903 die "unsupported interface type";
904 }
905
906 return $device;
907 }
908
909 sub print_drive_full {
910 my ($storecfg, $vmid, $drive) = @_;
911
912 my $opts = '';
913 foreach my $o (@qemu_drive_options) {
914 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
915 }
916
917 # use linux-aio by default (qemu default is threads)
918 $opts .= ",aio=native" if !$drive->{aio};
919
920 my $path;
921 my $volid = $drive->{file};
922 if (drive_is_cdrom($drive)) {
923 $path = get_iso_path($storecfg, $vmid, $volid);
924 } else {
925 if ($volid =~ m|^/|) {
926 $path = $volid;
927 } else {
928 $path = PVE::Storage::path($storecfg, $volid);
929 }
930 }
931
932 my $pathinfo = $path ? "file=$path," : '';
933
934 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
935 }
936
937
938 sub drive_is_cdrom {
939 my ($drive) = @_;
940
941 return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
942
943 }
944
945 sub parse_hostpci {
946 my ($value) = @_;
947
948 return undef if !$value;
949
950 my $res = {};
951
952 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
953 $res->{pciid} = $value;
954 } else {
955 return undef;
956 }
957
958 return $res;
959 }
960
961 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
962 sub parse_net {
963 my ($data) = @_;
964
965 my $res = {};
966
967 foreach my $kvp (split(/,/, $data)) {
968
969 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
970 my $model = lc($1);
971 my $mac = uc($3) || PVE::Tools::random_ether_addr();
972 $res->{model} = $model;
973 $res->{macaddr} = $mac;
974 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
975 $res->{bridge} = $1;
976 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
977 $res->{rate} = $1;
978 } else {
979 return undef;
980 }
981
982 }
983
984 return undef if !$res->{model};
985
986 return $res;
987 }
988
989 sub print_net {
990 my $net = shift;
991
992 my $res = "$net->{model}";
993 $res .= "=$net->{macaddr}" if $net->{macaddr};
994 $res .= ",bridge=$net->{bridge}" if $net->{bridge};
995 $res .= ",rate=$net->{rate}" if $net->{rate};
996
997 return $res;
998 }
999
1000 sub add_random_macs {
1001 my ($settings) = @_;
1002
1003 foreach my $opt (keys %$settings) {
1004 next if $opt !~ m/^net(\d+)$/;
1005 my $net = parse_net($settings->{$opt});
1006 next if !$net;
1007 $settings->{$opt} = print_net($net);
1008 }
1009 }
1010
1011 sub add_unused_volume {
1012 my ($config, $res, $volid) = @_;
1013
1014 my $key;
1015 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1016 my $test = "unused$ind";
1017 if (my $vid = $config->{$test}) {
1018 return if $vid eq $volid; # do not add duplicates
1019 } else {
1020 $key = $test;
1021 }
1022 }
1023
1024 die "To many unused volume - please delete them first.\n" if !$key;
1025
1026 $res->{$key} = $volid;
1027 }
1028
1029 # fixme: remove all thos $noerr parameters?
1030
1031 PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
1032 sub verify_bootdisk {
1033 my ($value, $noerr) = @_;
1034
1035 return $value if valid_drivename($value);
1036
1037 return undef if $noerr;
1038
1039 die "invalid boot disk '$value'\n";
1040 }
1041
1042 PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
1043 sub verify_net {
1044 my ($value, $noerr) = @_;
1045
1046 return $value if parse_net($value);
1047
1048 return undef if $noerr;
1049
1050 die "unable to parse network options\n";
1051 }
1052
1053 PVE::JSONSchema::register_format('pve-qm-drive', \&verify_drive);
1054 sub verify_drive {
1055 my ($value, $noerr) = @_;
1056
1057 return $value if parse_drive(undef, $value);
1058
1059 return undef if $noerr;
1060
1061 die "unable to parse drive options\n";
1062 }
1063
1064 PVE::JSONSchema::register_format('pve-qm-hostpci', \&verify_hostpci);
1065 sub verify_hostpci {
1066 my ($value, $noerr) = @_;
1067
1068 return $value if parse_hostpci($value);
1069
1070 return undef if $noerr;
1071
1072 die "unable to parse pci id\n";
1073 }
1074
1075 PVE::JSONSchema::register_format('pve-qm-watchdog', \&verify_watchdog);
1076 sub verify_watchdog {
1077 my ($value, $noerr) = @_;
1078
1079 return $value if parse_watchdog($value);
1080
1081 return undef if $noerr;
1082
1083 die "unable to parse watchdog options\n";
1084 }
1085
1086 sub parse_watchdog {
1087 my ($value) = @_;
1088
1089 return undef if !$value;
1090
1091 my $res = {};
1092
1093 foreach my $p (split(/,/, $value)) {
1094 next if $p =~ m/^\s*$/;
1095
1096 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1097 $res->{model} = $2;
1098 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1099 $res->{action} = $2;
1100 } else {
1101 return undef;
1102 }
1103 }
1104
1105 return $res;
1106 }
1107
1108 sub parse_usb_device {
1109 my ($value) = @_;
1110
1111 return undef if !$value;
1112
1113 my @dl = split(/,/, $value);
1114 my $found;
1115
1116 my $res = {};
1117 foreach my $v (@dl) {
1118 if ($v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/) {
1119 $found = 1;
1120 $res->{vendorid} = $1;
1121 $res->{productid} = $2;
1122 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1123 $found = 1;
1124 $res->{hostbus} = $1;
1125 $res->{hostport} = $2;
1126 } else {
1127 return undef;
1128 }
1129 }
1130 return undef if !$found;
1131
1132 return $res;
1133 }
1134
1135 PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
1136 sub verify_usb_device {
1137 my ($value, $noerr) = @_;
1138
1139 return $value if parse_usb_device($value);
1140
1141 return undef if $noerr;
1142
1143 die "unable to parse usb device\n";
1144 }
1145
1146 # add JSON properties for create and set function
1147 sub json_config_properties {
1148 my $prop = shift;
1149
1150 foreach my $opt (keys %$confdesc) {
1151 $prop->{$opt} = $confdesc->{$opt};
1152 }
1153
1154 return $prop;
1155 }
1156
1157 sub check_type {
1158 my ($key, $value) = @_;
1159
1160 die "unknown setting '$key'\n" if !$confdesc->{$key};
1161
1162 my $type = $confdesc->{$key}->{type};
1163
1164 if (!defined($value)) {
1165 die "got undefined value\n";
1166 }
1167
1168 if ($value =~ m/[\n\r]/) {
1169 die "property contains a line feed\n";
1170 }
1171
1172 if ($type eq 'boolean') {
1173 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1174 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1175 die "type check ('boolean') failed - got '$value'\n";
1176 } elsif ($type eq 'integer') {
1177 return int($1) if $value =~ m/^(\d+)$/;
1178 die "type check ('integer') failed - got '$value'\n";
1179 } elsif ($type eq 'string') {
1180 if (my $fmt = $confdesc->{$key}->{format}) {
1181 if ($fmt eq 'pve-qm-drive') {
1182 # special case - we need to pass $key to parse_drive()
1183 my $drive = parse_drive($key, $value);
1184 return $value if $drive;
1185 die "unable to parse drive options\n";
1186 }
1187 PVE::JSONSchema::check_format($fmt, $value);
1188 return $value;
1189 }
1190 $value =~ s/^\"(.*)\"$/$1/;
1191 return $value;
1192 } else {
1193 die "internal error"
1194 }
1195 }
1196
1197 sub lock_config {
1198 my ($vmid, $code, @param) = @_;
1199
1200 my $filename = config_file_lock($vmid);
1201
1202 my $res = lock_file($filename, 10, $code, @param);
1203
1204 die $@ if $@;
1205
1206 return $res;
1207 }
1208
1209 sub cfs_config_path {
1210 my ($vmid, $node) = @_;
1211
1212 $node = $nodename if !$node;
1213 return "nodes/$node/qemu-server/$vmid.conf";
1214 }
1215
1216 sub check_iommu_support{
1217 #fixme : need to check IOMMU support
1218 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1219
1220 my $iommu=1;
1221 return $iommu;
1222
1223 }
1224
1225 sub config_file {
1226 my ($vmid, $node) = @_;
1227
1228 my $cfspath = cfs_config_path($vmid, $node);
1229 return "/etc/pve/$cfspath";
1230 }
1231
1232 sub config_file_lock {
1233 my ($vmid) = @_;
1234
1235 return "$lock_dir/lock-$vmid.conf";
1236 }
1237
1238 sub touch_config {
1239 my ($vmid) = @_;
1240
1241 my $conf = config_file($vmid);
1242 utime undef, undef, $conf;
1243 }
1244
1245 sub create_disks {
1246 my ($storecfg, $vmid, $settings, $conf, $default_storage) = @_;
1247
1248 my $vollist = [];
1249
1250 eval {
1251 foreach_drive($settings, sub {
1252 my ($ds, $disk) = @_;
1253
1254 return if drive_is_cdrom($disk);
1255
1256 my $file = $disk->{file};
1257
1258 if ($file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
1259 my $storeid = $2 || $default_storage;
1260 my $size = $3;
1261 my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
1262 my $fmt = $disk->{format} || $defformat;
1263 syslog('info', "VM $vmid creating new disk - size is $size GB");
1264
1265 my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid,
1266 $fmt, undef, $size*1024*1024);
1267
1268 $disk->{file} = $volid;
1269 delete $disk->{format}; # no longer needed
1270 push @$vollist, $volid;
1271 $settings->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
1272 } else {
1273 my $path;
1274 if ($disk->{file} =~ m|^/dev/.+|) {
1275 $path = $disk->{file};
1276 } else {
1277 $path = PVE::Storage::path($storecfg, $disk->{file});
1278 }
1279 if (!(-f $path || -b $path)) {
1280 die "image '$path' does not exists\n";
1281 }
1282 }
1283 PVE::QemuServer::vm_deviceadd($storecfg, $conf, $vmid, $ds, $disk) if defined($conf);
1284 });
1285 };
1286
1287 my $err = $@;
1288
1289 if ($err) {
1290 syslog('err', "VM $vmid creating disks failed");
1291 foreach my $volid (@$vollist) {
1292 eval { PVE::Storage::vdisk_free($storecfg, $volid); };
1293 warn $@ if $@;
1294 }
1295 die $err;
1296 }
1297
1298 return $vollist;
1299 }
1300
1301 sub destroy_vm {
1302 my ($storecfg, $vmid, $keep_empty_config) = @_;
1303
1304 my $conffile = config_file($vmid);
1305
1306 my $conf = load_config($vmid);
1307
1308 check_lock($conf);
1309
1310 # only remove disks owned by this VM
1311 foreach_drive($conf, sub {
1312 my ($ds, $drive) = @_;
1313
1314 return if drive_is_cdrom($drive);
1315
1316 my $volid = $drive->{file};
1317 return if !$volid || $volid =~ m|^/|;
1318
1319 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
1320 return if !$path || !$owner || ($owner != $vmid);
1321
1322 PVE::Storage::vdisk_free($storecfg, $volid);
1323 });
1324
1325 if ($keep_empty_config) {
1326 PVE::Tools::file_set_contents($conffile, "memory: 128\n");
1327 } else {
1328 unlink $conffile;
1329 }
1330
1331 # also remove unused disk
1332 eval {
1333 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1334
1335 eval {
1336 PVE::Storage::foreach_volid($dl, sub {
1337 my ($volid, $sid, $volname, $d) = @_;
1338 PVE::Storage::vdisk_free($storecfg, $volid);
1339 });
1340 };
1341 warn $@ if $@;
1342
1343 };
1344 warn $@ if $@;
1345 }
1346
1347 # fixme: remove?
1348 sub load_diskinfo_old {
1349 my ($storecfg, $vmid, $conf) = @_;
1350
1351 my $info = {};
1352 my $res = {};
1353 my $vollist;
1354
1355 foreach_drive($conf, sub {
1356 my ($ds, $di) = @_;
1357
1358 $res->{$ds} = $di;
1359
1360 return if drive_is_cdrom($di);
1361
1362 if ($di->{file} =~ m|^/dev/.+|) {
1363 $info->{$di->{file}}->{size} = PVE::Storage::file_size_info($di->{file});
1364 } else {
1365 push @$vollist, $di->{file};
1366 }
1367 });
1368
1369 eval {
1370 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid, $vollist);
1371
1372 PVE::Storage::foreach_volid($dl, sub {
1373 my ($volid, $sid, $volname, $d) = @_;
1374 $info->{$volid} = $d;
1375 });
1376 };
1377 warn $@ if $@;
1378
1379 foreach my $ds (keys %$res) {
1380 my $di = $res->{$ds};
1381
1382 $res->{$ds}->{disksize} = $info->{$di->{file}} ?
1383 $info->{$di->{file}}->{size} / (1024*1024) : 0;
1384 }
1385
1386 return $res;
1387 }
1388
1389 sub load_config {
1390 my ($vmid) = @_;
1391
1392 my $cfspath = cfs_config_path($vmid);
1393
1394 my $conf = PVE::Cluster::cfs_read_file($cfspath);
1395
1396 die "no such VM ('$vmid')\n" if !defined($conf);
1397
1398 return $conf;
1399 }
1400
1401 sub parse_vm_config {
1402 my ($filename, $raw) = @_;
1403
1404 return undef if !defined($raw);
1405
1406 my $res = {
1407 digest => Digest::SHA1::sha1_hex($raw),
1408 };
1409
1410 $filename =~ m|/qemu-server/(\d+)\.conf$|
1411 || die "got strange filename '$filename'";
1412
1413 my $vmid = $1;
1414
1415 while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
1416 my $line = $1;
1417
1418 next if $line =~ m/^\#/;
1419
1420 next if $line =~ m/^\s*$/;
1421
1422 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1423 my $key = $1;
1424 my $value = PVE::Tools::decode_text($2);
1425 $res->{$key} = $value;
1426 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1427 my $key = $1;
1428 my $value = $2;
1429 $res->{$key} = $value;
1430 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1431 my $key = $1;
1432 my $value = $2;
1433 eval { $value = check_type($key, $value); };
1434 if ($@) {
1435 warn "vm $vmid - unable to parse value of '$key' - $@";
1436 } else {
1437 my $fmt = $confdesc->{$key}->{format};
1438 if ($fmt && $fmt eq 'pve-qm-drive') {
1439 my $v = parse_drive($key, $value);
1440 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
1441 $v->{file} = $volid;
1442 $value = print_drive($vmid, $v);
1443 } else {
1444 warn "vm $vmid - unable to parse value of '$key'\n";
1445 next;
1446 }
1447 }
1448
1449 if ($key eq 'cdrom') {
1450 $res->{ide2} = $value;
1451 } else {
1452 $res->{$key} = $value;
1453 }
1454 }
1455 }
1456 }
1457
1458 # convert old smp to sockets
1459 if ($res->{smp} && !$res->{sockets}) {
1460 $res->{sockets} = $res->{smp};
1461 }
1462 delete $res->{smp};
1463
1464 return $res;
1465 }
1466
1467 sub change_config {
1468 my ($vmid, $settings, $unset, $skiplock) = @_;
1469
1470 lock_config($vmid, &change_config_nolock, $settings, $unset, $skiplock);
1471 }
1472
1473 sub change_config_nolock {
1474 my ($vmid, $settings, $unset, $skiplock) = @_;
1475
1476 my $res = {};
1477
1478 $unset->{ide2} = $unset->{cdrom} if $unset->{cdrom};
1479
1480 check_lock($settings) if !$skiplock;
1481
1482 # we do not use 'smp' any longer
1483 if ($settings->{sockets}) {
1484 $unset->{smp} = 1;
1485 } elsif ($settings->{smp}) {
1486 $settings->{sockets} = $settings->{smp};
1487 $unset->{smp} = 1;
1488 }
1489
1490 my $new_volids = {};
1491
1492 foreach my $key (keys %$settings) {
1493 next if $key eq 'digest';
1494 my $value = $settings->{$key};
1495 if ($key eq 'description') {
1496 $value = PVE::Tools::encode_text($value);
1497 }
1498 eval { $value = check_type($key, $value); };
1499 die "unable to parse value of '$key' - $@" if $@;
1500 if ($key eq 'cdrom') {
1501 $res->{ide2} = $value;
1502 } else {
1503 $res->{$key} = $value;
1504 }
1505 if (valid_drivename($key)) {
1506 my $drive = PVE::QemuServer::parse_drive($key, $value);
1507 $new_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1508 }
1509 }
1510
1511 my $filename = config_file($vmid);
1512 my $tmpfn = "$filename.$$.tmp";
1513
1514 my $fh = new IO::File($filename, "r") ||
1515 die "unable to read config for VM $vmid\n";
1516
1517 my $werror = "unable to write config for VM $vmid\n";
1518
1519 my $out = new IO::File($tmpfn, "w") || die $werror;
1520
1521 eval {
1522
1523 my $done;
1524
1525 while (my $line = <$fh>) {
1526
1527 if (($line =~ m/^\#/) || ($line =~ m/^\s*$/)) {
1528 die $werror unless print $out $line;
1529 next;
1530 }
1531
1532 if ($line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/) {
1533 my $key = $1;
1534 my $value = $2;
1535
1536 # remove 'unusedX' settings if we re-add a volume
1537 next if $key =~ m/^unused/ && $new_volids->{$value};
1538
1539 # convert 'smp' to 'sockets'
1540 $key = 'sockets' if $key eq 'smp';
1541
1542 next if $done->{$key};
1543 $done->{$key} = 1;
1544
1545 if (defined($res->{$key})) {
1546 $value = $res->{$key};
1547 delete $res->{$key};
1548 }
1549 if (!defined($unset->{$key})) {
1550 die $werror unless print $out "$key: $value\n";
1551 }
1552
1553 next;
1554 }
1555
1556 die "unable to parse config file: $line\n";
1557 }
1558
1559 foreach my $key (keys %$res) {
1560
1561 if (!defined($unset->{$key})) {
1562 die $werror unless print $out "$key: $res->{$key}\n";
1563 }
1564 }
1565 };
1566
1567 my $err = $@;
1568
1569 $fh->close();
1570
1571 if ($err) {
1572 $out->close();
1573 unlink $tmpfn;
1574 die $err;
1575 }
1576
1577 if (!$out->close()) {
1578 $err = "close failed - $!\n";
1579 unlink $tmpfn;
1580 die $err;
1581 }
1582
1583 if (!rename($tmpfn, $filename)) {
1584 $err = "rename failed - $!\n";
1585 unlink $tmpfn;
1586 die $err;
1587 }
1588 }
1589
1590 sub load_defaults {
1591
1592 my $res = {};
1593
1594 # we use static defaults from our JSON schema configuration
1595 foreach my $key (keys %$confdesc) {
1596 if (defined(my $default = $confdesc->{$key}->{default})) {
1597 $res->{$key} = $default;
1598 }
1599 }
1600
1601 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
1602 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
1603
1604 return $res;
1605 }
1606
1607 sub config_list {
1608 my $vmlist = PVE::Cluster::get_vmlist();
1609 my $res = {};
1610 return $res if !$vmlist || !$vmlist->{ids};
1611 my $ids = $vmlist->{ids};
1612
1613 foreach my $vmid (keys %$ids) {
1614 my $d = $ids->{$vmid};
1615 next if !$d->{node} || $d->{node} ne $nodename;
1616 next if !$d->{type} || $d->{type} ne 'qemu';
1617 $res->{$vmid}->{exists} = 1;
1618 }
1619 return $res;
1620 }
1621
1622 # test if VM uses local resources (to prevent migration)
1623 sub check_local_resources {
1624 my ($conf, $noerr) = @_;
1625
1626 my $loc_res = 0;
1627
1628 $loc_res = 1 if $conf->{hostusb}; # old syntax
1629 $loc_res = 1 if $conf->{hostpci}; # old syntax
1630
1631 foreach my $k (keys %$conf) {
1632 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1633 }
1634
1635 die "VM uses local resources\n" if $loc_res && !$noerr;
1636
1637 return $loc_res;
1638 }
1639
1640 sub check_lock {
1641 my ($conf) = @_;
1642
1643 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1644 }
1645
1646 sub check_cmdline {
1647 my ($pidfile, $pid) = @_;
1648
1649 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1650 if (defined($fh)) {
1651 my $line = <$fh>;
1652 $fh->close;
1653 return undef if !$line;
1654 my @param = split(/\0/, $line);
1655
1656 my $cmd = $param[0];
1657 return if !$cmd || ($cmd !~ m|kvm$|);
1658
1659 for (my $i = 0; $i < scalar (@param); $i++) {
1660 my $p = $param[$i];
1661 next if !$p;
1662 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1663 my $p = $param[$i+1];
1664 return 1 if $p && ($p eq $pidfile);
1665 return undef;
1666 }
1667 }
1668 }
1669 return undef;
1670 }
1671
1672 sub check_running {
1673 my ($vmid, $nocheck) = @_;
1674
1675 my $filename = config_file($vmid);
1676
1677 die "unable to find configuration file for VM $vmid - no such machine\n"
1678 if !$nocheck && ! -f $filename;
1679
1680 my $pidfile = pidfile_name($vmid);
1681
1682 if (my $fd = IO::File->new("<$pidfile")) {
1683 my $st = stat($fd);
1684 my $line = <$fd>;
1685 close($fd);
1686
1687 my $mtime = $st->mtime;
1688 if ($mtime > time()) {
1689 warn "file '$filename' modified in future\n";
1690 }
1691
1692 if ($line =~ m/^(\d+)$/) {
1693 my $pid = $1;
1694 if (check_cmdline($pidfile, $pid)) {
1695 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1696 return $pid;
1697 }
1698 }
1699 }
1700 }
1701
1702 return undef;
1703 }
1704
1705 sub vzlist {
1706
1707 my $vzlist = config_list();
1708
1709 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1710
1711 while (defined(my $de = $fd->read)) {
1712 next if $de !~ m/^(\d+)\.pid$/;
1713 my $vmid = $1;
1714 next if !defined($vzlist->{$vmid});
1715 if (my $pid = check_running($vmid)) {
1716 $vzlist->{$vmid}->{pid} = $pid;
1717 }
1718 }
1719
1720 return $vzlist;
1721 }
1722
1723 my $storage_timeout_hash = {};
1724
1725 sub disksize {
1726 my ($storecfg, $conf) = @_;
1727
1728 my $bootdisk = $conf->{bootdisk};
1729 return undef if !$bootdisk;
1730 return undef if !valid_drivename($bootdisk);
1731
1732 return undef if !$conf->{$bootdisk};
1733
1734 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
1735 return undef if !defined($drive);
1736
1737 return undef if drive_is_cdrom($drive);
1738
1739 my $volid = $drive->{file};
1740 return undef if !$volid;
1741
1742 my $path;
1743 my $storeid;
1744 my $timeoutid;
1745
1746 if ($volid =~ m|^/|) {
1747 $path = $timeoutid = $volid;
1748 } else {
1749 $storeid = $timeoutid = PVE::Storage::parse_volume_id($volid);
1750 $path = PVE::Storage::path($storecfg, $volid);
1751 }
1752
1753 my $last_timeout = $storage_timeout_hash->{$timeoutid};
1754 if ($last_timeout) {
1755 if ((time() - $last_timeout) < 30) {
1756 # skip storage with errors
1757 return undef ;
1758 }
1759 delete $storage_timeout_hash->{$timeoutid};
1760 }
1761
1762 my ($size, $format, $used);
1763
1764 ($size, $format, $used) = PVE::Storage::file_size_info($path, 1);
1765
1766 if (!defined($format)) {
1767 # got timeout
1768 $storage_timeout_hash->{$timeoutid} = time();
1769 return undef;
1770 }
1771
1772 return wantarray ? ($size, $used) : $size;
1773 }
1774
1775 my $last_proc_pid_stat;
1776
1777 sub vmstatus {
1778 my ($opt_vmid) = @_;
1779
1780 my $res = {};
1781
1782 my $storecfg = PVE::Storage::config();
1783
1784 my $list = vzlist();
1785 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1786
1787 my $cpucount = $cpuinfo->{cpus} || 1;
1788
1789 foreach my $vmid (keys %$list) {
1790 next if $opt_vmid && ($vmid ne $opt_vmid);
1791
1792 my $cfspath = cfs_config_path($vmid);
1793 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
1794
1795 my $d = {};
1796 $d->{pid} = $list->{$vmid}->{pid};
1797
1798 # fixme: better status?
1799 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
1800
1801 my ($size, $used) = disksize($storecfg, $conf);
1802 if (defined($size) && defined($used)) {
1803 $d->{disk} = $used;
1804 $d->{maxdisk} = $size;
1805 } else {
1806 $d->{disk} = 0;
1807 $d->{maxdisk} = 0;
1808 }
1809
1810 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
1811 $d->{cpus} = $cpucount if $d->{cpus} > $cpucount;
1812
1813 $d->{name} = $conf->{name} || "VM $vmid";
1814 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1815
1816 $d->{uptime} = 0;
1817 $d->{cpu} = 0;
1818 $d->{mem} = 0;
1819
1820 $d->{netout} = 0;
1821 $d->{netin} = 0;
1822
1823 $d->{diskread} = 0;
1824 $d->{diskwrite} = 0;
1825
1826 $res->{$vmid} = $d;
1827 }
1828
1829 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
1830 foreach my $dev (keys %$netdev) {
1831 next if $dev !~ m/^tap([1-9]\d*)i/;
1832 my $vmid = $1;
1833 my $d = $res->{$vmid};
1834 next if !$d;
1835
1836 $d->{netout} += $netdev->{$dev}->{receive};
1837 $d->{netin} += $netdev->{$dev}->{transmit};
1838 }
1839
1840 my $ctime = gettimeofday;
1841
1842 foreach my $vmid (keys %$list) {
1843
1844 my $d = $res->{$vmid};
1845 my $pid = $d->{pid};
1846 next if !$pid;
1847
1848 if (my $fh = IO::File->new("/proc/$pid/io", "r")) {
1849 my $data = {};
1850 while (defined(my $line = <$fh>)) {
1851 if ($line =~ m/^([rw]char):\s+(\d+)$/) {
1852 $data->{$1} = $2;
1853 }
1854 }
1855 close($fh);
1856 $d->{diskread} = $data->{rchar} || 0;
1857 $d->{diskwrite} = $data->{wchar} || 0;
1858 }
1859
1860 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
1861 next if !$pstat; # not running
1862
1863 my $used = $pstat->{utime} + $pstat->{stime};
1864
1865 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1866
1867 if ($pstat->{vsize}) {
1868 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1869 }
1870
1871 my $old = $last_proc_pid_stat->{$pid};
1872 if (!$old) {
1873 $last_proc_pid_stat->{$pid} = {
1874 time => $ctime,
1875 used => $used,
1876 cpu => 0,
1877 };
1878 next;
1879 }
1880
1881 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1882
1883 if ($dtime > 1000) {
1884 my $dutime = $used - $old->{used};
1885
1886 $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
1887 $last_proc_pid_stat->{$pid} = {
1888 time => $ctime,
1889 used => $used,
1890 cpu => $d->{cpu},
1891 };
1892 } else {
1893 $d->{cpu} = $old->{cpu};
1894 }
1895 }
1896
1897 return $res;
1898 }
1899
1900 sub foreach_drive {
1901 my ($conf, $func) = @_;
1902
1903 foreach my $ds (keys %$conf) {
1904 next if !valid_drivename($ds);
1905
1906 my $drive = parse_drive($ds, $conf->{$ds});
1907 next if !$drive;
1908
1909 &$func($ds, $drive);
1910 }
1911 }
1912
1913 sub config_to_command {
1914 my ($storecfg, $vmid, $conf, $defaults, $migrate_uri) = @_;
1915
1916 my $cmd = [];
1917 my $pciaddr = '';
1918 my $kvmver = kvm_user_version();
1919 my $vernum = 0; # unknown
1920 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
1921 $vernum = $1*1000000+$2*1000;
1922 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1923 $vernum = $1*1000000+$2*1000+$3;
1924 }
1925
1926 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
1927
1928 my $have_ovz = -f '/proc/vz/vestat';
1929
1930 push @$cmd, '/usr/bin/kvm';
1931
1932 push @$cmd, '-id', $vmid;
1933
1934 my $use_virtio = 0;
1935
1936 my $socket = monitor_socket($vmid);
1937 push @$cmd, '-chardev', "socket,id=monitor,path=$socket,server,nowait";
1938 push @$cmd, '-mon', "chardev=monitor,mode=readline";
1939
1940 $socket = vnc_socket($vmid);
1941 push @$cmd, '-vnc', "unix:$socket,x509,password";
1942
1943 push @$cmd, '-pidfile' , pidfile_name($vmid);
1944
1945 push @$cmd, '-daemonize';
1946
1947 push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
1948
1949 # include usb device config
1950 push @$cmd, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg';
1951
1952 # enable absolute mouse coordinates (needed by vnc)
1953 my $tablet = defined($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
1954 push @$cmd, '-device', 'usb-tablet,bus=ehci.0,port=6' if $tablet;
1955
1956 # host pci devices
1957 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1958 my $d = parse_hostpci($conf->{"hostpci$i"});
1959 next if !$d;
1960 $pciaddr = print_pci_addr("hostpci$i");
1961 push @$cmd, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
1962 }
1963
1964 # usb devices
1965 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1966 my $d = parse_usb_device($conf->{"usb$i"});
1967 next if !$d;
1968 if ($d->{vendorid} && $d->{productid}) {
1969 push @$cmd, '-device', "usb-host,vendorid=$d->{vendorid},productid=$d->{productid}";
1970 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
1971 push @$cmd, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
1972 }
1973 }
1974
1975 # serial devices
1976 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1977 if (my $path = $conf->{"serial$i"}) {
1978 die "no such serial device\n" if ! -c $path;
1979 push @$cmd, '-chardev', "tty,id=serial$i,path=$path";
1980 push @$cmd, '-device', "isa-serial,chardev=serial$i";
1981 }
1982 }
1983
1984 # parallel devices
1985 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1986 if (my $path = $conf->{"parallel$i"}) {
1987 die "no such parallel device\n" if ! -c $path;
1988 push @$cmd, '-chardev', "parport,id=parallel$i,path=$path";
1989 push @$cmd, '-device', "isa-parallel,chardev=parallel$i";
1990 }
1991 }
1992
1993 my $vmname = $conf->{name} || "vm$vmid";
1994
1995 push @$cmd, '-name', $vmname;
1996
1997 my $sockets = 1;
1998 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
1999 $sockets = $conf->{sockets} if $conf->{sockets};
2000
2001 my $cores = $conf->{cores} || 1;
2002
2003 my $boot_opt;
2004
2005 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2006
2007 push @$cmd, '-cpu', $conf->{cpu} if $conf->{cpu};
2008
2009 push @$cmd, '-nodefaults';
2010
2011 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
2012 push @$cmd, '-boot', "menu=on,order=$bootorder";
2013
2014 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
2015
2016 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
2017
2018 my $vga = $conf->{vga};
2019 if (!$vga) {
2020 if ($conf->{ostype} && ($conf->{ostype} eq 'win7' || $conf->{ostype} eq 'w2k8')) {
2021 $vga = 'std';
2022 } else {
2023 $vga = 'cirrus';
2024 }
2025 }
2026
2027 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2028
2029 # time drift fix
2030 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
2031 push @$cmd, '-tdf' if $tdf;
2032
2033 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
2034
2035 if (my $ost = $conf->{ostype}) {
2036 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2037
2038 if ($ost =~ m/^w/) { # windows
2039 push @$cmd, '-localtime' if !defined($conf->{localtime});
2040
2041 # use rtc-td-hack when acpi is enabled
2042 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
2043 push @$cmd, '-rtc-td-hack';
2044 }
2045 }
2046
2047 # -tdf ?
2048 # -no-acpi
2049 # -no-kvm
2050 # -win2k-hack ?
2051 }
2052
2053 if ($nokvm) {
2054 push @$cmd, '-no-kvm';
2055 } else {
2056 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2057 }
2058
2059 push @$cmd, '-localtime' if $conf->{localtime};
2060
2061 push @$cmd, '-startdate', $conf->{startdate} if $conf->{startdate};
2062
2063 push @$cmd, '-S' if $conf->{freeze};
2064
2065 # set keyboard layout
2066 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2067 push @$cmd, '-k', $kb if $kb;
2068
2069 # enable sound
2070 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2071 #push @$cmd, '-soundhw', 'es1370';
2072 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2073 $pciaddr = print_pci_addr("balloon0");
2074 push @$cmd, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon};
2075
2076 if ($conf->{watchdog}) {
2077 my $wdopts = parse_watchdog($conf->{watchdog});
2078 $pciaddr = print_pci_addr("watchdog");
2079 my $watchdog = $wdopts->{model} || 'i6300esb';
2080 push @$cmd, '-device', "$watchdog$pciaddr";
2081 push @$cmd, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
2082 }
2083
2084 my $vollist = [];
2085 my $scsicontroller = {};
2086
2087 foreach_drive($conf, sub {
2088 my ($ds, $drive) = @_;
2089
2090 if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
2091 push @$vollist, $drive->{file};
2092 }
2093
2094 $use_virtio = 1 if $ds =~ m/^virtio/;
2095 if ($drive->{interface} eq 'scsi') {
2096 my $maxdev = 7;
2097 my $controller = int($drive->{index} / $maxdev);
2098 $pciaddr = print_pci_addr("scsi$controller");
2099 push @$cmd, '-device', "lsi,id=scsi$controller$pciaddr" if !$scsicontroller->{$controller};
2100 $scsicontroller->{$controller}=1;
2101 }
2102 my $tmp = print_drive_full($storecfg, $vmid, $drive);
2103 $tmp .= ",boot=on" if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2104 push @$cmd, '-drive', $tmp;
2105 push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
2106 });
2107
2108 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
2109
2110 my $foundnet = 0;
2111
2112 foreach my $k (sort keys %$conf) {
2113 next if $k !~ m/^net(\d+)$/;
2114 my $i = int($1);
2115
2116 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
2117
2118 if ($conf->{"net$i"} && (my $net = parse_net($conf->{"net$i"}))) {
2119
2120 $foundnet = 1;
2121
2122 my $ifname = "tap${vmid}i$i";
2123
2124 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2125 die "interface name '$ifname' is too long (max 15 character)\n"
2126 if length($ifname) >= 16;
2127
2128 my $device = $net->{model};
2129 my $vhostparam = '';
2130 if ($net->{model} eq 'virtio') {
2131 $use_virtio = 1;
2132 $device = 'virtio-net-pci';
2133 $vhostparam = ',vhost=on' if $kernel_has_vhost_net;
2134 };
2135
2136 if ($net->{bridge}) {
2137 push @$cmd, '-netdev', "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
2138 } else {
2139 push @$cmd, '-netdev', "type=user,id=${k},hostname=$vmname";
2140 }
2141
2142 # qemu > 0.15 always try to boot from network - we disable that by
2143 # not loading the pxe rom file
2144 my $extra = (!$conf->{boot} || ($conf->{boot} !~ m/n/)) ?
2145 "romfile=," : '';
2146 $pciaddr = print_pci_addr("${k}");
2147 push @$cmd, '-device', "$device,${extra}mac=$net->{macaddr},netdev=${k}$pciaddr";
2148 }
2149 }
2150
2151 push @$cmd, '-net', 'none' if !$foundnet;
2152
2153 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2154 # when the VM uses virtio devices.
2155 if (!$use_virtio && $have_ovz) {
2156
2157 my $cpuunits = defined($conf->{cpuunits}) ?
2158 $conf->{cpuunits} : $defaults->{cpuunits};
2159
2160 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2161
2162 # fixme: cpulimit is currently ignored
2163 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2164 }
2165
2166 # add custom args
2167 if ($conf->{args}) {
2168 my $aa = PVE::Tools::split_args($conf->{args});
2169 push @$cmd, @$aa;
2170 }
2171
2172 return wantarray ? ($cmd, $vollist) : $cmd;
2173 }
2174
2175 sub vnc_socket {
2176 my ($vmid) = @_;
2177 return "${var_run_tmpdir}/$vmid.vnc";
2178 }
2179
2180 sub monitor_socket {
2181 my ($vmid) = @_;
2182 return "${var_run_tmpdir}/$vmid.mon";
2183 }
2184
2185 sub pidfile_name {
2186 my ($vmid) = @_;
2187 return "${var_run_tmpdir}/$vmid.pid";
2188 }
2189
2190 sub next_migrate_port {
2191
2192 for (my $p = 60000; $p < 60010; $p++) {
2193
2194 my $sock = IO::Socket::INET->new(Listen => 5,
2195 LocalAddr => 'localhost',
2196 LocalPort => $p,
2197 ReuseAddr => 1,
2198 Proto => 0);
2199
2200 if ($sock) {
2201 close($sock);
2202 return $p;
2203 }
2204 }
2205
2206 die "unable to find free migration port";
2207 }
2208
2209 sub vm_devices_list {
2210 my ($vmid) = @_;
2211
2212 my $res = vm_monitor_command ($vmid, "info pci");
2213
2214 my @lines = split ("\n", $res);
2215 my $devices;
2216 my $bus;
2217 my $addr;
2218 my $id;
2219
2220 foreach my $line (@lines) {
2221 $line =~ s/^\s+//;
2222 if ($line =~ m/^Bus (\d+), device (\d+), function (\d+):$/) {
2223 $bus=$1;
2224 $addr=$2;
2225 }
2226 if ($line =~ m/^id "([a-z][a-z_\-]*\d*)"$/) {
2227 $id=$1;
2228 $devices->{$id}->{bus}=$bus;
2229 $devices->{$id}->{addr}=$addr;
2230 }
2231 }
2232
2233 return $devices;
2234 }
2235
2236 sub vm_deviceadd {
2237 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2238 return if !check_running($vmid) || !$conf->{hotplug} || $conf->{$deviceid};
2239
2240 if($deviceid =~ m/^(virtio)(\d+)$/) {
2241
2242 my $drive = print_drive_full($storecfg, $vmid, $device);
2243 my $ret = vm_monitor_command($vmid, "drive_add auto $drive");
2244 # If the command succeeds qemu prints: "OK"
2245 if ($ret !~ m/OK/s) {
2246 die "adding drive failed: $ret";
2247 }
2248
2249 my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
2250 $ret = vm_monitor_command($vmid, "device_add $devicefull");
2251 $ret =~ s/^\s+//;
2252 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2253 die 'error on hotplug device : $ret' if $ret ne "";
2254 }
2255
2256 for (my $i = 0; $i <= 5; $i++) {
2257 my $devices_list = vm_devices_list($vmid);
2258 return if defined($devices_list->{$deviceid});
2259 sleep 1;
2260 }
2261
2262 die "error on hotplug device $deviceid";
2263 }
2264
2265 sub vm_devicedel {
2266 my ($vmid, $conf, $deviceid) = @_;
2267
2268 return if !check_running ($vmid) || !$conf->{hotplug};
2269
2270 die "can't unplug bootdisk" if $conf->{bootdisk} eq $deviceid;
2271
2272 if($deviceid =~ m/^(virtio)(\d+)$/){
2273
2274 my $ret = vm_monitor_command($vmid, "drive_del drive-$deviceid");
2275 $ret =~ s/^\s+//;
2276 if ($ret =~ m/Device \'.*?\' not found/s) {
2277 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2278 }
2279 elsif ($ret ne "") {
2280 die "deleting drive $deviceid failed : $ret";
2281 }
2282
2283 $ret = vm_monitor_command($vmid, "device_del $deviceid");
2284 $ret =~ s/^\s+//;
2285 die 'detaching device $deviceid failed : $ret' if $ret ne "";
2286
2287 }
2288
2289 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2290 for (my $i = 0; $i <= 5; $i++) {
2291 my $devices_list = vm_devices_list($vmid);
2292 return if !defined($devices_list->{$deviceid});
2293 sleep 1;
2294 }
2295 die "error on hot-plugging device $deviceid";
2296
2297
2298 }
2299
2300 sub vm_start {
2301 my ($storecfg, $vmid, $statefile, $skiplock) = @_;
2302
2303 lock_config($vmid, sub {
2304 my $conf = load_config($vmid);
2305
2306 check_lock($conf) if !$skiplock;
2307
2308 die "VM $vmid already running\n" if check_running($vmid);
2309
2310 my $migrate_uri;
2311 my $migrate_port = 0;
2312
2313 if ($statefile) {
2314 if ($statefile eq 'tcp') {
2315 $migrate_port = next_migrate_port();
2316 $migrate_uri = "tcp:localhost:${migrate_port}";
2317 } else {
2318 if (-f $statefile) {
2319 $migrate_uri = "exec:cat $statefile";
2320 } else {
2321 warn "state file '$statefile' does not exist - doing normal startup\n";
2322 }
2323 }
2324 }
2325
2326 my $defaults = load_defaults();
2327
2328 my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $migrate_uri);
2329 # host pci devices
2330 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2331 my $d = parse_hostpci($conf->{"hostpci$i"});
2332 next if !$d;
2333 my $info = pci_device_info("0000:$d->{pciid}");
2334 die "IOMMU not present\n" if !check_iommu_support();
2335 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2336 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
2337 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
2338 }
2339
2340 PVE::Storage::activate_volumes($storecfg, $vollist);
2341
2342 eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
2343 my $err = $@;
2344 die "start failed: $err" if $err;
2345
2346 if ($statefile) {
2347
2348 if ($statefile eq 'tcp') {
2349 print "migration listens on port $migrate_port\n";
2350 } else {
2351 unlink $statefile;
2352 # fixme: send resume - is that necessary ?
2353 eval { vm_monitor_command($vmid, "cont"); };
2354 }
2355 }
2356
2357 # always set migrate speed (overwrite kvm default of 32m)
2358 # we set a very hight default of 8192m which is basically unlimited
2359 my $migrate_speed = $defaults->{migrate_speed} || 8192;
2360 $migrate_speed = $conf->{migrate_speed} || $migrate_speed;
2361 eval {
2362 my $cmd = "migrate_set_speed ${migrate_speed}m";
2363 vm_monitor_command($vmid, $cmd);
2364 };
2365
2366 if (my $migrate_downtime =
2367 $conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
2368 my $cmd = "migrate_set_downtime ${migrate_downtime}";
2369 eval { vm_monitor_command($vmid, $cmd); };
2370 }
2371
2372 vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
2373 });
2374 }
2375
2376 sub __read_avail {
2377 my ($fh, $timeout) = @_;
2378
2379 my $sel = new IO::Select;
2380 $sel->add($fh);
2381
2382 my $res = '';
2383 my $buf;
2384
2385 my @ready;
2386 while (scalar (@ready = $sel->can_read($timeout))) {
2387 my $count;
2388 if ($count = $fh->sysread($buf, 8192)) {
2389 if ($buf =~ /^(.*)\(qemu\) $/s) {
2390 $res .= $1;
2391 last;
2392 } else {
2393 $res .= $buf;
2394 }
2395 } else {
2396 if (!defined($count)) {
2397 die "$!\n";
2398 }
2399 last;
2400 }
2401 }
2402
2403 die "monitor read timeout\n" if !scalar(@ready);
2404
2405 return $res;
2406 }
2407
2408 sub vm_monitor_command {
2409 my ($vmid, $cmdstr, $nocheck) = @_;
2410
2411 my $res;
2412
2413 eval {
2414 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
2415
2416 my $sname = monitor_socket($vmid);
2417
2418 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
2419 die "unable to connect to VM $vmid socket - $!\n";
2420
2421 my $timeout = 3;
2422
2423 # hack: migrate sometime blocks the monitor (when migrate_downtime
2424 # is set)
2425 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2426 $timeout = 60*60; # 1 hour
2427 }
2428
2429 # read banner;
2430 my $data = __read_avail($sock, $timeout);
2431
2432 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2433 die "got unexpected qemu monitor banner\n";
2434 }
2435
2436 my $sel = new IO::Select;
2437 $sel->add($sock);
2438
2439 if (!scalar(my @ready = $sel->can_write($timeout))) {
2440 die "monitor write error - timeout";
2441 }
2442
2443 my $fullcmd = "$cmdstr\r";
2444
2445 my $b;
2446 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2447 die "monitor write error - $!";
2448 }
2449
2450 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2451
2452 $timeout = 20;
2453
2454 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2455 $timeout = 60*60; # 1 hour
2456 } elsif ($cmdstr =~ m/^(eject|change)/) {
2457 $timeout = 60; # note: cdrom mount command is slow
2458 }
2459 if ($res = __read_avail($sock, $timeout)) {
2460
2461 my @lines = split("\r?\n", $res);
2462
2463 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2464
2465 $res = join("\n", @lines);
2466 $res .= "\n";
2467 }
2468 };
2469
2470 my $err = $@;
2471
2472 if ($err) {
2473 syslog("err", "VM $vmid monitor command failed - $err");
2474 die $err;
2475 }
2476
2477 return $res;
2478 }
2479
2480 sub vm_commandline {
2481 my ($storecfg, $vmid) = @_;
2482
2483 my $conf = load_config($vmid);
2484
2485 my $defaults = load_defaults();
2486
2487 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
2488
2489 return join(' ', @$cmd);
2490 }
2491
2492 sub vm_reset {
2493 my ($vmid, $skiplock) = @_;
2494
2495 lock_config($vmid, sub {
2496
2497 my $conf = load_config($vmid);
2498
2499 check_lock($conf) if !$skiplock;
2500
2501 vm_monitor_command($vmid, "system_reset");
2502 });
2503 }
2504
2505 sub get_vm_volumes {
2506 my ($conf) = @_;
2507
2508 my $vollist = [];
2509 foreach_drive($conf, sub {
2510 my ($ds, $drive) = @_;
2511
2512 my ($sid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
2513 return if !$sid;
2514
2515 my $volid = $drive->{file};
2516 return if !$volid || $volid =~ m|^/|;
2517
2518 push @$vollist, $volid;
2519 });
2520
2521 return $vollist;
2522 }
2523
2524 sub vm_stop_cleanup {
2525 my ($storecfg, $vmid, $conf) = @_;
2526
2527 fairsched_rmnod($vmid); # try to destroy group
2528
2529 my $vollist = get_vm_volumes($conf);
2530 PVE::Storage::deactivate_volumes($storecfg, $vollist);
2531 }
2532
2533 sub vm_shutdown {
2534 my ($storecfg, $vmid, $skiplock, $timeout) = @_;
2535
2536 $timeout = 60 if !$timeout;
2537
2538 lock_config($vmid, sub {
2539
2540 my $conf = load_config($vmid);
2541
2542 check_lock($conf) if !$skiplock;
2543
2544 vm_monitor_command($vmid, "system_powerdown");
2545
2546 my $pid = check_running($vmid);
2547
2548 if ($pid && $timeout) {
2549 print "waiting until VM $vmid stopps (PID $pid)\n";
2550
2551 my $count = 0;
2552 while (($count < $timeout) && check_running($vmid)) {
2553 $count++;
2554 sleep 1;
2555 }
2556
2557 die "shutdown failed - got timeout\n" if check_running($vmid);
2558 }
2559
2560 vm_stop_cleanup($storecfg, $vmid, $conf);
2561 });
2562 }
2563
2564 # Note: use $nockeck to skip tests if VM configuration file exists.
2565 # We need that when migration VMs to other nodes (files already moved)
2566 sub vm_stop {
2567 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout) = @_;
2568
2569 $timeout = 60 if !$timeout;
2570
2571 lock_config($vmid, sub {
2572
2573 my $pid = check_running($vmid, $nocheck);
2574 return if !$pid;
2575
2576 my $conf;
2577 if (!$nocheck) {
2578 $conf = load_config($vmid);
2579 check_lock($conf) if !$skiplock;
2580 }
2581
2582 eval { vm_monitor_command($vmid, "quit", $nocheck); };
2583 my $err = $@;
2584
2585 if (!$err) {
2586 my $count = 0;
2587 while (($count < $timeout) && check_running($vmid, $nocheck)) {
2588 $count++;
2589 sleep 1;
2590 }
2591
2592 if ($count >= $timeout) {
2593 warn "VM still running - terminating now with SIGTERM\n";
2594 kill 15, $pid;
2595 }
2596 } else {
2597 warn "VM quit failed - terminating now with SIGTERM\n";
2598 kill 15, $pid;
2599 }
2600
2601 # wait again
2602 $timeout = 10;
2603
2604 my $count = 0;
2605 while (($count < $timeout) && check_running($vmid, $nocheck)) {
2606 $count++;
2607 sleep 1;
2608 }
2609
2610 if ($count >= $timeout) {
2611 warn "VM still running - terminating now with SIGKILL\n";
2612 kill 9, $pid;
2613 sleep 1;
2614 }
2615
2616 vm_stop_cleanup($storecfg, $vmid, $conf) if $conf;
2617 });
2618 }
2619
2620 sub vm_suspend {
2621 my ($vmid, $skiplock) = @_;
2622
2623 lock_config($vmid, sub {
2624
2625 my $conf = load_config($vmid);
2626
2627 check_lock($conf) if !$skiplock;
2628
2629 vm_monitor_command($vmid, "stop");
2630 });
2631 }
2632
2633 sub vm_resume {
2634 my ($vmid, $skiplock) = @_;
2635
2636 lock_config($vmid, sub {
2637
2638 my $conf = load_config($vmid);
2639
2640 check_lock($conf) if !$skiplock;
2641
2642 vm_monitor_command($vmid, "cont");
2643 });
2644 }
2645
2646 sub vm_sendkey {
2647 my ($vmid, $skiplock, $key) = @_;
2648
2649 lock_config($vmid, sub {
2650
2651 my $conf = load_config($vmid);
2652
2653 vm_monitor_command($vmid, "sendkey $key");
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 if (!check_running($vmid)) {
2667 fairsched_rmnod($vmid); # try to destroy group
2668 destroy_vm($storecfg, $vmid);
2669 } else {
2670 die "VM $vmid is running - destroy failed\n";
2671 }
2672 });
2673 }
2674
2675 sub vm_stopall {
2676 my ($storecfg, $timeout) = @_;
2677
2678 $timeout = 3*60 if !$timeout;
2679
2680 my $cleanuphash = {};
2681
2682 my $vzlist = vzlist();
2683 my $count = 0;
2684 foreach my $vmid (keys %$vzlist) {
2685 next if !$vzlist->{$vmid}->{pid};
2686 $count++;
2687 $cleanuphash->{$vmid} = 1;
2688 }
2689
2690 return if !$count;
2691
2692 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs\n";
2693 syslog('info', $msg);
2694 warn $msg;
2695
2696 foreach my $vmid (keys %$vzlist) {
2697 next if !$vzlist->{$vmid}->{pid};
2698 eval { vm_monitor_command($vmid, "system_powerdown"); };
2699 warn $@ if $@;
2700 }
2701
2702 my $wt = 5;
2703 my $maxtries = int(($timeout + $wt -1)/$wt);
2704 my $try = 0;
2705 while (($try < $maxtries) && $count) {
2706 $try++;
2707 sleep $wt;
2708
2709 $vzlist = vzlist();
2710 $count = 0;
2711 foreach my $vmid (keys %$vzlist) {
2712 next if !$vzlist->{$vmid}->{pid};
2713 $count++;
2714 }
2715 last if !$count;
2716 }
2717
2718 if ($count) {
2719
2720 foreach my $vmid (keys %$vzlist) {
2721 next if !$vzlist->{$vmid}->{pid};
2722
2723 warn "VM $vmid still running - sending stop now\n";
2724 eval { vm_monitor_command($vmid, "quit"); };
2725 warn $@ if $@;
2726 }
2727
2728 $timeout = 30;
2729 $maxtries = int(($timeout + $wt -1)/$wt);
2730 $try = 0;
2731 while (($try < $maxtries) && $count) {
2732 $try++;
2733 sleep $wt;
2734
2735 $vzlist = vzlist();
2736 $count = 0;
2737 foreach my $vmid (keys %$vzlist) {
2738 next if !$vzlist->{$vmid}->{pid};
2739 $count++;
2740 }
2741 last if !$count;
2742 }
2743
2744 if ($count) {
2745
2746 foreach my $vmid (keys %$vzlist) {
2747 next if !$vzlist->{$vmid}->{pid};
2748
2749 warn "VM $vmid still running - terminating now with SIGTERM\n";
2750 kill 15, $vzlist->{$vmid}->{pid};
2751 }
2752 sleep 1;
2753 }
2754
2755 # this is called by system shotdown scripts, so remaining
2756 # processes gets killed anyways (no need to send kill -9 here)
2757 }
2758
2759 $vzlist = vzlist();
2760 foreach my $vmid (keys %$cleanuphash) {
2761 next if $vzlist->{$vmid}->{pid};
2762 eval {
2763 my $conf = load_config($vmid);
2764 vm_stop_cleanup($storecfg, $vmid, $conf);
2765 };
2766 warn $@ if $@;
2767 }
2768
2769 $msg = "Qemu Server stopped\n";
2770 syslog('info', $msg);
2771 print $msg;
2772 }
2773
2774 # pci helpers
2775
2776 sub file_write {
2777 my ($filename, $buf) = @_;
2778
2779 my $fh = IO::File->new($filename, "w");
2780 return undef if !$fh;
2781
2782 my $res = print $fh $buf;
2783
2784 $fh->close();
2785
2786 return $res;
2787 }
2788
2789 sub pci_device_info {
2790 my ($name) = @_;
2791
2792 my $res;
2793
2794 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
2795 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
2796
2797 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
2798 return undef if !defined($irq) || $irq !~ m/^\d+$/;
2799
2800 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
2801 return undef if !defined($vendor) || $vendor !~ s/^0x//;
2802
2803 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
2804 return undef if !defined($product) || $product !~ s/^0x//;
2805
2806 $res = {
2807 name => $name,
2808 vendor => $vendor,
2809 product => $product,
2810 domain => $domain,
2811 bus => $bus,
2812 slot => $slot,
2813 func => $func,
2814 irq => $irq,
2815 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
2816 };
2817
2818 return $res;
2819 }
2820
2821 sub pci_dev_reset {
2822 my ($dev) = @_;
2823
2824 my $name = $dev->{name};
2825
2826 my $fn = "$pcisysfs/devices/$name/reset";
2827
2828 return file_write($fn, "1");
2829 }
2830
2831 sub pci_dev_bind_to_stub {
2832 my ($dev) = @_;
2833
2834 my $name = $dev->{name};
2835
2836 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
2837 return 1 if -d $testdir;
2838
2839 my $data = "$dev->{vendor} $dev->{product}";
2840 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
2841
2842 my $fn = "$pcisysfs/devices/$name/driver/unbind";
2843 if (!file_write($fn, $name)) {
2844 return undef if -f $fn;
2845 }
2846
2847 $fn = "$pcisysfs/drivers/pci-stub/bind";
2848 if (! -d $testdir) {
2849 return undef if !file_write($fn, $name);
2850 }
2851
2852 return -d $testdir;
2853 }
2854
2855 sub print_pci_addr {
2856 my ($id) = @_;
2857
2858 my $res = '';
2859 my $devices = {
2860 #addr1 : ide,parallel,serial (motherboard)
2861 #addr2 : first videocard
2862 balloon0 => { bus => 0, addr => 3 },
2863 watchdog => { bus => 0, addr => 4 },
2864 scsi0 => { bus => 0, addr => 5 },
2865 scsi1 => { bus => 0, addr => 6 },
2866 virtio0 => { bus => 0, addr => 10 },
2867 virtio1 => { bus => 0, addr => 11 },
2868 virtio2 => { bus => 0, addr => 12 },
2869 virtio3 => { bus => 0, addr => 13 },
2870 virtio4 => { bus => 0, addr => 14 },
2871 virtio5 => { bus => 0, addr => 15 },
2872 hostpci0 => { bus => 0, addr => 16 },
2873 hostpci1 => { bus => 0, addr => 17 },
2874 net0 => { bus => 0, addr => 18 },
2875 net1 => { bus => 0, addr => 19 },
2876 net2 => { bus => 0, addr => 20 },
2877 net3 => { bus => 0, addr => 21 },
2878 net4 => { bus => 0, addr => 22 },
2879 net5 => { bus => 0, addr => 23 },
2880 #addr29 : usb-host (pve-usb.cfg)
2881 };
2882
2883 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
2884 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
2885 $res = ",bus=pci.$devices->{$id}->{bus},addr=$addr";
2886 }
2887 return $res;
2888
2889 }
2890
2891 sub vm_balloonset {
2892 my ($vmid, $value) = @_;
2893
2894 vm_monitor_command($vmid, "balloon $value");
2895 }
2896
2897 # vzdump restore implementaion
2898
2899 sub archive_read_firstfile {
2900 my $archive = shift;
2901
2902 die "ERROR: file '$archive' does not exist\n" if ! -f $archive;
2903
2904 # try to detect archive type first
2905 my $pid = open (TMP, "tar tf '$archive'|") ||
2906 die "unable to open file '$archive'\n";
2907 my $firstfile = <TMP>;
2908 kill 15, $pid;
2909 close TMP;
2910
2911 die "ERROR: archive contaions no data\n" if !$firstfile;
2912 chomp $firstfile;
2913
2914 return $firstfile;
2915 }
2916
2917 sub restore_cleanup {
2918 my $statfile = shift;
2919
2920 print STDERR "starting cleanup\n";
2921
2922 if (my $fd = IO::File->new($statfile, "r")) {
2923 while (defined(my $line = <$fd>)) {
2924 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
2925 my $volid = $2;
2926 eval {
2927 if ($volid =~ m|^/|) {
2928 unlink $volid || die 'unlink failed\n';
2929 } else {
2930 my $cfg = cfs_read_file('storage.cfg');
2931 PVE::Storage::vdisk_free($cfg, $volid);
2932 }
2933 print STDERR "temporary volume '$volid' sucessfuly removed\n";
2934 };
2935 print STDERR "unable to cleanup '$volid' - $@" if $@;
2936 } else {
2937 print STDERR "unable to parse line in statfile - $line";
2938 }
2939 }
2940 $fd->close();
2941 }
2942 }
2943
2944 sub restore_archive {
2945 my ($archive, $vmid, $opts) = @_;
2946
2947 if ($archive ne '-') {
2948 my $firstfile = archive_read_firstfile($archive);
2949 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
2950 if $firstfile ne 'qemu-server.conf';
2951 }
2952
2953 my $tocmd = "/usr/lib/qemu-server/qmextract";
2954
2955 $tocmd .= " --storage " . PVE::Tools::shellquote($opts->{storage}) if $opts->{storage};
2956 $tocmd .= ' --prealloc' if $opts->{prealloc};
2957 $tocmd .= ' --info' if $opts->{info};
2958
2959 # tar option "xf" does not autodetect compression when read fron STDIN,
2960 # so we pipe to zcat
2961 my $cmd = "zcat -f|tar xf " . PVE::Tools::shellquote($archive) . " " .
2962 PVE::Tools::shellquote("--to-command=$tocmd");
2963
2964 my $tmpdir = "/var/tmp/vzdumptmp$$";
2965 mkpath $tmpdir;
2966
2967 local $ENV{VZDUMP_TMPDIR} = $tmpdir;
2968 local $ENV{VZDUMP_VMID} = $vmid;
2969
2970 my $conffile = PVE::QemuServer::config_file($vmid);
2971 my $tmpfn = "$conffile.$$.tmp";
2972
2973 # disable interrupts (always do cleanups)
2974 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
2975 print STDERR "got interrupt - ignored\n";
2976 };
2977
2978 eval {
2979 # enable interrupts
2980 local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
2981 die "interrupted by signal\n";
2982 };
2983
2984 if ($archive eq '-') {
2985 print "extracting archive from STDIN\n";
2986 run_command($cmd, input => "<&STDIN");
2987 } else {
2988 print "extracting archive '$archive'\n";
2989 run_command($cmd);
2990 }
2991
2992 return if $opts->{info};
2993
2994 # read new mapping
2995 my $map = {};
2996 my $statfile = "$tmpdir/qmrestore.stat";
2997 if (my $fd = IO::File->new($statfile, "r")) {
2998 while (defined (my $line = <$fd>)) {
2999 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3000 $map->{$1} = $2 if $1;
3001 } else {
3002 print STDERR "unable to parse line in statfile - $line\n";
3003 }
3004 }
3005 $fd->close();
3006 }
3007
3008 my $confsrc = "$tmpdir/qemu-server.conf";
3009
3010 my $srcfd = new IO::File($confsrc, "r") ||
3011 die "unable to open file '$confsrc'\n";
3012
3013 my $outfd = new IO::File ($tmpfn, "w") ||
3014 die "unable to write config for VM $vmid\n";
3015
3016 my $netcount = 0;
3017
3018 while (defined (my $line = <$srcfd>)) {
3019 next if $line =~ m/^\#vzdump\#/;
3020 next if $line =~ m/^lock:/;
3021 next if $line =~ m/^unused\d+:/;
3022
3023 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3024 # try to convert old 1.X settings
3025 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3026 foreach my $devconfig (PVE::Tools::split_list($ethcfg)) {
3027 my ($model, $macaddr) = split(/\=/, $devconfig);
3028 $macaddr = PVE::Tools::random_ether_addr() if !$macaddr || $opts->{unique};
3029 my $net = {
3030 model => $model,
3031 bridge => "vmbr$ind",
3032 macaddr => $macaddr,
3033 };
3034 my $netstr = print_net($net);
3035 print $outfd "net${netcount}: $netstr\n";
3036 $netcount++;
3037 }
3038 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && ($opts->{unique})) {
3039 my ($id, $netstr) = ($1, $2);
3040 my $net = parse_net($netstr);
3041 $net->{macaddr} = PVE::Tools::random_ether_addr() if $net->{macaddr};
3042 $netstr = print_net($net);
3043 print $outfd "$id: $netstr\n";
3044 } elsif ($line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/) {
3045 my $virtdev = $1;
3046 my $value = $2;
3047 if ($line =~ m/backup=no/) {
3048 print $outfd "#$line";
3049 } elsif ($virtdev && $map->{$virtdev}) {
3050 my $di = PVE::QemuServer::parse_drive($virtdev, $value);
3051 $di->{file} = $map->{$virtdev};
3052 $value = PVE::QemuServer::print_drive($vmid, $di);
3053 print $outfd "$virtdev: $value\n";
3054 } else {
3055 print $outfd $line;
3056 }
3057 } else {
3058 print $outfd $line;
3059 }
3060 }
3061
3062 $srcfd->close();
3063 $outfd->close();
3064 };
3065 my $err = $@;
3066
3067 if ($err) {
3068
3069 unlink $tmpfn;
3070
3071 restore_cleanup("$tmpdir/qmrestore.stat") if !$opts->{info};
3072
3073 die $err;
3074 }
3075
3076 rmtree $tmpdir;
3077
3078 rename $tmpfn, $conffile ||
3079 die "unable to commit configuration file '$conffile'\n";
3080 };
3081
3082 1;