]> git.proxmox.com Git - qemu-server.git/blame - PVE/QemuServer.pm
Add hotplug option
[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,
158 type => 'integer',
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
DM
902 my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}");
903 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=device-$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 {
1268 my ($storecfg, $vmid, $settings) = @_;
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+)?)$/) {
1281 my $storeid = $2 || 'local';
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 }
1305 });
1306 };
1307
1308 my $err = $@;
1309
1310 if ($err) {
6b64503e 1311 syslog('err', "VM $vmid creating disks failed");
1e3baf05 1312 foreach my $volid (@$vollist) {
6b64503e 1313 eval { PVE::Storage::vdisk_free($storecfg, $volid); };
1e3baf05
DM
1314 warn $@ if $@;
1315 }
1316 die $err;
1317 }
1318
1319 return $vollist;
1320}
1321
1322sub unlink_image {
1323 my ($storecfg, $vmid, $volid) = @_;
1324
1325 die "reject to unlink absolute path '$volid'"
1326 if $volid =~ m|^/|;
19672434 1327
6b64503e 1328 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
1e3baf05
DM
1329
1330 die "reject to unlink '$volid' - not owned by this VM"
1331 if !$owner || ($owner != $vmid);
1332
6b64503e 1333 syslog('info', "VM $vmid deleting volume '$volid'");
1e3baf05 1334
6b64503e 1335 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 1336
6b64503e 1337 touch_config($vmid);
1e3baf05
DM
1338}
1339
1340sub destroy_vm {
1341 my ($storecfg, $vmid) = @_;
1342
6b64503e 1343 my $conffile = config_file($vmid);
1e3baf05 1344
6b64503e 1345 my $conf = load_config($vmid);
1e3baf05 1346
6b64503e 1347 check_lock($conf);
1e3baf05 1348
19672434 1349 # only remove disks owned by this VM
1e3baf05
DM
1350 foreach_drive($conf, sub {
1351 my ($ds, $drive) = @_;
1352
6b64503e 1353 return if drive_is_cdrom($drive);
1e3baf05
DM
1354
1355 my $volid = $drive->{file};
1356 next if !$volid || $volid =~ m|^/|;
1357
6b64503e 1358 my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
1e3baf05
DM
1359 next if !$path || !$owner || ($owner != $vmid);
1360
6b64503e 1361 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05 1362 });
19672434 1363
1e3baf05
DM
1364 unlink $conffile;
1365
1366 # also remove unused disk
1367 eval {
6b64503e 1368 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid);
1e3baf05
DM
1369
1370 eval {
6b64503e 1371 PVE::Storage::foreach_volid($dl, sub {
1e3baf05 1372 my ($volid, $sid, $volname, $d) = @_;
6b64503e 1373 PVE::Storage::vdisk_free($storecfg, $volid);
1e3baf05
DM
1374 });
1375 };
1376 warn $@ if $@;
1377
1378 };
1379 warn $@ if $@;
1380}
1381
1382# fixme: remove?
1383sub load_diskinfo_old {
1384 my ($storecfg, $vmid, $conf) = @_;
1385
1386 my $info = {};
1387 my $res = {};
1388 my $vollist;
1389
1390 foreach_drive($conf, sub {
1391 my ($ds, $di) = @_;
1392
1393 $res->{$ds} = $di;
1394
6b64503e 1395 return if drive_is_cdrom($di);
1e3baf05
DM
1396
1397 if ($di->{file} =~ m|^/dev/.+|) {
6b64503e 1398 $info->{$di->{file}}->{size} = PVE::Storage::file_size_info($di->{file});
1e3baf05
DM
1399 } else {
1400 push @$vollist, $di->{file};
1401 }
1402 });
1403
1404 eval {
6b64503e 1405 my $dl = PVE::Storage::vdisk_list($storecfg, undef, $vmid, $vollist);
1e3baf05 1406
6b64503e 1407 PVE::Storage::foreach_volid($dl, sub {
1e3baf05
DM
1408 my ($volid, $sid, $volname, $d) = @_;
1409 $info->{$volid} = $d;
1410 });
1411 };
1412 warn $@ if $@;
1413
1414 foreach my $ds (keys %$res) {
1415 my $di = $res->{$ds};
1416
19672434 1417 $res->{$ds}->{disksize} = $info->{$di->{file}} ?
1e3baf05
DM
1418 $info->{$di->{file}}->{size} / (1024*1024) : 0;
1419 }
1420
1421 return $res;
1422}
1423
1424sub load_config {
1425 my ($vmid) = @_;
1426
1427 my $cfspath = cfs_config_path($vmid);
1428
1429 my $conf = PVE::Cluster::cfs_read_file($cfspath);
1430
1431 die "no such VM ('$vmid')\n" if !defined($conf);
1432
1433 return $conf;
19672434 1434}
1e3baf05
DM
1435
1436sub parse_vm_config {
1437 my ($filename, $raw) = @_;
1438
1439 return undef if !defined($raw);
1440
554ac7e7
DM
1441 my $res = {
1442 digest => Digest::SHA1::sha1_hex($raw),
1443 };
1e3baf05 1444
19672434 1445 $filename =~ m|/qemu-server/(\d+)\.conf$|
1e3baf05
DM
1446 || die "got strange filename '$filename'";
1447
1448 my $vmid = $1;
1449
1450 while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
1451 my $line = $1;
19672434 1452
1e3baf05
DM
1453 next if $line =~ m/^\#/;
1454
1455 next if $line =~ m/^\s*$/;
1456
1457 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1458 my $key = $1;
1459 my $value = PVE::Tools::decode_text($2);
1460 $res->{$key} = $value;
1461 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1462 my $key = $1;
1463 my $value = $2;
1464 $res->{$key} = $value;
1465 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1466 my $key = $1;
1467 my $value = $2;
1468 eval { $value = check_type($key, $value); };
1469 if ($@) {
1470 warn "vm $vmid - unable to parse value of '$key' - $@";
1471 } else {
1472 my $fmt = $confdesc->{$key}->{format};
1473 if ($fmt && $fmt eq 'pve-qm-drive') {
1474 my $v = parse_drive($key, $value);
1475 if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
1476 $v->{file} = $volid;
6b64503e 1477 $value = print_drive($vmid, $v);
1e3baf05
DM
1478 } else {
1479 warn "vm $vmid - unable to parse value of '$key'\n";
1480 next;
1481 }
1482 }
1483
1484 if ($key eq 'cdrom') {
1485 $res->{ide2} = $value;
1486 } else {
1487 $res->{$key} = $value;
1488 }
1489 }
1490 }
1491 }
1492
1493 # convert old smp to sockets
1494 if ($res->{smp} && !$res->{sockets}) {
1495 $res->{sockets} = $res->{smp};
19672434 1496 }
1e3baf05
DM
1497 delete $res->{smp};
1498
1499 return $res;
1500}
1501
1502sub change_config {
1503 my ($vmid, $settings, $unset, $skiplock) = @_;
1504
6b64503e 1505 lock_config($vmid, &change_config_nolock, $settings, $unset, $skiplock);
1e3baf05
DM
1506}
1507
1508sub change_config_nolock {
1509 my ($vmid, $settings, $unset, $skiplock) = @_;
1510
1511 my $res = {};
1512
1513 $unset->{ide2} = $unset->{cdrom} if $unset->{cdrom};
1514
1515 check_lock($settings) if !$skiplock;
1516
1517 # we do not use 'smp' any longer
1518 if ($settings->{sockets}) {
19672434 1519 $unset->{smp} = 1;
1e3baf05
DM
1520 } elsif ($settings->{smp}) {
1521 $settings->{sockets} = $settings->{smp};
1522 $unset->{smp} = 1;
1523 }
1524
1525 my $new_volids = {};
1526
1527 foreach my $key (keys %$settings) {
554ac7e7 1528 next if $key eq 'digest';
1e3baf05
DM
1529 my $value = $settings->{$key};
1530 if ($key eq 'description') {
1531 $value = PVE::Tools::encode_text($value);
1532 }
1533 eval { $value = check_type($key, $value); };
1534 die "unable to parse value of '$key' - $@" if $@;
1535 if ($key eq 'cdrom') {
1536 $res->{ide2} = $value;
1537 } else {
1538 $res->{$key} = $value;
1539 }
1540 if (valid_drivename($key)) {
1541 my $drive = PVE::QemuServer::parse_drive($key, $value);
1542 $new_volids->{$drive->{file}} = 1 if $drive && $drive->{file};
1543 }
1544 }
1545
1546 my $filename = config_file($vmid);
1547 my $tmpfn = "$filename.$$.tmp";
1548
6b64503e 1549 my $fh = new IO::File($filename, "r") ||
1e3baf05
DM
1550 die "unable to read config for VM $vmid\n";
1551
1552 my $werror = "unable to write config for VM $vmid\n";
1553
6b64503e 1554 my $out = new IO::File($tmpfn, "w") || die $werror;
1e3baf05
DM
1555
1556 eval {
1557
1558 my $done;
1559
1560 while (my $line = <$fh>) {
19672434 1561
1e3baf05
DM
1562 if (($line =~ m/^\#/) || ($line =~ m/^\s*$/)) {
1563 die $werror unless print $out $line;
1564 next;
1565 }
1566
1567 if ($line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/) {
1568 my $key = $1;
1569 my $value = $2;
1570
1571 # remove 'unusedX' settings if we re-add a volume
1572 next if $key =~ m/^unused/ && $new_volids->{$value};
1573
1574 # convert 'smp' to 'sockets'
1575 $key = 'sockets' if $key eq 'smp';
1576
1577 next if $done->{$key};
1578 $done->{$key} = 1;
1579
6b64503e 1580 if (defined($res->{$key})) {
1e3baf05
DM
1581 $value = $res->{$key};
1582 delete $res->{$key};
1583 }
6b64503e 1584 if (!defined($unset->{$key})) {
1e3baf05 1585 die $werror unless print $out "$key: $value\n";
19672434 1586 }
1e3baf05
DM
1587
1588 next;
1589 }
1590
1591 die "unable to parse config file: $line\n";
1592 }
1593
1594 foreach my $key (keys %$res) {
1595
6b64503e 1596 if (!defined($unset->{$key})) {
1e3baf05
DM
1597 die $werror unless print $out "$key: $res->{$key}\n";
1598 }
1599 }
1600 };
1601
1602 my $err = $@;
1603
1604 $fh->close();
1605
1606 if ($err) {
1607 $out->close();
1608 unlink $tmpfn;
1609 die $err;
1610 }
1611
1612 if (!$out->close()) {
1613 $err = "close failed - $!\n";
1614 unlink $tmpfn;
19672434 1615 die $err;
1e3baf05
DM
1616 }
1617
1618 if (!rename($tmpfn, $filename)) {
1619 $err = "rename failed - $!\n";
1620 unlink $tmpfn;
1621 die $err;
1622 }
1623}
1624
19672434 1625sub load_defaults {
1e3baf05
DM
1626
1627 my $res = {};
1628
1629 # we use static defaults from our JSON schema configuration
1630 foreach my $key (keys %$confdesc) {
1631 if (defined(my $default = $confdesc->{$key}->{default})) {
1632 $res->{$key} = $default;
1633 }
1634 }
19672434 1635
1e3baf05
DM
1636 my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
1637 $res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
1638
1639 return $res;
1640}
1641
1642sub config_list {
1643 my $vmlist = PVE::Cluster::get_vmlist();
1644 my $res = {};
1645 return $res if !$vmlist || !$vmlist->{ids};
1646 my $ids = $vmlist->{ids};
1647
1e3baf05
DM
1648 foreach my $vmid (keys %$ids) {
1649 my $d = $ids->{$vmid};
1650 next if !$d->{node} || $d->{node} ne $nodename;
5ee957cc 1651 next if !$d->{type} || $d->{type} ne 'qemu';
1e3baf05
DM
1652 $res->{$vmid}->{exists} = 1;
1653 }
1654 return $res;
1655}
1656
64e13401
DM
1657# test if VM uses local resources (to prevent migration)
1658sub check_local_resources {
1659 my ($conf, $noerr) = @_;
1660
1661 my $loc_res = 0;
19672434 1662
e0ab7331
DM
1663 $loc_res = 1 if $conf->{hostusb}; # old syntax
1664 $loc_res = 1 if $conf->{hostpci}; # old syntax
64e13401 1665
0d29ab3b 1666 foreach my $k (keys %$conf) {
2fe1a152 1667 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
64e13401
DM
1668 }
1669
1670 die "VM uses local resources\n" if $loc_res && !$noerr;
1671
1672 return $loc_res;
1673}
1674
1e3baf05
DM
1675sub check_lock {
1676 my ($conf) = @_;
1677
1678 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1679}
1680
1681sub check_cmdline {
1682 my ($pidfile, $pid) = @_;
1683
6b64503e
DM
1684 my $fh = IO::File->new("/proc/$pid/cmdline", "r");
1685 if (defined($fh)) {
1e3baf05
DM
1686 my $line = <$fh>;
1687 $fh->close;
1688 return undef if !$line;
6b64503e 1689 my @param = split(/\0/, $line);
1e3baf05
DM
1690
1691 my $cmd = $param[0];
1692 return if !$cmd || ($cmd !~ m|kvm$|);
1693
1694 for (my $i = 0; $i < scalar (@param); $i++) {
1695 my $p = $param[$i];
1696 next if !$p;
1697 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1698 my $p = $param[$i+1];
1699 return 1 if $p && ($p eq $pidfile);
1700 return undef;
1701 }
1702 }
1703 }
1704 return undef;
1705}
1706
1707sub check_running {
e6c3b671 1708 my ($vmid, $nocheck) = @_;
1e3baf05 1709
e6c3b671 1710 my $filename = config_file($vmid);
1e3baf05
DM
1711
1712 die "unable to find configuration file for VM $vmid - no such machine\n"
e6c3b671 1713 if !$nocheck && ! -f $filename;
1e3baf05 1714
e6c3b671 1715 my $pidfile = pidfile_name($vmid);
1e3baf05 1716
e6c3b671
DM
1717 if (my $fd = IO::File->new("<$pidfile")) {
1718 my $st = stat($fd);
1e3baf05 1719 my $line = <$fd>;
6b64503e 1720 close($fd);
1e3baf05
DM
1721
1722 my $mtime = $st->mtime;
1723 if ($mtime > time()) {
1724 warn "file '$filename' modified in future\n";
1725 }
1726
1727 if ($line =~ m/^(\d+)$/) {
1728 my $pid = $1;
e6c3b671
DM
1729 if (check_cmdline($pidfile, $pid)) {
1730 if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
1731 return $pid;
1732 }
1733 }
1e3baf05
DM
1734 }
1735 }
1736
1737 return undef;
1738}
1739
1740sub vzlist {
19672434 1741
1e3baf05
DM
1742 my $vzlist = config_list();
1743
6b64503e 1744 my $fd = IO::Dir->new($var_run_tmpdir) || return $vzlist;
1e3baf05 1745
19672434 1746 while (defined(my $de = $fd->read)) {
1e3baf05
DM
1747 next if $de !~ m/^(\d+)\.pid$/;
1748 my $vmid = $1;
6b64503e
DM
1749 next if !defined($vzlist->{$vmid});
1750 if (my $pid = check_running($vmid)) {
1e3baf05
DM
1751 $vzlist->{$vmid}->{pid} = $pid;
1752 }
1753 }
1754
1755 return $vzlist;
1756}
1757
1758my $storage_timeout_hash = {};
1759
1760sub disksize {
1761 my ($storecfg, $conf) = @_;
1762
1763 my $bootdisk = $conf->{bootdisk};
1764 return undef if !$bootdisk;
1765 return undef if !valid_drivename($bootdisk);
1766
1767 return undef if !$conf->{$bootdisk};
1768
1769 my $drive = parse_drive($bootdisk, $conf->{$bootdisk});
1770 return undef if !defined($drive);
1771
1772 return undef if drive_is_cdrom($drive);
1773
1774 my $volid = $drive->{file};
1775 return undef if !$volid;
1776
1777 my $path;
1778 my $storeid;
1779 my $timeoutid;
1780
1781 if ($volid =~ m|^/|) {
1782 $path = $timeoutid = $volid;
1783 } else {
6b64503e 1784 $storeid = $timeoutid = PVE::Storage::parse_volume_id($volid);
1e3baf05
DM
1785 $path = PVE::Storage::path($storecfg, $volid);
1786 }
1787
1788 my $last_timeout = $storage_timeout_hash->{$timeoutid};
1789 if ($last_timeout) {
1790 if ((time() - $last_timeout) < 30) {
1791 # skip storage with errors
1792 return undef ;
1793 }
1794 delete $storage_timeout_hash->{$timeoutid};
1795 }
1796
1797 my ($size, $format, $used);
1798
1799 ($size, $format, $used) = PVE::Storage::file_size_info($path, 1);
1800
1801 if (!defined($format)) {
1802 # got timeout
1803 $storage_timeout_hash->{$timeoutid} = time();
1804 return undef;
1805 }
1806
1807 return wantarray ? ($size, $used) : $size;
1808}
1809
1810my $last_proc_pid_stat;
1811
1812sub vmstatus {
1813 my ($opt_vmid) = @_;
1814
1815 my $res = {};
1816
19672434 1817 my $storecfg = PVE::Storage::config();
1e3baf05
DM
1818
1819 my $list = vzlist();
694fcad4 1820 my ($uptime) = PVE::ProcFSTools::read_proc_uptime(1);
1e3baf05
DM
1821
1822 foreach my $vmid (keys %$list) {
1823 next if $opt_vmid && ($vmid ne $opt_vmid);
1824
1825 my $cfspath = cfs_config_path($vmid);
1826 my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
1827
1828 my $d = {};
1829 $d->{pid} = $list->{$vmid}->{pid};
1830
1831 # fixme: better status?
1832 $d->{status} = $list->{$vmid}->{pid} ? 'running' : 'stopped';
1833
1834 my ($size, $used) = disksize($storecfg, $conf);
1835 if (defined($size) && defined($used)) {
1836 $d->{disk} = $used;
1837 $d->{maxdisk} = $size;
1838 } else {
1839 $d->{disk} = 0;
1840 $d->{maxdisk} = 0;
1841 }
1842
1843 $d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
1844 $d->{name} = $conf->{name} || "VM $vmid";
19672434 1845 $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
1e3baf05 1846
1e3baf05
DM
1847 $d->{uptime} = 0;
1848 $d->{cpu} = 0;
1849 $d->{relcpu} = 0;
1850 $d->{mem} = 0;
1851
1852 $d->{netout} = 0;
1853 $d->{netin} = 0;
1854
1855 $d->{diskread} = 0;
1856 $d->{diskwrite} = 0;
1857
1858 $res->{$vmid} = $d;
1859 }
1860
1861 my $netdev = PVE::ProcFSTools::read_proc_net_dev();
1862 foreach my $dev (keys %$netdev) {
1863 next if $dev !~ m/^tap([1-9]\d*)i/;
1864 my $vmid = $1;
1865 my $d = $res->{$vmid};
1866 next if !$d;
19672434 1867
1e3baf05
DM
1868 $d->{netout} += $netdev->{$dev}->{receive};
1869 $d->{netin} += $netdev->{$dev}->{transmit};
1870 }
1871
1e3baf05
DM
1872 my $cpucount = $cpuinfo->{cpus} || 1;
1873 my $ctime = gettimeofday;
1874
1875 foreach my $vmid (keys %$list) {
1876
1877 my $d = $res->{$vmid};
1878 my $pid = $d->{pid};
1879 next if !$pid;
1880
1881 if (my $fh = IO::File->new("/proc/$pid/io", "r")) {
1882 my $data = {};
6b64503e 1883 while (defined(my $line = <$fh>)) {
1e3baf05
DM
1884 if ($line =~ m/^([rw]char):\s+(\d+)$/) {
1885 $data->{$1} = $2;
1886 }
1887 }
1888 close($fh);
1889 $d->{diskread} = $data->{rchar} || 0;
1890 $d->{diskwrite} = $data->{wchar} || 0;
1891 }
1892
694fcad4
DM
1893 my $pstat = PVE::ProcFSTools::read_proc_pid_stat($pid);
1894 next if !$pstat; # not running
19672434 1895
694fcad4 1896 my $used = $pstat->{utime} + $pstat->{stime};
1e3baf05
DM
1897
1898 my $vcpus = $d->{cpus} > $cpucount ? $cpucount : $d->{cpus};
1899
694fcad4 1900 $d->{uptime} = int(($uptime - $pstat->{starttime})/$cpuinfo->{user_hz});
1e3baf05 1901
694fcad4 1902 if ($pstat->{vsize}) {
6b64503e 1903 $d->{mem} = int(($pstat->{rss}/$pstat->{vsize})*$d->{maxmem});
1e3baf05
DM
1904 }
1905
1906 my $old = $last_proc_pid_stat->{$pid};
1907 if (!$old) {
19672434
DM
1908 $last_proc_pid_stat->{$pid} = {
1909 time => $ctime,
1e3baf05
DM
1910 used => $used,
1911 cpu => 0,
1912 relcpu => 0,
1913 };
1914 next;
1915 }
1916
7f0b5beb 1917 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
1e3baf05
DM
1918
1919 if ($dtime > 1000) {
1920 my $dutime = $used - $old->{used};
1921
1922 $d->{cpu} = $dutime/$dtime;
1923 $d->{relcpu} = ($d->{cpu} * $cpucount) / $vcpus;
1924 $last_proc_pid_stat->{$pid} = {
19672434 1925 time => $ctime,
1e3baf05
DM
1926 used => $used,
1927 cpu => $d->{cpu},
1928 relcpu => $d->{relcpu},
1929 };
1930 } else {
1931 $d->{cpu} = $old->{cpu};
1932 $d->{relcpu} = $old->{relcpu};
1933 }
1934 }
1935
1936 return $res;
1937}
1938
1939sub foreach_drive {
1940 my ($conf, $func) = @_;
1941
1942 foreach my $ds (keys %$conf) {
1943 next if !valid_drivename($ds);
1944
6b64503e 1945 my $drive = parse_drive($ds, $conf->{$ds});
1e3baf05
DM
1946 next if !$drive;
1947
1948 &$func($ds, $drive);
1949 }
1950}
1951
1952sub config_to_command {
1953 my ($storecfg, $vmid, $conf, $defaults, $migrate_uri) = @_;
1954
1955 my $cmd = [];
b78ebef7 1956 my $pciaddr = '';
1e3baf05
DM
1957 my $kvmver = kvm_user_version();
1958 my $vernum = 0; # unknown
1959 if ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
1960 $vernum = $1*1000000+$2*1000+$3;
1961 }
1962
1963 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 14000;
1964
1965 my $have_ovz = -f '/proc/vz/vestat';
1966
1967 push @$cmd, '/usr/bin/kvm';
1968
1969 push @$cmd, '-id', $vmid;
1970
1971 my $use_virtio = 0;
1972
6b64503e 1973 my $socket = monitor_socket($vmid);
abb39b66
DA
1974 push @$cmd, '-chardev', "socket,id=monitor,path=$socket,server,nowait";
1975 push @$cmd, '-mon', "chardev=monitor,mode=readline";
1e3baf05 1976
6b64503e 1977 $socket = vnc_socket($vmid);
1e3baf05
DM
1978 push @$cmd, '-vnc', "unix:$socket,x509,password";
1979
6b64503e 1980 push @$cmd, '-pidfile' , pidfile_name($vmid);
19672434 1981
1e3baf05
DM
1982 push @$cmd, '-daemonize';
1983
1984 push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
1985
1986 # include usb device config
1987 push @$cmd, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg';
19672434 1988
1e3baf05 1989 # enable absolute mouse coordinates (needed by vnc)
6b64503e 1990 my $tablet = defined($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
1e3baf05
DM
1991 push @$cmd, '-device', 'usb-tablet,bus=ehci.0,port=6' if $tablet;
1992
1993 # host pci devices
040b06b7
DA
1994 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1995 my $d = parse_hostpci($conf->{"hostpci$i"});
1996 next if !$d;
b78ebef7
DA
1997 $pciaddr = print_pci_addr("hostpci$i");
1998 push @$cmd, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
1e3baf05
DM
1999 }
2000
2001 # usb devices
2002 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2003 my $d = parse_usb_device($conf->{"usb$i"});
2004 next if !$d;
2005 if ($d->{vendorid} && $d->{productid}) {
2006 push @$cmd, '-device', "usb-host,vendorid=$d->{vendorid},productid=$d->{productid}";
2007 } elsif (defined($d->{hostbus}) && defined($d->{hostport})) {
2008 push @$cmd, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2009 }
2010 }
2011
1e3baf05 2012 # serial devices
bae179aa 2013 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
34978be3 2014 if (my $path = $conf->{"serial$i"}) {
19672434 2015 die "no such serial device\n" if ! -c $path;
34978be3
DM
2016 push @$cmd, '-chardev', "tty,id=serial$i,path=$path";
2017 push @$cmd, '-device', "isa-serial,chardev=serial$i";
2018 }
1e3baf05
DM
2019 }
2020
2021 # parallel devices
1989a89c 2022 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
34978be3 2023 if (my $path = $conf->{"parallel$i"}) {
19672434 2024 die "no such parallel device\n" if ! -c $path;
34978be3
DM
2025 push @$cmd, '-chardev', "parport,id=parallel$i,path=$path";
2026 push @$cmd, '-device', "isa-parallel,chardev=parallel$i";
2027 }
1e3baf05
DM
2028 }
2029
2030 my $vmname = $conf->{name} || "vm$vmid";
2031
2032 push @$cmd, '-name', $vmname;
19672434 2033
1e3baf05
DM
2034 my $sockets = 1;
2035 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
2036 $sockets = $conf->{sockets} if $conf->{sockets};
2037
2038 my $cores = $conf->{cores} || 1;
2039
2040 my $boot_opt;
2041
2042 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2043
2044 push @$cmd, '-cpu', $conf->{cpu} if $conf->{cpu};
2045
1e3baf05
DM
2046 push @$cmd, '-nodefaults';
2047
32baffb4
DM
2048 my $bootorder = $conf->{boot} || $confdesc->{boot}->{default};
2049 push @$cmd, '-boot', "menu=on,order=$bootorder";
1e3baf05 2050
6b64503e 2051 push @$cmd, '-no-acpi' if defined($conf->{acpi}) && $conf->{acpi} == 0;
1e3baf05 2052
6b64503e 2053 push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
1e3baf05
DM
2054
2055 my $vga = $conf->{vga};
2056 if (!$vga) {
2057 if ($conf->{ostype} && ($conf->{ostype} eq 'win7' || $conf->{ostype} eq 'w2k8')) {
2058 $vga = 'std';
2059 } else {
2060 $vga = 'cirrus';
2061 }
2062 }
19672434 2063
1e3baf05
DM
2064 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2065
2066 # time drift fix
6b64503e 2067 my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
1e3baf05
DM
2068 push @$cmd, '-tdf' if $tdf;
2069
6b64503e 2070 my $nokvm = defined($conf->{kvm}) && $conf->{kvm} == 0 ? 1 : 0;
1e3baf05
DM
2071
2072 if (my $ost = $conf->{ostype}) {
2073 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2074
2075 if ($ost =~ m/^w/) { # windows
6b64503e 2076 push @$cmd, '-localtime' if !defined($conf->{localtime});
1e3baf05
DM
2077
2078 # use rtc-td-hack when acpi is enabled
6b64503e 2079 if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
1e3baf05
DM
2080 push @$cmd, '-rtc-td-hack';
2081 }
2082 }
2083
2084 # -tdf ?
19672434
DM
2085 # -no-acpi
2086 # -no-kvm
1e3baf05
DM
2087 # -win2k-hack ?
2088 }
2089
7f0b5beb
DM
2090 if ($nokvm) {
2091 push @$cmd, '-no-kvm';
2092 } else {
2093 die "No accelerator found!\n" if !$cpuinfo->{hvm};
2094 }
1e3baf05
DM
2095
2096 push @$cmd, '-localtime' if $conf->{localtime};
2097
2098 push @$cmd, '-startdate', $conf->{startdate} if $conf->{startdate};
2099
2100 push @$cmd, '-S' if $conf->{freeze};
2101
2102 # set keyboard layout
2103 my $kb = $conf->{keyboard} || $defaults->{keyboard};
2104 push @$cmd, '-k', $kb if $kb;
2105
2106 # enable sound
2107 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2108 #push @$cmd, '-soundhw', 'es1370';
2109 #push @$cmd, '-soundhw', $soundhw if $soundhw;
b78ebef7 2110 $pciaddr = print_pci_addr("balloon0");
13b5a753 2111 push @$cmd, '-device', "virtio-balloon-pci,id=balloon0$pciaddr" if $conf->{balloon};
1e3baf05 2112
0ea9541d
DM
2113 if ($conf->{watchdog}) {
2114 my $wdopts = parse_watchdog($conf->{watchdog});
0a40e8ea
DA
2115 $pciaddr = print_pci_addr("watchdog");
2116 my $watchdog = $wdopts->{model} || 'i6300esb';
2117 push @$cmd, '-device', "$watchdog$pciaddr";
0ea9541d
DM
2118 push @$cmd, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
2119 }
2120
1e3baf05 2121 my $vollist = [];
941e0c42 2122 my $scsicontroller = {};
1e3baf05
DM
2123
2124 foreach_drive($conf, sub {
2125 my ($ds, $drive) = @_;
2126
19672434 2127 eval {
6b64503e 2128 PVE::Storage::parse_volume_id($drive->{file});
1e3baf05
DM
2129 push @$vollist, $drive->{file};
2130 }; # ignore errors
2131
2132 $use_virtio = 1 if $ds =~ m/^virtio/;
941e0c42
DA
2133 if ($drive->{interface} eq 'scsi') {
2134 my $maxdev = 7;
6b64503e 2135 my $controller = int($drive->{index} / $maxdev);
4513fd83
DA
2136 $pciaddr = print_pci_addr("scsi$controller");
2137 push @$cmd, '-device', "lsi,id=scsi$controller$pciaddr" if !$scsicontroller->{$controller};
941e0c42
DA
2138 my $scsicontroller->{$controller}=1;
2139 }
6b64503e 2140 my $tmp = print_drive_full($storecfg, $vmid, $drive);
1e3baf05
DM
2141 $tmp .= ",boot=on" if $conf->{bootdisk} && ($conf->{bootdisk} eq $ds);
2142 push @$cmd, '-drive', $tmp;
6b64503e 2143 push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
1e3baf05
DM
2144 });
2145
2146 push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
19672434 2147
1e3baf05
DM
2148 my $foundnet = 0;
2149
2150 foreach my $k (sort keys %$conf) {
2151 next if $k !~ m/^net(\d+)$/;
6b64503e 2152 my $i = int($1);
1e3baf05
DM
2153
2154 die "got strange net id '$i'\n" if $i >= ${MAX_NETS};
2155
2156 if ($conf->{"net$i"} && (my $net = parse_net($conf->{"net$i"}))) {
2157
2158 $foundnet = 1;
2159
2160 my $ifname = "tap${vmid}i$i";
2161
2162 # kvm uses TUNSETIFF ioctl, and that limits ifname length
19672434 2163 die "interface name '$ifname' is too long (max 15 character)\n"
1e3baf05
DM
2164 if length($ifname) >= 16;
2165
2166 my $device = $net->{model};
2167 my $vhostparam = '';
2168 if ($net->{model} eq 'virtio') {
2169 $use_virtio = 1;
2170 $device = 'virtio-net-pci';
2171 $vhostparam = ',vhost=on' if $kernel_has_vhost_net;
2172 };
2173
2174 if ($net->{bridge}) {
2175 push @$cmd, '-netdev', "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
2176 } else {
2177 push @$cmd, '-netdev', "type=user,id=${k},hostname=$vmname";
2178 }
2179
2180 # qemu > 0.15 always try to boot from network - we disable that by
2181 # not loading the pxe rom file
2182 my $extra = (!$conf->{boot} || ($conf->{boot} !~ m/n/)) ?
2183 "romfile=," : '';
f290f8d9
DA
2184 $pciaddr = print_pci_addr("${k}");
2185 push @$cmd, '-device', "$device,${extra}mac=$net->{macaddr},netdev=${k}$pciaddr";
1e3baf05 2186 }
19672434
DM
2187 }
2188
1e3baf05
DM
2189 push @$cmd, '-net', 'none' if !$foundnet;
2190
2191 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2192 # when the VM uses virtio devices.
19672434
DM
2193 if (!$use_virtio && $have_ovz) {
2194
6b64503e 2195 my $cpuunits = defined($conf->{cpuunits}) ?
1e3baf05
DM
2196 $conf->{cpuunits} : $defaults->{cpuunits};
2197
2198 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2199
2200 # fixme: cpulimit is currently ignored
2201 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2202 }
2203
2204 # add custom args
2205 if ($conf->{args}) {
6b64503e 2206 my $aa = split_args($conf->{args});
1e3baf05
DM
2207 push @$cmd, @$aa;
2208 }
2209
2210 return wantarray ? ($cmd, $vollist) : $cmd;
2211}
19672434 2212
1e3baf05
DM
2213sub vnc_socket {
2214 my ($vmid) = @_;
2215 return "${var_run_tmpdir}/$vmid.vnc";
2216}
2217
2218sub monitor_socket {
2219 my ($vmid) = @_;
2220 return "${var_run_tmpdir}/$vmid.mon";
2221}
2222
2223sub pidfile_name {
2224 my ($vmid) = @_;
2225 return "${var_run_tmpdir}/$vmid.pid";
2226}
2227
1e3baf05
DM
2228sub next_migrate_port {
2229
2230 for (my $p = 60000; $p < 60010; $p++) {
2231
6b64503e
DM
2232 my $sock = IO::Socket::INET->new(Listen => 5,
2233 LocalAddr => 'localhost',
2234 LocalPort => $p,
2235 ReuseAddr => 1,
2236 Proto => 0);
1e3baf05
DM
2237
2238 if ($sock) {
6b64503e 2239 close($sock);
1e3baf05
DM
2240 return $p;
2241 }
2242 }
2243
2244 die "unable to find free migration port";
2245}
2246
2247sub vm_start {
2248 my ($storecfg, $vmid, $statefile, $skiplock) = @_;
2249
6b64503e
DM
2250 lock_config($vmid, sub {
2251 my $conf = load_config($vmid);
1e3baf05 2252
6b64503e 2253 check_lock($conf) if !$skiplock;
1e3baf05 2254
6b64503e 2255 if (check_running($vmid)) {
1e3baf05 2256 my $msg = "VM $vmid already running - start failed\n" ;
6b64503e 2257 syslog('err', $msg);
1e3baf05
DM
2258 die $msg;
2259 } else {
6b64503e 2260 syslog('info', "VM $vmid start");
1e3baf05
DM
2261 }
2262
2263 my $migrate_uri;
2264 my $migrate_port = 0;
2265
2266 if ($statefile) {
2267 if ($statefile eq 'tcp') {
2268 $migrate_port = next_migrate_port();
2269 $migrate_uri = "tcp:localhost:${migrate_port}";
2270 } else {
2271 if (-f $statefile) {
2272 $migrate_uri = "exec:cat $statefile";
2273 } else {
2274 warn "state file '$statefile' does not exist - doing normal startup\n";
2275 }
2276 }
2277 }
2278
2279 my $defaults = load_defaults();
2280
e6c3b671 2281 my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $migrate_uri);
1e3baf05 2282 # host pci devices
040b06b7
DA
2283 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2284 my $d = parse_hostpci($conf->{"hostpci$i"});
2285 next if !$d;
2286 my $info = pci_device_info("0000:$d->{pciid}");
2287 die "IOMMU not present\n" if !check_iommu_support();
2288 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2289 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
2290 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
2291 }
1e3baf05
DM
2292
2293 PVE::Storage::activate_volumes($storecfg, $vollist);
2294
6b64503e 2295 eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
1e3baf05
DM
2296
2297 my $err = $@;
2298
2299 if ($err) {
2300 my $msg = "start failed: $err";
6b64503e 2301 syslog('err', "VM $vmid $msg");
1e3baf05
DM
2302 die $msg;
2303 }
2304
2305 if ($statefile) {
2306
2307 if ($statefile eq 'tcp') {
2308 print "migration listens on port $migrate_port\n";
2309 } else {
2310 unlink $statefile;
2311 # fixme: send resume - is that necessary ?
6b64503e 2312 eval { vm_monitor_command($vmid, "cont", 1) };
1e3baf05
DM
2313 }
2314 }
2315
19672434 2316 if (my $migrate_speed =
1e3baf05
DM
2317 $conf->{migrate_speed} || $defaults->{migrate_speed}) {
2318 my $cmd = "migrate_set_speed ${migrate_speed}m";
6b64503e 2319 eval { vm_monitor_command($vmid, $cmd, 1); };
1e3baf05
DM
2320 }
2321
19672434 2322 if (my $migrate_downtime =
1e3baf05
DM
2323 $conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
2324 my $cmd = "migrate_set_downtime ${migrate_downtime}";
6b64503e 2325 eval { vm_monitor_command($vmid, $cmd, 1); };
1e3baf05 2326 }
e6c3b671 2327
7878afeb 2328 vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
1e3baf05
DM
2329 });
2330}
2331
2332sub __read_avail {
2333 my ($fh, $timeout) = @_;
2334
2335 my $sel = new IO::Select;
6b64503e 2336 $sel->add($fh);
1e3baf05
DM
2337
2338 my $res = '';
2339 my $buf;
2340
2341 my @ready;
6b64503e 2342 while (scalar (@ready = $sel->can_read($timeout))) {
1e3baf05 2343 my $count;
6b64503e 2344 if ($count = $fh->sysread($buf, 8192)) {
1e3baf05
DM
2345 if ($buf =~ /^(.*)\(qemu\) $/s) {
2346 $res .= $1;
2347 last;
2348 } else {
2349 $res .= $buf;
2350 }
2351 } else {
6b64503e 2352 if (!defined($count)) {
1e3baf05
DM
2353 die "$!\n";
2354 }
2355 last;
2356 }
2357 }
2358
6b64503e 2359 die "monitor read timeout\n" if !scalar(@ready);
1e3baf05
DM
2360
2361 return $res;
2362}
2363
2364sub vm_monitor_command {
e6c3b671 2365 my ($vmid, $cmdstr, $nolog, $nocheck) = @_;
1e3baf05
DM
2366
2367 my $res;
2368
6b64503e 2369 syslog("info", "VM $vmid monitor command '$cmdstr'") if !$nolog;
1e3baf05
DM
2370
2371 eval {
e6c3b671 2372 die "VM not running\n" if !check_running($vmid, $nocheck);
1e3baf05 2373
e6c3b671 2374 my $sname = monitor_socket($vmid);
1e3baf05 2375
6b64503e 2376 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
1e3baf05
DM
2377 die "unable to connect to VM $vmid socket - $!\n";
2378
2379 my $timeout = 3;
2380
19672434 2381 # hack: migrate sometime blocks the monitor (when migrate_downtime
1e3baf05
DM
2382 # is set)
2383 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2384 $timeout = 60*60; # 1 hour
2385 }
2386
2387 # read banner;
6b64503e 2388 my $data = __read_avail($sock, $timeout);
19672434 2389
1e3baf05
DM
2390 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2391 die "got unexpected qemu monitor banner\n";
2392 }
2393
2394 my $sel = new IO::Select;
6b64503e 2395 $sel->add($sock);
1e3baf05 2396
6b64503e 2397 if (!scalar(my @ready = $sel->can_write($timeout))) {
1e3baf05
DM
2398 die "monitor write error - timeout";
2399 }
2400
2401 my $fullcmd = "$cmdstr\r";
2402
2403 my $b;
6b64503e 2404 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
1e3baf05
DM
2405 die "monitor write error - $!";
2406 }
2407
2408 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2409
19672434 2410 $timeout = 20;
1e3baf05
DM
2411
2412 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2413 $timeout = 60*60; # 1 hour
2414 } elsif ($cmdstr =~ m/^(eject|change)/) {
2415 $timeout = 60; # note: cdrom mount command is slow
2416 }
6b64503e 2417 if ($res = __read_avail($sock, $timeout)) {
19672434 2418
6b64503e 2419 my @lines = split("\r?\n", $res);
1e3baf05
DM
2420
2421 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
19672434 2422
6b64503e 2423 $res = join("\n", @lines);
1e3baf05
DM
2424 $res .= "\n";
2425 }
2426 };
2427
2428 my $err = $@;
2429
2430 if ($err) {
6b64503e 2431 syslog("err", "VM $vmid monitor command failed - $err");
1e3baf05
DM
2432 die $err;
2433 }
2434
2435 return $res;
2436}
2437
2438sub vm_commandline {
2439 my ($storecfg, $vmid) = @_;
2440
6b64503e 2441 my $conf = load_config($vmid);
1e3baf05
DM
2442
2443 my $defaults = load_defaults();
2444
6b64503e 2445 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
1e3baf05 2446
6b64503e 2447 return join(' ', @$cmd);
1e3baf05
DM
2448}
2449
2450sub vm_reset {
2451 my ($vmid, $skiplock) = @_;
2452
6b64503e 2453 lock_config($vmid, sub {
1e3baf05 2454
6b64503e 2455 my $conf = load_config($vmid);
1e3baf05 2456
6b64503e 2457 check_lock($conf) if !$skiplock;
1e3baf05 2458
6b64503e 2459 syslog("info", "VM $vmid sending 'reset'");
1e3baf05 2460
6b64503e 2461 vm_monitor_command($vmid, "system_reset", 1);
1e3baf05
DM
2462 });
2463}
2464
2465sub vm_shutdown {
2466 my ($vmid, $skiplock) = @_;
2467
6b64503e 2468 lock_config($vmid, sub {
1e3baf05 2469
6b64503e 2470 my $conf = load_config($vmid);
1e3baf05 2471
6b64503e 2472 check_lock($conf) if !$skiplock;
1e3baf05 2473
6b64503e 2474 syslog("info", "VM $vmid sending 'shutdown'");
1e3baf05 2475
6b64503e 2476 vm_monitor_command($vmid, "system_powerdown", 1);
1e3baf05
DM
2477 });
2478}
2479
e6c3b671
DM
2480# Note: use $nockeck to skip tests if VM configuration file exists.
2481# We need that when migration VMs to other nodes (files already moved)
1e3baf05 2482sub vm_stop {
e6c3b671 2483 my ($vmid, $skiplock, $nocheck) = @_;
1e3baf05 2484
e6c3b671 2485 lock_config($vmid, sub {
1e3baf05 2486
e6c3b671 2487 my $pid = check_running($vmid, $nocheck);
1e3baf05
DM
2488
2489 if (!$pid) {
e6c3b671 2490 syslog('info', "VM $vmid already stopped");
1e3baf05
DM
2491 return;
2492 }
2493
e6c3b671
DM
2494 if (!$nocheck) {
2495 my $conf = load_config($vmid);
2496 check_lock($conf) if !$skiplock;
2497 }
19672434 2498
6b64503e 2499 syslog("info", "VM $vmid stopping");
1e3baf05 2500
6b64503e 2501 eval { vm_monitor_command($vmid, "quit", 1, $nocheck); };
1e3baf05
DM
2502
2503 my $err = $@;
2504
2505 if (!$err) {
2506 # wait some time
2507 my $timeout = 50; # fixme: how long?
2508
2509 my $count = 0;
e6c3b671 2510 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
2511 $count++;
2512 sleep 1;
2513 }
2514
2515 if ($count >= $timeout) {
6b64503e 2516 syslog('info', "VM $vmid still running - terminating now with SIGTERM");
1e3baf05
DM
2517 kill 15, $pid;
2518 }
2519 } else {
6b64503e 2520 syslog('info', "VM $vmid quit failed - terminating now with SIGTERM");
1e3baf05
DM
2521 kill 15, $pid;
2522 }
2523
2524 # wait again
2525 my $timeout = 10;
2526
2527 my $count = 0;
e6c3b671 2528 while (($count < $timeout) && check_running($vmid, $nocheck)) {
1e3baf05
DM
2529 $count++;
2530 sleep 1;
2531 }
2532
2533 if ($count >= $timeout) {
6b64503e 2534 syslog('info', "VM $vmid still running - terminating now with SIGKILL\n");
1e3baf05
DM
2535 kill 9, $pid;
2536 }
2537
e6c3b671 2538 fairsched_rmnod($vmid); # try to destroy group
1e3baf05
DM
2539 });
2540}
2541
2542sub vm_suspend {
2543 my ($vmid, $skiplock) = @_;
2544
6b64503e 2545 lock_config($vmid, sub {
1e3baf05 2546
6b64503e 2547 my $conf = load_config($vmid);
1e3baf05 2548
6b64503e 2549 check_lock($conf) if !$skiplock;
1e3baf05 2550
6b64503e 2551 syslog("info", "VM $vmid suspend");
1e3baf05 2552
6b64503e 2553 vm_monitor_command($vmid, "stop", 1);
1e3baf05
DM
2554 });
2555}
2556
2557sub vm_resume {
2558 my ($vmid, $skiplock) = @_;
2559
6b64503e 2560 lock_config($vmid, sub {
1e3baf05 2561
6b64503e 2562 my $conf = load_config($vmid);
1e3baf05 2563
6b64503e 2564 check_lock($conf) if !$skiplock;
1e3baf05 2565
6b64503e 2566 syslog("info", "VM $vmid resume");
1e3baf05 2567
6b64503e 2568 vm_monitor_command($vmid, "cont", 1);
1e3baf05
DM
2569 });
2570}
2571
5fdbe4f0
DM
2572sub vm_sendkey {
2573 my ($vmid, $skiplock, $key) = @_;
1e3baf05 2574
6b64503e 2575 lock_config($vmid, sub {
1e3baf05 2576
6b64503e 2577 my $conf = load_config($vmid);
1e3baf05 2578
6b64503e 2579 check_lock($conf) if !$skiplock;
1e3baf05 2580
5fdbe4f0 2581 syslog("info", "VM $vmid sending key $key");
19672434 2582
5fdbe4f0 2583 vm_monitor_command($vmid, "sendkey $key", 1);
1e3baf05
DM
2584 });
2585}
2586
2587sub vm_destroy {
2588 my ($storecfg, $vmid, $skiplock) = @_;
2589
6b64503e 2590 lock_config($vmid, sub {
1e3baf05 2591
6b64503e 2592 my $conf = load_config($vmid);
1e3baf05 2593
6b64503e 2594 check_lock($conf) if !$skiplock;
1e3baf05 2595
6b64503e 2596 syslog("info", "VM $vmid destroy called (removing all data)");
1e3baf05
DM
2597
2598 eval {
2599 if (!check_running($vmid)) {
2600 fairsched_rmnod($vmid); # try to destroy group
2601 destroy_vm($storecfg, $vmid);
2602 } else {
2603 die "VM is running\n";
2604 }
2605 };
2606
2607 my $err = $@;
2608
2609 if ($err) {
6b64503e 2610 syslog("err", "VM $vmid destroy failed - $err");
1e3baf05
DM
2611 die $err;
2612 }
2613 });
2614}
2615
2616sub vm_stopall {
2617 my ($timeout) = @_;
2618
2619 $timeout = 3*60 if !$timeout;
2620
2621 my $vzlist = vzlist();
2622 my $count = 0;
2623 foreach my $vmid (keys %$vzlist) {
2624 next if !$vzlist->{$vmid}->{pid};
2625 $count++;
2626 }
2627
2628 if ($count) {
2629
2630 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs\n";
6b64503e 2631 syslog('info', $msg);
1e3baf05
DM
2632 print STDERR $msg;
2633
2634 foreach my $vmid (keys %$vzlist) {
2635 next if !$vzlist->{$vmid}->{pid};
6b64503e 2636 eval { vm_shutdown($vmid, 1); };
1e3baf05
DM
2637 print STDERR $@ if $@;
2638 }
2639
2640 my $wt = 5;
6b64503e 2641 my $maxtries = int(($timeout + $wt -1)/$wt);
1e3baf05
DM
2642 my $try = 0;
2643 while (($try < $maxtries) && $count) {
2644 $try++;
2645 sleep $wt;
2646
2647 $vzlist = vzlist();
2648 $count = 0;
2649 foreach my $vmid (keys %$vzlist) {
2650 next if !$vzlist->{$vmid}->{pid};
2651 $count++;
2652 }
2653 last if !$count;
2654 }
2655
2656 return if !$count;
2657
2658 foreach my $vmid (keys %$vzlist) {
2659 next if !$vzlist->{$vmid}->{pid};
19672434 2660
1e3baf05 2661 $msg = "VM $vmid still running - sending stop now\n";
6b64503e 2662 syslog('info', $msg);
1e3baf05
DM
2663 print $msg;
2664
6b64503e 2665 eval { vm_monitor_command($vmid, "quit", 1); };
1e3baf05
DM
2666 print STDERR $@ if $@;
2667
2668 }
2669
2670 $timeout = 30;
6b64503e 2671 $maxtries = int(($timeout + $wt -1)/$wt);
1e3baf05
DM
2672 $try = 0;
2673 while (($try < $maxtries) && $count) {
2674 $try++;
2675 sleep $wt;
2676
2677 $vzlist = vzlist();
2678 $count = 0;
2679 foreach my $vmid (keys %$vzlist) {
2680 next if !$vzlist->{$vmid}->{pid};
2681 $count++;
2682 }
2683 last if !$count;
2684 }
2685
2686 return if !$count;
2687
2688 foreach my $vmid (keys %$vzlist) {
2689 next if !$vzlist->{$vmid}->{pid};
19672434 2690
1e3baf05 2691 $msg = "VM $vmid still running - terminating now with SIGTERM\n";
6b64503e 2692 syslog('info', $msg);
1e3baf05
DM
2693 print $msg;
2694 kill 15, $vzlist->{$vmid}->{pid};
2695 }
2696
2697 # this is called by system shotdown scripts, so remaining
2698 # processes gets killed anyways (no need to send kill -9 here)
2699
2700 $msg = "Qemu Server stopped\n";
6b64503e 2701 syslog('info', $msg);
1e3baf05
DM
2702 print STDERR $msg;
2703 }
2704}
2705
2706# pci helpers
2707
2708sub file_write {
2709 my ($filename, $buf) = @_;
2710
6b64503e 2711 my $fh = IO::File->new($filename, "w");
1e3baf05
DM
2712 return undef if !$fh;
2713
2714 my $res = print $fh $buf;
2715
2716 $fh->close();
2717
2718 return $res;
2719}
2720
2721sub pci_device_info {
2722 my ($name) = @_;
2723
2724 my $res;
2725
2726 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
2727 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
2728
2729 my $irq = file_read_firstline("$pcisysfs/devices/$name/irq");
2730 return undef if !defined($irq) || $irq !~ m/^\d+$/;
2731
2732 my $vendor = file_read_firstline("$pcisysfs/devices/$name/vendor");
2733 return undef if !defined($vendor) || $vendor !~ s/^0x//;
2734
2735 my $product = file_read_firstline("$pcisysfs/devices/$name/device");
2736 return undef if !defined($product) || $product !~ s/^0x//;
2737
2738 $res = {
2739 name => $name,
2740 vendor => $vendor,
2741 product => $product,
2742 domain => $domain,
2743 bus => $bus,
2744 slot => $slot,
2745 func => $func,
2746 irq => $irq,
2747 has_fl_reset => -f "$pcisysfs/devices/$name/reset" || 0,
2748 };
2749
2750 return $res;
2751}
2752
2753sub pci_dev_reset {
2754 my ($dev) = @_;
2755
2756 my $name = $dev->{name};
2757
2758 my $fn = "$pcisysfs/devices/$name/reset";
2759
6b64503e 2760 return file_write($fn, "1");
1e3baf05
DM
2761}
2762
2763sub pci_dev_bind_to_stub {
2764 my ($dev) = @_;
2765
2766 my $name = $dev->{name};
2767
2768 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
2769 return 1 if -d $testdir;
2770
2771 my $data = "$dev->{vendor} $dev->{product}";
6b64503e 2772 return undef if !file_write("$pcisysfs/drivers/pci-stub/new_id", $data);
1e3baf05
DM
2773
2774 my $fn = "$pcisysfs/devices/$name/driver/unbind";
6b64503e 2775 if (!file_write($fn, $name)) {
1e3baf05
DM
2776 return undef if -f $fn;
2777 }
2778
2779 $fn = "$pcisysfs/drivers/pci-stub/bind";
2780 if (! -d $testdir) {
6b64503e 2781 return undef if !file_write($fn, $name);
1e3baf05
DM
2782 }
2783
2784 return -d $testdir;
2785}
2786
6b64503e 2787sub print_pci_addr {
72a063e4 2788 my ($id) = @_;
6b64503e 2789
72a063e4 2790 my $res = '';
6b64503e 2791 my $devices = {
e5f7f8ed
DA
2792 #addr1 : ide,parallel,serial (motherboard)
2793 #addr2 : first videocard
13b5a753 2794 balloon0 => { bus => 0, addr => 3 },
0a40e8ea 2795 watchdog => { bus => 0, addr => 4 },
4513fd83
DA
2796 scsi0 => { bus => 0, addr => 5 },
2797 scsi1 => { bus => 0, addr => 6 },
6b64503e
DM
2798 virtio0 => { bus => 0, addr => 10 },
2799 virtio1 => { bus => 0, addr => 11 },
2800 virtio2 => { bus => 0, addr => 12 },
2801 virtio3 => { bus => 0, addr => 13 },
2802 virtio4 => { bus => 0, addr => 14 },
2803 virtio5 => { bus => 0, addr => 15 },
b78ebef7
DA
2804 hostpci0 => { bus => 0, addr => 16 },
2805 hostpci1 => { bus => 0, addr => 17 },
f290f8d9
DA
2806 net0 => { bus => 0, addr => 18 },
2807 net1 => { bus => 0, addr => 19 },
2808 net2 => { bus => 0, addr => 20 },
2809 net3 => { bus => 0, addr => 21 },
2810 net4 => { bus => 0, addr => 22 },
2811 net5 => { bus => 0, addr => 23 },
e5f7f8ed 2812 #addr29 : usb-host (pve-usb.cfg)
6b64503e
DM
2813 };
2814
2815 if (defined($devices->{$id}->{bus}) && defined($devices->{$id}->{addr})) {
72a063e4
DA
2816 my $addr = sprintf("0x%x", $devices->{$id}->{addr});
2817 $res = ",bus=pci.$devices->{$id}->{bus},addr=$addr";
2818 }
2819 return $res;
2820
2821}
2822
13a48620 2823sub vm_balloonset {
7878afeb 2824 my ($vmid, $value) = @_;
13a48620 2825
7878afeb 2826 vm_monitor_command($vmid, "balloon $value", 1);
13a48620
DA
2827}
2828
1e3baf05 28291;