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