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