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