]>
git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer.pm
1 package PVE
:: QemuServer
;
20 use Storable
qw(dclone) ;
21 use PVE
:: Exception
qw(raise raise_param_exc) ;
23 use PVE
:: Tools
qw(run_command lock_file file_read_firstline) ;
24 use PVE
:: Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file) ;
27 use Time
:: HiRes
qw(gettimeofday) ;
29 my $cpuinfo = PVE
:: ProcFSTools
:: read_cpuinfo
();
31 # Note about locking: we use flock on the config file protect
32 # against concurent actions.
33 # Aditionaly, we have a 'lock' setting in the config file. This
34 # can be set to 'migrate' or 'backup'. Most actions are not
35 # allowed when such lock is set. But you can ignore this kind of
36 # lock with the --skiplock flag.
38 cfs_register_file
( '/qemu-server/' ,
42 PVE
:: JSONSchema
:: register_standard_option
( 'skiplock' , {
43 description
=> "Ignore locks - only root is allowed to use this option." ,
48 PVE
:: JSONSchema
:: register_standard_option
( 'pve-qm-stateuri' , {
49 description
=> "Some command save/restore state from this location." ,
55 #no warnings 'redefine';
57 unless ( defined (& _VZSYSCALLS_H_
)) {
58 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined (& _VZSYSCALLS_H_
);
59 require 'sys/syscall.ph' ;
60 if ( defined (& __x86_64__
)) {
61 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined (& __NR_fairsched_vcpus
);
62 eval 'sub __NR_fairsched_mknod () {504;}' unless defined (& __NR_fairsched_mknod
);
63 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined (& __NR_fairsched_rmnod
);
64 eval 'sub __NR_fairsched_chwt () {506;}' unless defined (& __NR_fairsched_chwt
);
65 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined (& __NR_fairsched_mvpr
);
66 eval 'sub __NR_fairsched_rate () {508;}' unless defined (& __NR_fairsched_rate
);
67 eval 'sub __NR_setluid () {501;}' unless defined (& __NR_setluid
);
68 eval 'sub __NR_setublimit () {502;}' unless defined (& __NR_setublimit
);
70 elsif ( defined ( & __i386__
) ) {
71 eval 'sub __NR_fairsched_mknod () {500;}' unless defined (& __NR_fairsched_mknod
);
72 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined (& __NR_fairsched_rmnod
);
73 eval 'sub __NR_fairsched_chwt () {502;}' unless defined (& __NR_fairsched_chwt
);
74 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined (& __NR_fairsched_mvpr
);
75 eval 'sub __NR_fairsched_rate () {504;}' unless defined (& __NR_fairsched_rate
);
76 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined (& __NR_fairsched_vcpus
);
77 eval 'sub __NR_setluid () {511;}' unless defined (& __NR_setluid
);
78 eval 'sub __NR_setublimit () {512;}' unless defined (& __NR_setublimit
);
80 die ( "no fairsched syscall for this arch" );
82 require 'asm/ioctl.ph' ;
83 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined (& KVM_GET_API_VERSION
);
87 my ( $parent, $weight, $desired ) = @_ ;
89 return syscall (& __NR_fairsched_mknod
, int ( $parent ), int ( $weight ), int ( $desired ));
95 return syscall (& __NR_fairsched_rmnod
, int ( $id ));
99 my ( $pid, $newid ) = @_ ;
101 return syscall (& __NR_fairsched_mvpr
, int ( $pid ), int ( $newid ));
104 sub fairsched_vcpus
{
105 my ( $id, $vcpus ) = @_ ;
107 return syscall (& __NR_fairsched_vcpus
, int ( $id ), int ( $vcpus ));
111 my ( $id, $op, $rate ) = @_ ;
113 return syscall (& __NR_fairsched_rate
, int ( $id ), int ( $op ), int ( $rate ));
116 use constant FAIRSCHED_SET_RATE
=> 0 ;
117 use constant FAIRSCHED_DROP_RATE
=> 1 ;
118 use constant FAIRSCHED_GET_RATE
=> 2 ;
120 sub fairsched_cpulimit
{
121 my ( $id, $limit ) = @_ ;
123 my $cpulim1024 = int ( $limit * 1024 / 100 );
124 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
126 return fairsched_rate
( $id, $op, $cpulim1024 );
129 my $nodename = PVE
:: INotify
:: nodename
();
131 mkdir "/etc/pve/nodes/ $nodename " ;
132 my $confdir = "/etc/pve/nodes/ $nodename/qemu -server" ;
135 my $var_run_tmpdir = "/var/run/qemu-server" ;
136 mkdir $var_run_tmpdir ;
138 my $lock_dir = "/var/lock/qemu-server" ;
141 my $pcisysfs = "/sys/bus/pci" ;
147 description
=> "Specifies whether a VM will be started during system bootup." ,
153 description
=> "Automatic restart after crash (currently ignored)." ,
159 description
=> "Activate hotplug for disk and network device" ,
165 description
=> "Allow reboot. If set to '0' the VM exit on reboot." ,
171 description
=> "Lock/unlock the VM." ,
172 enum
=> [ qw(migrate backup) ],
177 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit. \n\n NOTE: This option is currently ignored." ,
184 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs. \n\n NOTE: You can disable fair-scheduler configuration by setting this to 0." ,
192 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device." ,
199 description
=> "Amount of target RAM for the VM in MB." ,
205 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file." ,
206 enum
=> PVE
:: Tools
:: kvmkeymaplist
(),
212 description
=> "Set a name for the VM. Only used on the configuration web interface." ,
217 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file." ,
222 enum
=> [ qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26) ],
223 description
=> <<EODESC,
224 Used to enable special optimization/features for specific
227 other => unspecified OS
228 wxp => Microsoft Windows XP
229 w2k => Microsoft Windows 2000
230 w2k3 => Microsoft Windows 2003
231 w2k8 => Microsoft Windows 2008
232 wvista => Microsoft Windows Vista
233 win7 => Microsoft Windows 7
234 l24 => Linux 2.4 Kernel
235 l26 => Linux 2.6/3.X Kernel
237 other|l24|l26 ... no special behaviour
238 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
244 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." ,
245 pattern
=> '[acdn]{1,4}' ,
250 type
=> 'string' , format
=> 'pve-qm-bootdisk' ,
251 description
=> "Enable booting from specified disk." ,
252 pattern
=> '(ide|scsi|virtio)\d+' ,
257 description
=> "The number of CPUs. Please use option -sockets instead." ,
264 description
=> "The number of CPU sockets." ,
271 description
=> "The number of cores per socket." ,
278 description
=> "Enable/disable ACPI." ,
284 description
=> "Enable/disable KVM hardware virtualization." ,
290 description
=> "Enable/disable time drift fix. This is ignored for kvm versions newer that 1.0 (not needed anymore)." ,
296 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS." ,
301 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution)." ,
306 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win7/w2k8, and 'cirrur' for other OS types" ,
307 enum
=> [ qw(std cirrus vmware) ],
311 type
=> 'string' , format
=> 'pve-qm-watchdog' ,
312 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]' ,
313 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)" ,
318 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)" ,
319 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'." ,
320 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)' ,
326 description
=> <<EODESCR,
327 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
329 args: -no-reboot -no-hpet
336 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. Else the mouse runs out of sync with normal vnc clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches." ,
341 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit." ,
345 migrate_downtime
=> {
348 description
=> "Set maximum tolerated downtime (in seconds) for migrations." ,
354 type
=> 'string' , format
=> 'pve-qm-drive' ,
355 typetext
=> 'volume' ,
356 description
=> "This is an alias for option -ide2" ,
360 description
=> "Emulated CPU type." ,
362 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom cpu64-rhel6 cpu64-rhel5 Conroe Penryn Nehalem Westmere Opteron_G1 Opteron_G2 Opteron_G3 host) ],
367 # what about other qemu settings ?
369 #machine => 'string',
382 ##soundhw => 'string',
384 while ( my ( $k, $v ) = each %$confdesc ) {
385 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm- $k " , $v );
388 my $MAX_IDE_DISKS = 4 ;
389 my $MAX_SCSI_DISKS = 14 ;
390 my $MAX_VIRTIO_DISKS = 6 ;
391 my $MAX_SATA_DISKS = 6 ;
392 my $MAX_USB_DEVICES = 5 ;
394 my $MAX_UNUSED_DISKS = 8 ;
395 my $MAX_HOSTPCI_DEVICES = 2 ;
396 my $MAX_SERIAL_PORTS = 4 ;
397 my $MAX_PARALLEL_PORTS = 3 ;
399 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
400 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
401 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
406 type
=> 'string' , format
=> 'pve-qm-net' ,
407 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
408 description
=> <<EODESCR,
409 Specify network devices.
411 MODEL is one of: $nic_model_list_txt
413 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
414 automatically generated if not specified.
416 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
418 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
420 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
426 The DHCP server assign addresses to the guest starting from 10.0.2.15.
430 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
432 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
433 $confdesc ->{ "net $i " } = $netdesc ;
440 type
=> 'string' , format
=> 'pve-qm-drive' ,
441 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]' ,
442 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
444 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
448 type
=> 'string' , format
=> 'pve-qm-drive' ,
449 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]' ,
450 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
452 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
456 type
=> 'string' , format
=> 'pve-qm-drive' ,
457 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]' ,
458 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to 5)." ,
460 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-sata" , $satadesc );
464 type
=> 'string' , format
=> 'pve-qm-drive' ,
465 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]' ,
466 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
468 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
472 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
473 typetext
=> 'host=HOSTUSBDEVICE' ,
474 description
=> <<EODESCR,
475 Configure an USB device (n is 0 to 4). This can be used to
476 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
478 'bus-port(.port)*' (decimal numbers) or
479 'vendor_id:product_id' (hexadeciaml numbers)
481 You can use the 'lsusb -t' command to list existing usb devices.
483 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
487 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
491 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
492 typetext
=> "HOSTPCIDEVICE" ,
493 description
=> <<EODESCR,
494 Map host pci devices. HOSTPCIDEVICE syntax is:
496 'bus:dev.func' (hexadecimal numbers)
498 You can us the 'lspci' command to list existing pci devices.
500 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
502 Experimental: user reported problems with this option.
505 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
510 pattern
=> '/dev/ttyS\d+' ,
511 description
=> <<EODESCR,
512 Map host serial devices (n is 0 to 3).
514 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
516 Experimental: user reported problems with this option.
523 pattern
=> '/dev/parport\d+' ,
524 description
=> <<EODESCR,
525 Map host parallel devices (n is 0 to 2).
527 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
529 Experimental: user reported problems with this option.
533 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
534 $confdesc ->{ "parallel $i " } = $paralleldesc ;
537 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
538 $confdesc ->{ "serial $i " } = $serialdesc ;
541 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
542 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
545 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
546 $drivename_hash ->{ "ide $i " } = 1 ;
547 $confdesc ->{ "ide $i " } = $idedesc ;
550 for ( my $i = 0 ; $i < $MAX_SATA_DISKS ; $i++ ) {
551 $drivename_hash ->{ "sata $i " } = 1 ;
552 $confdesc ->{ "sata $i " } = $satadesc ;
555 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
556 $drivename_hash ->{ "scsi $i " } = 1 ;
557 $confdesc ->{ "scsi $i " } = $scsidesc ;
560 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
561 $drivename_hash ->{ "virtio $i " } = 1 ;
562 $confdesc ->{ "virtio $i " } = $virtiodesc ;
565 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
566 $confdesc ->{ "usb $i " } = $usbdesc ;
571 type
=> 'string' , format
=> 'pve-volume-id' ,
572 description
=> "Reference to unused volumes." ,
575 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
576 $confdesc ->{ "unused $i " } = $unuseddesc ;
579 my $kvm_api_version = 0 ;
583 return $kvm_api_version if $kvm_api_version ;
585 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
588 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
589 $kvm_api_version = $v ;
594 return $kvm_api_version ;
597 my $kvm_user_version ;
599 sub kvm_user_version
{
601 return $kvm_user_version if $kvm_user_version ;
603 $kvm_user_version = 'unknown' ;
605 my $tmp = `kvm -help 2>/dev/null` ;
607 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) / ) {
608 $kvm_user_version = $2 ;
611 return $kvm_user_version ;
615 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
618 # order is important - used to autoselect boot disk
619 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
620 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
621 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))),
622 ( map { "sata $_ " } ( 0 .. ( $MAX_SATA_DISKS - 1 ))));
625 sub valid_drivename
{
628 return defined ( $drivename_hash ->{ $dev });
633 return defined ( $confdesc ->{ $key });
637 return $nic_model_list ;
640 sub os_list_description
{
645 w2k
=> 'Windows 2000' ,
646 w2k3
=>, 'Windows 2003' ,
647 w2k8
=> 'Windows 2008' ,
648 wvista
=> 'Windows Vista' ,
655 sub disk_devive_info
{
658 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
666 } elsif ( $bus eq 'scsi' ) {
670 my $controller = int ( $index / $maxdev );
671 my $unit = $index % $maxdev ;
674 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
675 controller
=> $controller, unit
=> $unit, index => $index };
679 sub qemu_drive_name
{
680 my ( $dev, $media ) = @_ ;
682 my $info = disk_devive_info
( $dev );
685 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
686 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
687 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
688 $mediastr, $info ->{ unit
});
690 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
698 return $cdrom_path if $cdrom_path ;
700 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
701 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
702 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
706 my ( $storecfg, $vmid, $cdrom ) = @_ ;
708 if ( $cdrom eq 'cdrom' ) {
709 return get_cdrom_path
();
710 } elsif ( $cdrom eq 'none' ) {
712 } elsif ( $cdrom =~ m
|^/|) {
715 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
719 # try to convert old style file names to volume IDs
720 sub filename_to_volume_id
{
721 my ( $vmid, $file, $media ) = @_ ;
723 if (!( $file eq 'none' || $file eq 'cdrom' ||
724 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
726 return undef if $file =~ m
|/|;
728 if ( $media && $media eq 'cdrom' ) {
729 $file = "local:iso/ $file " ;
731 $file = "local: $vmid/$file " ;
738 sub verify_media_type
{
739 my ( $opt, $vtype, $media ) = @_ ;
744 if ( $media eq 'disk' ) {
746 } elsif ( $media eq 'cdrom' ) {
749 die "internal error" ;
752 return if ( $vtype eq $etype );
754 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
757 sub cleanup_drive_path
{
758 my ( $opt, $storecfg, $drive ) = @_ ;
760 # try to convert filesystem paths to volume IDs
762 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
763 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
764 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
765 ( $drive ->{ file
} !~ m/^\d+$/ )) {
766 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
767 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
768 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
769 verify_media_type
( $opt, $vtype, $drive ->{ media
});
770 $drive ->{ file
} = $volid ;
773 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
776 sub create_conf_nolock
{
777 my ( $vmid, $settings ) = @_ ;
779 my $filename = config_file
( $vmid );
781 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
783 my $defaults = load_defaults
();
785 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
786 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
789 foreach my $opt ( keys %$settings ) {
790 next if ! $confdesc ->{ $opt };
792 my $value = $settings ->{ $opt };
795 $data .= " $opt : $value\n " ;
798 PVE
:: Tools
:: file_set_contents
( $filename, $data );
801 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
802 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
803 # [,aio=native|threads]
806 my ( $key, $data ) = @_ ;
810 # $key may be undefined - used to verify JSON parameters
811 if (! defined ( $key )) {
812 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
814 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
815 $res ->{ interface
} = $1 ;
821 foreach my $p ( split ( /,/ , $data )) {
822 next if $p =~ m/^\s*$/ ;
824 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
825 my ( $k, $v ) = ( $1, $2 );
827 $k = 'file' if $k eq 'volume' ;
829 return undef if defined $res ->{ $k };
833 if (! $res ->{ file
} && $p !~ m/=/ ) {
841 return undef if ! $res ->{ file
};
843 return undef if $res ->{ cache
} &&
844 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback|unsafe)$/ ;
845 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
846 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
847 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
848 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
849 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
850 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
851 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
852 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
853 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
854 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
855 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
857 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
858 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
859 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
860 return undef if $res ->{ interface
} eq 'virtio' ;
863 # rerror does not work with scsi drives
864 if ( $res ->{ rerror
}) {
865 return undef if $res ->{ interface
} eq 'scsi' ;
871 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
874 my ( $vmid, $drive ) = @_ ;
877 foreach my $o ( @qemu_drive_options, 'backup' ) {
878 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
881 return " $drive ->{file} $opts " ;
884 sub print_drivedevice_full
{
885 my ( $storecfg, $vmid, $drive ) = @_ ;
890 if ( $drive ->{ interface
} eq 'virtio' ) {
891 my $pciaddr = print_pci_addr
( " $drive ->{interface} $drive ->{index}" );
892 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index} $pciaddr " ;
893 } elsif ( $drive ->{ interface
} eq 'scsi' ) {
895 my $controller = int ( $drive ->{ index } / $maxdev );
896 my $unit = $drive ->{ index } % $maxdev ;
897 my $devicetype = 'hd' ;
899 if ( drive_is_cdrom
( $drive )) {
902 if ( $drive ->{ file
} =~ m
|^/|) {
903 $path = $drive ->{ file
};
905 $path = PVE
:: Storage
:: path
( $storecfg, $drive ->{ file
});
907 if ( $path =~ m
|^ /dev/ | ) {
908 $devicetype = 'block' ;
912 $device = "scsi- $devicetype,bus =lsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
913 } elsif ( $drive ->{ interface
} eq 'ide' ){
915 my $controller = int ( $drive ->{ index } / $maxdev );
916 my $unit = $drive ->{ index } % $maxdev ;
917 my $devicetype = ( $drive ->{ media
} && $drive ->{ media
} eq 'cdrom' ) ?
"cd" : "hd" ;
919 $device = "ide- $devicetype,bus =ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
920 } elsif ( $drive ->{ interface
} eq 'sata' ){
921 my $controller = int ( $drive ->{ index } / $MAX_SATA_DISKS );
922 my $unit = $drive ->{ index } % $MAX_SATA_DISKS ;
923 $device = "ide-drive,bus=ahci $controller . $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
924 } elsif ( $drive ->{ interface
} eq 'usb' ) {
926 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
928 die "unsupported interface type" ;
931 $device .= ",bootindex= $drive ->{bootindex}" if $drive ->{ bootindex
};
936 sub print_drive_full
{
937 my ( $storecfg, $vmid, $drive ) = @_ ;
940 foreach my $o ( @qemu_drive_options ) {
941 next if $o eq 'bootindex' ;
942 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
945 # use linux-aio by default (qemu default is threads)
946 $opts .= ",aio=native" if ! $drive ->{ aio
};
949 my $volid = $drive ->{ file
};
950 if ( drive_is_cdrom
( $drive )) {
951 $path = get_iso_path
( $storecfg, $vmid, $volid );
953 if ( $volid =~ m
|^/|) {
956 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
958 if (! $drive ->{ cache
} && ( $path =~ m
|^ /dev/ | || $path =~ m
| \
. raw
$|)) {
959 $opts .= ",cache=none" ;
963 my $pathinfo = $path ?
"file= $path, " : '' ;
965 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
968 sub print_netdevice_full
{
969 my ( $vmid, $conf, $net, $netid ) = @_ ;
971 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
973 my $device = $net ->{ model
};
974 if ( $net ->{ model
} eq 'virtio' ) {
975 $device = 'virtio-net-pci' ;
978 # qemu > 0.15 always try to boot from network - we disable that by
979 # not loading the pxe rom file
980 my $extra = ( $bootorder !~ m/n/ ) ?
"romfile=," : '' ;
981 my $pciaddr = print_pci_addr
( " $netid " );
982 my $tmpstr = " $device,$ {extra}mac= $net ->{macaddr},netdev= $netid$pciaddr,id = $netid " ;
983 $tmpstr .= ",bootindex= $net ->{bootindex}" if $net ->{ bootindex
} ;
987 sub print_netdev_full
{
988 my ( $vmid, $conf, $net, $netid ) = @_ ;
991 if ( $netid =~ m/^net(\d+)$/ ) {
995 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
997 my $ifname = "tap${vmid}i $i " ;
999 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1000 die "interface name ' $ifname ' is too long (max 15 character) \n "
1001 if length ( $ifname ) >= 16 ;
1003 my $vhostparam = '' ;
1004 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net ->{ model
} eq 'virtio' ;
1006 my $vmname = $conf ->{ name
} || "vm $vmid " ;
1008 if ( $net ->{ bridge
}) {
1009 return "type=tap,id= $netid,ifname =${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
1011 return "type=user,id= $netid,hostname = $vmname " ;
1015 sub drive_is_cdrom
{
1018 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
1025 return undef if ! $value ;
1029 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
1030 $res ->{ pciid
} = $value ;
1038 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1044 foreach my $kvp ( split ( /,/ , $data )) {
1046 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
1048 my $mac = uc ( $3 ) || PVE
:: Tools
:: random_ether_addr
();
1049 $res ->{ model
} = $model ;
1050 $res ->{ macaddr
} = $mac ;
1051 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
1052 $res ->{ bridge
} = $1 ;
1053 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
1061 return undef if ! $res ->{ model
};
1069 my $res = " $net ->{model}" ;
1070 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
1071 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
1072 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
1077 sub add_random_macs
{
1078 my ( $settings ) = @_ ;
1080 foreach my $opt ( keys %$settings ) {
1081 next if $opt !~ m/^net(\d+)$/ ;
1082 my $net = parse_net
( $settings ->{ $opt });
1084 $settings ->{ $opt } = print_net
( $net );
1088 sub add_unused_volume
{
1089 my ( $config, $volid ) = @_ ;
1092 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1093 my $test = "unused $ind " ;
1094 if ( my $vid = $config ->{ $test }) {
1095 return if $vid eq $volid ; # do not add duplicates
1101 die "To many unused volume - please delete them first. \n " if ! $key ;
1103 $config ->{ $key } = $volid ;
1108 # fixme: remove all thos $noerr parameters?
1110 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1111 sub verify_bootdisk
{
1112 my ( $value, $noerr ) = @_ ;
1114 return $value if valid_drivename
( $value );
1116 return undef if $noerr ;
1118 die "invalid boot disk ' $value ' \n " ;
1121 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1123 my ( $value, $noerr ) = @_ ;
1125 return $value if parse_net
( $value );
1127 return undef if $noerr ;
1129 die "unable to parse network options \n " ;
1132 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1134 my ( $value, $noerr ) = @_ ;
1136 return $value if parse_drive
( undef , $value );
1138 return undef if $noerr ;
1140 die "unable to parse drive options \n " ;
1143 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1144 sub verify_hostpci
{
1145 my ( $value, $noerr ) = @_ ;
1147 return $value if parse_hostpci
( $value );
1149 return undef if $noerr ;
1151 die "unable to parse pci id \n " ;
1154 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1155 sub verify_watchdog
{
1156 my ( $value, $noerr ) = @_ ;
1158 return $value if parse_watchdog
( $value );
1160 return undef if $noerr ;
1162 die "unable to parse watchdog options \n " ;
1165 sub parse_watchdog
{
1168 return undef if ! $value ;
1172 foreach my $p ( split ( /,/ , $value )) {
1173 next if $p =~ m/^\s*$/ ;
1175 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1177 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1178 $res ->{ action
} = $2 ;
1187 sub parse_usb_device
{
1190 return undef if ! $value ;
1192 my @dl = split ( /,/ , $value );
1196 foreach my $v ( @dl ) {
1197 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1199 $res ->{ vendorid
} = $1 ;
1200 $res ->{ productid
} = $2 ;
1201 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1203 $res ->{ hostbus
} = $1 ;
1204 $res ->{ hostport
} = $2 ;
1209 return undef if ! $found ;
1214 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1215 sub verify_usb_device
{
1216 my ( $value, $noerr ) = @_ ;
1218 return $value if parse_usb_device
( $value );
1220 return undef if $noerr ;
1222 die "unable to parse usb device \n " ;
1225 # add JSON properties for create and set function
1226 sub json_config_properties
{
1229 foreach my $opt ( keys %$confdesc ) {
1230 $prop ->{ $opt } = $confdesc ->{ $opt };
1237 my ( $key, $value ) = @_ ;
1239 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1241 my $type = $confdesc ->{ $key }->{ type
};
1243 if (! defined ( $value )) {
1244 die "got undefined value \n " ;
1247 if ( $value =~ m/[\n\r]/ ) {
1248 die "property contains a line feed \n " ;
1251 if ( $type eq 'boolean' ) {
1252 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1253 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1254 die "type check ('boolean') failed - got ' $value ' \n " ;
1255 } elsif ( $type eq 'integer' ) {
1256 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1257 die "type check ('integer') failed - got ' $value ' \n " ;
1258 } elsif ( $type eq 'string' ) {
1259 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1260 if ( $fmt eq 'pve-qm-drive' ) {
1261 # special case - we need to pass $key to parse_drive()
1262 my $drive = parse_drive
( $key, $value );
1263 return $value if $drive ;
1264 die "unable to parse drive options \n " ;
1266 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1269 $value =~ s/^\"(.*)\"$/$1/ ;
1272 die "internal error"
1277 my ( $vmid, $code, @param ) = @_ ;
1279 my $filename = config_file_lock
( $vmid );
1281 my $res = lock_file
( $filename, 10 , $code, @param );
1288 sub cfs_config_path
{
1289 my ( $vmid, $node ) = @_ ;
1291 $node = $nodename if ! $node ;
1292 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1295 sub check_iommu_support
{
1296 #fixme : need to check IOMMU support
1297 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1305 my ( $vmid, $node ) = @_ ;
1307 my $cfspath = cfs_config_path
( $vmid, $node );
1308 return "/etc/pve/ $cfspath " ;
1311 sub config_file_lock
{
1314 return " $lock_dir/lock - $vmid .conf" ;
1320 my $conf = config_file
( $vmid );
1321 utime undef , undef , $conf ;
1325 my ( $storecfg, $vmid, $keep_empty_config ) = @_ ;
1327 my $conffile = config_file
( $vmid );
1329 my $conf = load_config
( $vmid );
1333 # only remove disks owned by this VM
1334 foreach_drive
( $conf, sub {
1335 my ( $ds, $drive ) = @_ ;
1337 return if drive_is_cdrom
( $drive );
1339 my $volid = $drive ->{ file
};
1340 return if ! $volid || $volid =~ m
|^/|;
1342 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1343 return if ! $path || ! $owner || ( $owner != $vmid );
1345 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1348 if ( $keep_empty_config ) {
1349 PVE
:: Tools
:: file_set_contents
( $conffile, "memory: 128 \n " );
1354 # also remove unused disk
1356 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1359 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1360 my ( $volid, $sid, $volname, $d ) = @_ ;
1361 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1371 sub load_diskinfo_old
{
1372 my ( $storecfg, $vmid, $conf ) = @_ ;
1378 foreach_drive
( $conf, sub {
1383 return if drive_is_cdrom
( $di );
1385 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1386 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1388 push @$vollist, $di ->{ file
};
1393 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1395 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1396 my ( $volid, $sid, $volname, $d ) = @_ ;
1397 $info ->{ $volid } = $d ;
1402 foreach my $ds ( keys %$res ) {
1403 my $di = $res ->{ $ds };
1405 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1406 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1415 my $cfspath = cfs_config_path
( $vmid );
1417 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1419 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1424 sub parse_vm_config
{
1425 my ( $filename, $raw ) = @_ ;
1427 return undef if ! defined ( $raw );
1430 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1433 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1434 || die "got strange filename ' $filename '" ;
1440 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1443 next if $line =~ m/^\s*$/ ;
1445 if ( $line =~ m/^\#(.*)\s*$/ ) {
1446 $descr .= PVE
:: Tools
:: decode_text
( $1 ) . " \n " ;
1450 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1451 $descr .= PVE
:: Tools
:: decode_text
( $2 );
1452 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1455 $res ->{ $key } = $value ;
1456 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1459 eval { $value = check_type
( $key, $value ); };
1461 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1463 my $fmt = $confdesc ->{ $key }->{ format
};
1464 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1465 my $v = parse_drive
( $key, $value );
1466 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1467 $v ->{ file
} = $volid ;
1468 $value = print_drive
( $vmid, $v );
1470 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1475 if ( $key eq 'cdrom' ) {
1476 $res ->{ ide2
} = $value ;
1478 $res ->{ $key } = $value ;
1484 $res ->{ description
} = $descr if $descr ;
1486 # convert old smp to sockets
1487 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1488 $res ->{ sockets
} = $res ->{ smp
};
1495 sub write_vm_config
{
1496 my ( $filename, $conf ) = @_ ;
1498 if ( $conf ->{ cdrom
}) {
1499 die "option ide2 conflicts with cdrom \n " if $conf ->{ ide2
};
1500 $conf ->{ ide2
} = $conf ->{ cdrom
};
1501 delete $conf ->{ cdrom
};
1504 # we do not use 'smp' any longer
1505 if ( $conf ->{ sockets
}) {
1506 delete $conf ->{ smp
};
1507 } elsif ( $conf ->{ smp
}) {
1508 $conf ->{ sockets
} = $conf ->{ smp
};
1509 delete $conf ->{ cores
};
1510 delete $conf ->{ smp
};
1513 my $new_volids = {};
1514 foreach my $key ( keys %$conf ) {
1515 next if $key eq 'digest' || $key eq 'description' ;
1516 my $value = $conf ->{ $key };
1517 eval { $value = check_type
( $key, $value ); };
1518 die "unable to parse value of ' $key ' - $@ " if $@ ;
1520 $conf ->{ $key } = $value ;
1522 if ( valid_drivename
( $key )) {
1523 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1524 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1528 # remove 'unusedX' settings if we re-add a volume
1529 foreach my $key ( keys %$conf ) {
1530 my $value = $conf ->{ $key };
1531 if ( $key =~ m/^unused/ && $new_volids ->{ $value }) {
1532 delete $conf ->{ $key };
1539 # add description as comment to top of file
1540 my $descr = $conf ->{ description
} || '' ;
1541 foreach my $cl ( split ( /\n/ , $descr )) {
1542 $raw .= '#' . PVE
:: Tools
:: encode_text
( $cl ) . " \n " ;
1545 foreach my $key ( sort keys %$conf ) {
1546 next if $key eq 'digest' || $key eq 'description' ;
1547 $raw .= " $key : $conf ->{ $key } \n " ;
1553 sub update_config_nolock
{
1554 my ( $vmid, $conf, $skiplock ) = @_ ;
1556 check_lock
( $conf ) if ! $skiplock ;
1558 my $cfspath = cfs_config_path
( $vmid );
1560 PVE
:: Cluster
:: cfs_write_file
( $cfspath, $conf );
1564 my ( $vmid, $conf, $skiplock ) = @_ ;
1566 lock_config
( $vmid, & update_config_nolock
, $conf, $skiplock );
1573 # we use static defaults from our JSON schema configuration
1574 foreach my $key ( keys %$confdesc ) {
1575 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1576 $res ->{ $key } = $default ;
1580 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1581 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1587 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1589 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1590 my $ids = $vmlist ->{ ids
};
1592 foreach my $vmid ( keys %$ids ) {
1593 my $d = $ids ->{ $vmid };
1594 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1595 next if ! $d ->{ type
} || $d ->{ type
} ne 'qemu' ;
1596 $res ->{ $vmid }->{ exists } = 1 ;
1601 # test if VM uses local resources (to prevent migration)
1602 sub check_local_resources
{
1603 my ( $conf, $noerr ) = @_ ;
1607 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1608 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1610 foreach my $k ( keys %$conf ) {
1611 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1614 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1622 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1626 my ( $pidfile, $pid ) = @_ ;
1628 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1632 return undef if ! $line ;
1633 my @param = split ( /\0/ , $line );
1635 my $cmd = $param [ 0 ];
1636 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1638 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1641 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1642 my $p = $param [ $i+1 ];
1643 return 1 if $p && ( $p eq $pidfile );
1652 my ( $vmid, $nocheck ) = @_ ;
1654 my $filename = config_file
( $vmid );
1656 die "unable to find configuration file for VM $vmid - no such machine \n "
1657 if ! $nocheck && ! - f
$filename ;
1659 my $pidfile = pidfile_name
( $vmid );
1661 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1666 my $mtime = $st -> mtime ;
1667 if ( $mtime > time ()) {
1668 warn "file ' $filename ' modified in future \n " ;
1671 if ( $line =~ m/^(\d+)$/ ) {
1673 if ( check_cmdline
( $pidfile, $pid )) {
1674 if ( my $pinfo = PVE
:: ProcFSTools
:: check_process_running
( $pid )) {
1686 my $vzlist = config_list
();
1688 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1690 while ( defined ( my $de = $fd -> read )) {
1691 next if $de !~ m/^(\d+)\.pid$/ ;
1693 next if ! defined ( $vzlist ->{ $vmid });
1694 if ( my $pid = check_running
( $vmid )) {
1695 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1702 my $storage_timeout_hash = {};
1705 my ( $storecfg, $conf ) = @_ ;
1707 my $bootdisk = $conf ->{ bootdisk
};
1708 return undef if ! $bootdisk ;
1709 return undef if ! valid_drivename
( $bootdisk );
1711 return undef if ! $conf ->{ $bootdisk };
1713 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1714 return undef if ! defined ( $drive );
1716 return undef if drive_is_cdrom
( $drive );
1718 my $volid = $drive ->{ file
};
1719 return undef if ! $volid ;
1725 if ( $volid =~ m
|^/|) {
1726 $path = $timeoutid = $volid ;
1729 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1730 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1738 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1739 if ( $last_timeout ) {
1740 if (( time () - $last_timeout ) < 30 ) {
1741 # skip storage with errors
1744 delete $storage_timeout_hash ->{ $timeoutid };
1747 my ( $size, $format, $used );
1749 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1751 if (! defined ( $format )) {
1753 $storage_timeout_hash ->{ $timeoutid } = time ();
1757 return wantarray ?
( $size, $used ) : $size ;
1760 my $last_proc_pid_stat ;
1763 my ( $opt_vmid ) = @_ ;
1767 my $storecfg = PVE
:: Storage
:: config
();
1769 my $list = vzlist
();
1770 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
( 1 );
1772 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1774 foreach my $vmid ( keys %$list ) {
1775 next if $opt_vmid && ( $vmid ne $opt_vmid );
1777 my $cfspath = cfs_config_path
( $vmid );
1778 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1781 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1783 # fixme: better status?
1784 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1786 my ( $size, $used ) = disksize
( $storecfg, $conf );
1787 if ( defined ( $size ) && defined ( $used )) {
1789 $d ->{ maxdisk
} = $size ;
1795 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1796 $d ->{ cpus
} = $cpucount if $d ->{ cpus
} > $cpucount ;
1798 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1799 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1809 $d ->{ diskwrite
} = 0 ;
1814 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1815 foreach my $dev ( keys %$netdev ) {
1816 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1818 my $d = $res ->{ $vmid };
1821 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1822 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1825 my $ctime = gettimeofday
;
1827 foreach my $vmid ( keys %$list ) {
1829 my $d = $res ->{ $vmid };
1830 my $pid = $d ->{ pid
};
1833 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1835 while ( defined ( my $line = < $fh >)) {
1836 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1841 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1842 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1845 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1846 next if ! $pstat ; # not running
1848 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
1850 $d ->{ uptime
} = int (( $uptime - $pstat ->{ starttime
})/ $cpuinfo ->{ user_hz
});
1852 if ( $pstat ->{ vsize
}) {
1853 $d ->{ mem
} = int (( $pstat ->{ rss
}/ $pstat ->{ vsize
})* $d ->{ maxmem
});
1856 my $old = $last_proc_pid_stat ->{ $pid };
1858 $last_proc_pid_stat ->{ $pid } = {
1866 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1868 if ( $dtime > 1000 ) {
1869 my $dutime = $used - $old ->{ used
};
1871 $d ->{ cpu
} = (( $dutime/$dtime )* $cpucount ) / $d ->{ cpus
};
1872 $last_proc_pid_stat ->{ $pid } = {
1878 $d ->{ cpu
} = $old ->{ cpu
};
1886 my ( $conf, $func ) = @_ ;
1888 foreach my $ds ( keys %$conf ) {
1889 next if ! valid_drivename
( $ds );
1891 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1894 & $func ( $ds, $drive );
1898 sub config_to_command
{
1899 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1903 my $kvmver = kvm_user_version
();
1904 my $vernum = 0 ; # unknown
1905 if ( $kvmver =~ m/^(\d+)\.(\d+)$/ ) {
1906 $vernum = $1*1000000+$2*1000 ;
1907 } elsif ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1908 $vernum = $1*1000000+$2*1000+$3 ;
1911 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 15000 ;
1913 my $have_ovz = - f
'/proc/vz/vestat' ;
1915 push @$cmd, '/usr/bin/kvm' ;
1917 push @$cmd, '-id' , $vmid ;
1921 my $socket = monitor_socket
( $vmid );
1922 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1923 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1925 $socket = vnc_socket
( $vmid );
1926 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1928 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1930 push @$cmd, '-daemonize' ;
1932 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1935 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1936 next if ! $conf ->{ "usb $i " };
1939 # include usb device config
1940 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2 ;
1942 # enable absolute mouse coordinates (needed by vnc)
1943 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1946 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' ;
1948 push @$cmd, '-usbdevice' , 'tablet' ;
1953 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1954 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1956 $pciaddr = print_pci_addr
( "hostpci $i " );
1957 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
1961 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1962 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1964 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1965 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1966 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
1967 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
1972 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
1973 if ( my $path = $conf ->{ "serial $i " }) {
1974 die "no such serial device \n " if ! - c
$path ;
1975 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
1976 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
1981 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
1982 if ( my $path = $conf ->{ "parallel $i " }) {
1983 die "no such parallel device \n " if ! - c
$path ;
1984 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
1985 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
1989 my $vmname = $conf ->{ name
} || "vm $vmid " ;
1991 push @$cmd, '-name' , $vmname ;
1994 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
1995 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
1997 my $cores = $conf ->{ cores
} || 1 ;
1999 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2001 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2003 push @$cmd, '-nodefaults' ;
2005 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2007 my $bootindex_hash = {};
2009 foreach my $o ( split ( // , $bootorder )) {
2010 $bootindex_hash ->{ $o } = $i*100 ;
2014 push @$cmd, '-boot' , "menu=on" ;
2016 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2018 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2020 my $vga = $conf ->{ vga
};
2022 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2029 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2032 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2033 # ignore - no longer supported by newer kvm
2034 # push @$cmd, '-tdf' if $tdf;
2036 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2038 if ( my $ost = $conf ->{ ostype
}) {
2039 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2041 if ( $ost =~ m/^w/ ) { # windows
2042 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2044 # use rtc-td-hack when acpi is enabled
2045 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2046 push @$cmd, '-rtc-td-hack' ;
2057 push @$cmd, '-no-kvm' ;
2059 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2062 push @$cmd, '-localtime' if $conf ->{ localtime };
2064 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2066 push @$cmd, '-S' if $conf ->{ freeze
};
2068 # set keyboard layout
2069 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2070 push @$cmd, '-k' , $kb if $kb ;
2073 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2074 #push @$cmd, '-soundhw', 'es1370';
2075 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2076 $pciaddr = print_pci_addr
( "balloon0" );
2077 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2079 if ( $conf ->{ watchdog
}) {
2080 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2081 $pciaddr = print_pci_addr
( "watchdog" );
2082 my $watchdog = $wdopts ->{ model
} || 'i6300esb' ;
2083 push @$cmd, '-device' , " $watchdog$pciaddr " ;
2084 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2088 my $scsicontroller = {};
2089 my $ahcicontroller = {};
2091 foreach_drive
( $conf, sub {
2092 my ( $ds, $drive ) = @_ ;
2094 if ( PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 )) {
2095 push @$vollist, $drive ->{ file
};
2098 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2100 if ( drive_is_cdrom
( $drive )) {
2101 if ( $bootindex_hash ->{ d
}) {
2102 $drive ->{ bootindex
} = $bootindex_hash ->{ d
};
2103 $bootindex_hash ->{ d
} += 1 ;
2106 if ( $bootindex_hash ->{ c
}) {
2107 $drive ->{ bootindex
} = $bootindex_hash ->{ c
} if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2108 $bootindex_hash ->{ c
} += 1 ;
2112 if ( $drive ->{ interface
} eq 'scsi' ) {
2114 my $controller = int ( $drive ->{ index } / $maxdev );
2115 $pciaddr = print_pci_addr
( "lsi $controller " );
2116 push @$cmd, '-device' , "lsi,id=lsi $controller$pciaddr " if ! $scsicontroller ->{ $controller };
2117 $scsicontroller ->{ $controller }= 1 ;
2120 if ( $drive ->{ interface
} eq 'sata' ) {
2121 my $controller = int ( $drive ->{ index } / $MAX_SATA_DISKS );
2122 $pciaddr = print_pci_addr
( "ahci $controller " );
2123 push @$cmd, '-device' , "ahci,id=ahci $controller,multifunction =on $pciaddr " if ! $ahcicontroller ->{ $controller };
2124 $ahcicontroller ->{ $controller }= 1 ;
2127 push @$cmd, '-drive' , print_drive_full
( $storecfg, $vmid, $drive );
2128 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2131 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2133 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
2134 next if ! $conf ->{ "net $i " };
2135 my $d = parse_net
( $conf ->{ "net $i " });
2138 $use_virtio = 1 if $d ->{ model
} eq 'virtio' ;
2140 if ( $bootindex_hash ->{ n
}) {
2141 $d ->{ bootindex
} = $bootindex_hash ->{ n
};
2142 $bootindex_hash ->{ n
} += 1 ;
2145 my $netdevfull = print_netdev_full
( $vmid,$conf,$d, "net $i " );
2146 push @$cmd, '-netdev' , $netdevfull ;
2148 my $netdevicefull = print_netdevice_full
( $vmid,$conf,$d, "net $i " );
2149 push @$cmd, '-device' , $netdevicefull ;
2153 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2154 # when the VM uses virtio devices.
2155 if (! $use_virtio && $have_ovz ) {
2157 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2158 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2160 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2162 # fixme: cpulimit is currently ignored
2163 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2167 if ( $conf ->{ args
}) {
2168 my $aa = PVE
:: Tools
:: split_args
( $conf ->{ args
});
2172 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2177 return "${var_run_tmpdir}/ $vmid .vnc" ;
2180 sub monitor_socket
{
2182 return "${var_run_tmpdir}/ $vmid .mon" ;
2187 return "${var_run_tmpdir}/ $vmid .pid" ;
2190 sub next_migrate_port
{
2192 for ( my $p = 60000 ; $p < 60010 ; $p++ ) {
2194 my $sock = IO
:: Socket
:: INET-
> new ( Listen
=> 5 ,
2195 LocalAddr
=> 'localhost' ,
2206 die "unable to find free migration port" ;
2209 sub vm_devices_list
{
2212 my $res = vm_monitor_command
( $vmid, "info pci" );
2214 my @lines = split ( " \n " , $res );
2220 foreach my $line ( @lines ) {
2222 if ( $line =~ m/^Bus (\d+), device (\d+), function (\d+):$/ ) {
2226 if ( $line =~ m/^id "([a-z][a-z_\-]*\d*)"$/ ) {
2228 $devices ->{ $id }->{ bus
}= $bus ;
2229 $devices ->{ $id }->{ addr
}= $addr ;
2237 my ( $storecfg, $conf, $vmid, $deviceid, $device ) = @_ ;
2239 return 1 if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2241 my $devices_list = vm_devices_list
( $vmid );
2242 return 1 if defined ( $devices_list ->{ $deviceid });
2244 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2245 return undef if ! qemu_driveadd
( $storecfg, $vmid, $device );
2246 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2247 qemu_deviceadd
( $vmid, $devicefull );
2248 if (! qemu_deviceaddverify
( $vmid, $deviceid )) {
2249 qemu_drivedel
( $vmid, $deviceid );
2254 if ( $deviceid =~ m/^(lsi)(\d+)$/ ) {
2255 my $pciaddr = print_pci_addr
( $deviceid );
2256 my $devicefull = "lsi,id= $deviceid$pciaddr " ;
2257 qemu_deviceadd
( $vmid, $devicefull );
2258 return undef if (! qemu_deviceaddverify
( $vmid, $deviceid ));
2261 if ( $deviceid =~ m/^(scsi)(\d+)$/ ) {
2262 return undef if ! qemu_findorcreatelsi
( $storecfg,$conf, $vmid, $device );
2263 return undef if ! qemu_driveadd
( $storecfg, $vmid, $device );
2264 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2265 if (! qemu_deviceadd
( $vmid, $devicefull )) {
2266 qemu_drivedel
( $vmid, $deviceid );
2271 if ( $deviceid =~ m/^(net)(\d+)$/ ) {
2272 return undef if ! qemu_netdevadd
( $vmid, $conf, $device, $deviceid );
2273 my $netdevicefull = print_netdevice_full
( $vmid, $conf, $device, $deviceid );
2274 qemu_deviceadd
( $vmid, $netdevicefull );
2275 if (! qemu_deviceaddverify
( $vmid, $deviceid )) {
2276 qemu_netdevdel
( $vmid, $deviceid );
2284 sub vm_deviceunplug
{
2285 my ( $vmid, $conf, $deviceid ) = @_ ;
2287 return 1 if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2289 my $devices_list = vm_devices_list
( $vmid );
2290 return 1 if ! defined ( $devices_list ->{ $deviceid });
2292 die "can't unplug bootdisk" if $conf ->{ bootdisk
} && $conf ->{ bootdisk
} eq $deviceid ;
2294 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2295 return undef if ! qemu_drivedel
( $vmid, $deviceid );
2296 qemu_devicedel
( $vmid, $deviceid );
2297 return undef if ! qemu_devicedelverify
( $vmid, $deviceid );
2300 if ( $deviceid =~ m/^(lsi)(\d+)$/ ) {
2301 return undef if ! qemu_devicedel
( $vmid, $deviceid );
2304 if ( $deviceid =~ m/^(scsi)(\d+)$/ ) {
2305 return undef if ! qemu_devicedel
( $vmid, $deviceid );
2306 return undef if ! qemu_drivedel
( $vmid, $deviceid );
2309 if ( $deviceid =~ m/^(net)(\d+)$/ ) {
2310 return undef if ! qemu_netdevdel
( $vmid, $deviceid );
2311 qemu_devicedel
( $vmid, $deviceid );
2312 return undef if ! qemu_devicedelverify
( $vmid, $deviceid );
2318 sub qemu_deviceadd
{
2319 my ( $vmid, $devicefull ) = @_ ;
2321 my $ret = vm_monitor_command
( $vmid, "device_add $devicefull " );
2323 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2324 return 1 if $ret eq "" ;
2325 syslog
( "err" , "error on hotplug device : $ret " );
2330 sub qemu_devicedel
{
2331 my ( $vmid, $deviceid ) = @_ ;
2333 my $ret = vm_monitor_command
( $vmid, "device_del $deviceid " );
2335 return 1 if $ret eq "" ;
2336 syslog
( "err" , "detaching device $deviceid failed : $ret " );
2341 my ( $storecfg, $vmid, $device ) = @_ ;
2343 my $drive = print_drive_full
( $storecfg, $vmid, $device );
2344 my $ret = vm_monitor_command
( $vmid, "drive_add auto $drive " );
2345 # If the command succeeds qemu prints: "OK"
2346 if ( $ret !~ m/OK/s ) {
2347 syslog
( "err" , "adding drive failed: $ret " );
2354 my ( $vmid, $deviceid ) = @_ ;
2356 my $ret = vm_monitor_command
( $vmid, "drive_del drive- $deviceid " );
2358 if ( $ret =~ m/Device \'.*?\' not found/s ) {
2359 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2361 elsif ( $ret ne "" ) {
2362 syslog
( "err" , "deleting drive $deviceid failed : $ret " );
2368 sub qemu_deviceaddverify
{
2369 my ( $vmid,$deviceid ) = @_ ;
2371 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2372 my $devices_list = vm_devices_list
( $vmid );
2373 return 1 if defined ( $devices_list ->{ $deviceid });
2376 syslog
( "err" , "error on hotplug device $deviceid " );
2381 sub qemu_devicedelverify
{
2382 my ( $vmid,$deviceid ) = @_ ;
2384 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2385 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2386 my $devices_list = vm_devices_list
( $vmid );
2387 return 1 if ! defined ( $devices_list ->{ $deviceid });
2390 syslog
( "err" , "error on hot-unplugging device $deviceid " );
2394 sub qemu_findorcreatelsi
{
2395 my ( $storecfg, $conf, $vmid, $device ) = @_ ;
2398 my $controller = int ( $device ->{ index } / $maxdev );
2399 my $lsiid = "lsi $controller " ;
2400 my $devices_list = vm_devices_list
( $vmid );
2402 if (! defined ( $devices_list ->{ $lsiid })) {
2403 return undef if ! vm_deviceplug
( $storecfg, $conf, $vmid, $lsiid );
2408 sub qemu_netdevadd
{
2409 my ( $vmid, $conf, $device, $deviceid ) = @_ ;
2411 my $netdev = print_netdev_full
( $vmid, $conf, $device, $deviceid );
2412 my $ret = vm_monitor_command
( $vmid, "netdev_add $netdev " );
2415 #if the command succeeds, no output is sent. So any non-empty string shows an error
2416 return 1 if $ret eq "" ;
2417 syslog
( "err" , "adding netdev failed: $ret " );
2421 sub qemu_netdevdel
{
2422 my ( $vmid, $deviceid ) = @_ ;
2424 my $ret = vm_monitor_command
( $vmid, "netdev_del $deviceid " );
2426 #if the command succeeds, no output is sent. So any non-empty string shows an error
2427 return 1 if $ret eq "" ;
2428 syslog
( "err" , "deleting netdev failed: $ret " );
2433 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2435 lock_config
( $vmid, sub {
2436 my $conf = load_config
( $vmid );
2438 check_lock
( $conf ) if ! $skiplock ;
2440 die "VM $vmid already running \n " if check_running
( $vmid );
2443 my $migrate_port = 0 ;
2446 if ( $statefile eq 'tcp' ) {
2447 $migrate_port = next_migrate_port
();
2448 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2450 if (- f
$statefile ) {
2451 $migrate_uri = "exec:cat $statefile " ;
2453 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2458 my $defaults = load_defaults
();
2460 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2462 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2463 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2465 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2466 die "IOMMU not present \n " if ! check_iommu_support
();
2467 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2468 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2469 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2472 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2474 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2476 die "start failed: $err " if $err ;
2480 if ( $statefile eq 'tcp' ) {
2481 print "migration listens on port $migrate_port\n " ;
2484 # fixme: send resume - is that necessary ?
2485 eval { vm_monitor_command
( $vmid, "cont" ); };
2489 # always set migrate speed (overwrite kvm default of 32m)
2490 # we set a very hight default of 8192m which is basically unlimited
2491 my $migrate_speed = $defaults ->{ migrate_speed
} || 8192 ;
2492 $migrate_speed = $conf ->{ migrate_speed
} || $migrate_speed ;
2494 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2495 vm_monitor_command
( $vmid, $cmd );
2498 if ( my $migrate_downtime =
2499 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2500 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2501 eval { vm_monitor_command
( $vmid, $cmd ); };
2504 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2510 my ( $fh, $timeout ) = @_ ;
2512 my $sel = new IO
:: Select
;
2519 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2521 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2522 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2529 if (! defined ( $count )) {
2536 die "monitor read timeout \n " if ! scalar ( @ready );
2541 sub vm_monitor_command
{
2542 my ( $vmid, $cmdstr, $nocheck ) = @_ ;
2547 die "VM $vmid not running \n " if ! check_running
( $vmid, $nocheck );
2549 my $sname = monitor_socket
( $vmid );
2551 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2552 die "unable to connect to VM $vmid socket - $!\n " ;
2556 # hack: migrate sometime blocks the monitor (when migrate_downtime
2558 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2559 $timeout = 60 * 60 ; # 1 hour
2563 my $data = __read_avail
( $sock, $timeout );
2565 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2566 die "got unexpected qemu monitor banner \n " ;
2569 my $sel = new IO
:: Select
;
2572 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2573 die "monitor write error - timeout" ;
2576 my $fullcmd = " $cmdstr\r " ;
2578 # syslog('info', "VM $vmid monitor command: $cmdstr");
2581 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2582 die "monitor write error - $! " ;
2585 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2589 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2590 $timeout = 60 * 60 ; # 1 hour
2591 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2592 $timeout = 60 ; # note: cdrom mount command is slow
2594 if ( $res = __read_avail
( $sock, $timeout )) {
2596 my @lines = split ( " \r ? \n " , $res );
2598 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2600 $res = join ( " \n " , @lines );
2608 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2615 sub vm_commandline
{
2616 my ( $storecfg, $vmid ) = @_ ;
2618 my $conf = load_config
( $vmid );
2620 my $defaults = load_defaults
();
2622 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2624 return join ( ' ' , @$cmd );
2628 my ( $vmid, $skiplock ) = @_ ;
2630 lock_config
( $vmid, sub {
2632 my $conf = load_config
( $vmid );
2634 check_lock
( $conf ) if ! $skiplock ;
2636 vm_monitor_command
( $vmid, "system_reset" );
2640 sub get_vm_volumes
{
2644 foreach_drive
( $conf, sub {
2645 my ( $ds, $drive ) = @_ ;
2647 my ( $sid, $volname ) = PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 );
2650 my $volid = $drive ->{ file
};
2651 return if ! $volid || $volid =~ m
|^/|;
2653 push @$vollist, $volid ;
2659 sub vm_stop_cleanup
{
2660 my ( $storecfg, $vmid, $conf, $keepActive ) = @_ ;
2663 fairsched_rmnod
( $vmid ); # try to destroy group
2666 my $vollist = get_vm_volumes
( $conf );
2667 PVE
:: Storage
:: deactivate_volumes
( $storecfg, $vollist );
2670 warn $@ if $@ ; # avoid errors - just warn
2673 # Note: use $nockeck to skip tests if VM configuration file exists.
2674 # We need that when migration VMs to other nodes (files already moved)
2675 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
2677 my ( $storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive ) = @_ ;
2679 $timeout = 60 if ! defined ( $timeout );
2681 $force = 1 if ! defined ( $force ) && ! $shutdown ;
2683 lock_config
( $vmid, sub {
2685 my $pid = check_running
( $vmid, $nocheck );
2690 $conf = load_config
( $vmid );
2691 check_lock
( $conf ) if ! $skiplock ;
2696 vm_monitor_command
( $vmid, "system_powerdown" , $nocheck );
2698 vm_monitor_command
( $vmid, "quit" , $nocheck );
2705 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2710 if ( $count >= $timeout ) {
2712 warn "VM still running - terminating now with SIGTERM \n " ;
2715 die "VM quit/powerdown failed - got timeout \n " ;
2718 vm_stop_cleanup
( $storecfg, $vmid, $conf, $keepActive ) if $conf ;
2723 warn "VM quit/powerdown failed - terminating now with SIGTERM \n " ;
2726 die "VM quit/powerdown failed \n " ;
2734 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2739 if ( $count >= $timeout ) {
2740 warn "VM still running - terminating now with SIGKILL \n " ;
2745 vm_stop_cleanup
( $storecfg, $vmid, $conf, $keepActive ) if $conf ;
2750 my ( $vmid, $skiplock ) = @_ ;
2752 lock_config
( $vmid, sub {
2754 my $conf = load_config
( $vmid );
2756 check_lock
( $conf ) if ! $skiplock ;
2758 vm_monitor_command
( $vmid, "stop" );
2763 my ( $vmid, $skiplock ) = @_ ;
2765 lock_config
( $vmid, sub {
2767 my $conf = load_config
( $vmid );
2769 check_lock
( $conf ) if ! $skiplock ;
2771 vm_monitor_command
( $vmid, "cont" );
2776 my ( $vmid, $skiplock, $key ) = @_ ;
2778 lock_config
( $vmid, sub {
2780 my $conf = load_config
( $vmid );
2782 vm_monitor_command
( $vmid, "sendkey $key " );
2787 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2789 lock_config
( $vmid, sub {
2791 my $conf = load_config
( $vmid );
2793 check_lock
( $conf ) if ! $skiplock ;
2795 if (! check_running
( $vmid )) {
2796 fairsched_rmnod
( $vmid ); # try to destroy group
2797 destroy_vm
( $storecfg, $vmid );
2799 die "VM $vmid is running - destroy failed \n " ;
2805 my ( $storecfg, $timeout ) = @_ ;
2807 $timeout = 3 * 60 if ! $timeout ;
2809 my $cleanuphash = {};
2811 my $vzlist = vzlist
();
2813 foreach my $vmid ( keys %$vzlist ) {
2814 next if ! $vzlist ->{ $vmid }->{ pid
};
2816 $cleanuphash ->{ $vmid } = 1 ;
2821 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2822 syslog
( 'info' , $msg );
2825 foreach my $vmid ( keys %$vzlist ) {
2826 next if ! $vzlist ->{ $vmid }->{ pid
};
2827 eval { vm_monitor_command
( $vmid, "system_powerdown" ); };
2832 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2834 while (( $try < $maxtries ) && $count ) {
2840 foreach my $vmid ( keys %$vzlist ) {
2841 next if ! $vzlist ->{ $vmid }->{ pid
};
2849 foreach my $vmid ( keys %$vzlist ) {
2850 next if ! $vzlist ->{ $vmid }->{ pid
};
2852 warn "VM $vmid still running - sending stop now \n " ;
2853 eval { vm_monitor_command
( $vmid, "quit" ); };
2858 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2860 while (( $try < $maxtries ) && $count ) {
2866 foreach my $vmid ( keys %$vzlist ) {
2867 next if ! $vzlist ->{ $vmid }->{ pid
};
2875 foreach my $vmid ( keys %$vzlist ) {
2876 next if ! $vzlist ->{ $vmid }->{ pid
};
2878 warn "VM $vmid still running - terminating now with SIGTERM \n " ;
2879 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2884 # this is called by system shotdown scripts, so remaining
2885 # processes gets killed anyways (no need to send kill -9 here)
2889 foreach my $vmid ( keys %$cleanuphash ) {
2890 next if $vzlist ->{ $vmid }->{ pid
};
2892 my $conf = load_config
( $vmid );
2893 vm_stop_cleanup
( $storecfg, $vmid, $conf );
2898 $msg = "Qemu Server stopped \n " ;
2899 syslog
( 'info' , $msg );
2906 my ( $filename, $buf ) = @_ ;
2908 my $fh = IO
:: File-
> new ( $filename, "w" );
2909 return undef if ! $fh ;
2911 my $res = print $fh $buf ;
2918 sub pci_device_info
{
2923 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2924 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2926 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2927 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2929 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2930 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2932 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2933 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2938 product
=> $product,
2944 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2953 my $name = $dev ->{ name
};
2955 my $fn = " $pcisysfs/devices/$name/reset " ;
2957 return file_write
( $fn, "1" );
2960 sub pci_dev_bind_to_stub
{
2963 my $name = $dev ->{ name
};
2965 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2966 return 1 if - d
$testdir ;
2968 my $data = " $dev ->{vendor} $dev ->{product}" ;
2969 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2971 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2972 if (! file_write
( $fn, $name )) {
2973 return undef if - f
$fn ;
2976 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2977 if (! - d
$testdir ) {
2978 return undef if ! file_write
( $fn, $name );
2984 sub print_pci_addr
{
2989 #addr1 : ide,parallel,serial (motherboard)
2990 #addr2 : first videocard
2991 balloon0
=> { bus
=> 0 , addr
=> 3 },
2992 watchdog
=> { bus
=> 0 , addr
=> 4 },
2993 lsi0
=> { bus
=> 0 , addr
=> 5 },
2994 lsi1
=> { bus
=> 0 , addr
=> 6 },
2995 ahci0
=> { bus
=> 0 , addr
=> 7 },
2996 virtio0
=> { bus
=> 0 , addr
=> 10 },
2997 virtio1
=> { bus
=> 0 , addr
=> 11 },
2998 virtio2
=> { bus
=> 0 , addr
=> 12 },
2999 virtio3
=> { bus
=> 0 , addr
=> 13 },
3000 virtio4
=> { bus
=> 0 , addr
=> 14 },
3001 virtio5
=> { bus
=> 0 , addr
=> 15 },
3002 hostpci0
=> { bus
=> 0 , addr
=> 16 },
3003 hostpci1
=> { bus
=> 0 , addr
=> 17 },
3004 net0
=> { bus
=> 0 , addr
=> 18 },
3005 net1
=> { bus
=> 0 , addr
=> 19 },
3006 net2
=> { bus
=> 0 , addr
=> 20 },
3007 net3
=> { bus
=> 0 , addr
=> 21 },
3008 net4
=> { bus
=> 0 , addr
=> 22 },
3009 net5
=> { bus
=> 0 , addr
=> 23 },
3010 #addr29 : usb-host (pve-usb.cfg)
3013 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
3014 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
3015 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
3022 my ( $vmid, $value ) = @_ ;
3024 vm_monitor_command
( $vmid, "balloon $value " );
3027 # vzdump restore implementaion
3029 sub archive_read_firstfile
{
3030 my $archive = shift ;
3032 die "ERROR: file ' $archive ' does not exist \n " if ! - f
$archive ;
3034 # try to detect archive type first
3035 my $pid = open ( TMP
, "tar tf ' $archive '|" ) ||
3036 die "unable to open file ' $archive ' \n " ;
3037 my $firstfile = < TMP
>;
3041 die "ERROR: archive contaions no data \n " if ! $firstfile ;
3047 sub restore_cleanup
{
3048 my $statfile = shift ;
3050 print STDERR
"starting cleanup \n " ;
3052 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3053 while ( defined ( my $line = < $fd >)) {
3054 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3057 if ( $volid =~ m
|^/|) {
3058 unlink $volid || die 'unlink failed \n ' ;
3060 my $cfg = cfs_read_file
( 'storage.cfg' );
3061 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
3063 print STDERR
"temporary volume ' $volid ' sucessfuly removed \n " ;
3065 print STDERR
"unable to cleanup ' $volid ' - $@ " if $@ ;
3067 print STDERR
"unable to parse line in statfile - $line " ;
3074 sub restore_archive
{
3075 my ( $archive, $vmid, $user, $opts ) = @_ ;
3077 if ( $archive ne '-' ) {
3078 my $firstfile = archive_read_firstfile
( $archive );
3079 die "ERROR: file ' $archive ' dos not lock like a QemuServer vzdump backup \n "
3080 if $firstfile ne 'qemu-server.conf' ;
3083 my $tocmd = "/usr/lib/qemu-server/qmextract" ;
3085 $tocmd .= " --storage " . PVE
:: Tools
:: shellquote
( $opts ->{ storage
}) if $opts ->{ storage
};
3086 $tocmd .= " --pool " . PVE
:: Tools
:: shellquote
( $opts ->{ pool
}) if $opts ->{ pool
};
3087 $tocmd .= ' --prealloc' if $opts ->{ prealloc
};
3088 $tocmd .= ' --info' if $opts ->{ info
};
3090 # tar option "xf" does not autodetect compression when read from STDIN,
3091 # so we pipe to zcat
3092 my $cmd = "zcat -f|tar xf " . PVE
:: Tools
:: shellquote
( $archive ) . " " .
3093 PVE
:: Tools
:: shellquote
( "--to-command= $tocmd " );
3095 my $tmpdir = "/var/tmp/vzdumptmp $$ " ;
3098 local $ENV { VZDUMP_TMPDIR
} = $tmpdir ;
3099 local $ENV { VZDUMP_VMID
} = $vmid ;
3100 local $ENV { VZDUMP_USER
} = $user ;
3102 my $conffile = PVE
:: QemuServer
:: config_file
( $vmid );
3103 my $tmpfn = " $conffile . $$ .tmp" ;
3105 # disable interrupts (always do cleanups)
3106 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = sub {
3107 print STDERR
"got interrupt - ignored \n " ;
3112 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = $SIG { PIPE
} = sub {
3113 die "interrupted by signal \n " ;
3116 if ( $archive eq '-' ) {
3117 print "extracting archive from STDIN \n " ;
3118 run_command
( $cmd, input
=> "<&STDIN" );
3120 print "extracting archive ' $archive ' \n " ;
3124 return if $opts ->{ info
};
3128 my $statfile = " $tmpdir/qmrestore .stat" ;
3129 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3130 while ( defined ( my $line = < $fd >)) {
3131 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3132 $map ->{ $1 } = $2 if $1 ;
3134 print STDERR
"unable to parse line in statfile - $line\n " ;
3140 my $confsrc = " $tmpdir/qemu -server.conf" ;
3142 my $srcfd = new IO
:: File
( $confsrc, "r" ) ||
3143 die "unable to open file ' $confsrc ' \n " ;
3145 my $outfd = new IO
:: File
( $tmpfn, "w" ) ||
3146 die "unable to write config for VM $vmid\n " ;
3150 while ( defined ( my $line = < $srcfd >)) {
3151 next if $line =~ m/^\#vzdump\#/ ;
3152 next if $line =~ m/^lock:/ ;
3153 next if $line =~ m/^unused\d+:/ ;
3155 if (( $line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/ )) {
3156 # try to convert old 1.X settings
3157 my ( $id, $ind, $ethcfg ) = ( $1, $2, $3 );
3158 foreach my $devconfig ( PVE
:: Tools
:: split_list
( $ethcfg )) {
3159 my ( $model, $macaddr ) = split ( /\=/ , $devconfig );
3160 $macaddr = PVE
:: Tools
:: random_ether_addr
() if ! $macaddr || $opts ->{ unique
};
3163 bridge
=> "vmbr $ind " ,
3164 macaddr
=> $macaddr,
3166 my $netstr = print_net
( $net );
3167 print $outfd "net${netcount}: $netstr\n " ;
3170 } elsif (( $line =~ m/^(net\d+):\s*(\S+)\s*$/ ) && ( $opts ->{ unique
})) {
3171 my ( $id, $netstr ) = ( $1, $2 );
3172 my $net = parse_net
( $netstr );
3173 $net ->{ macaddr
} = PVE
:: Tools
:: random_ether_addr
() if $net ->{ macaddr
};
3174 $netstr = print_net
( $net );
3175 print $outfd " $id : $netstr\n " ;
3176 } elsif ( $line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/ ) {
3179 if ( $line =~ m/backup=no/ ) {
3180 print $outfd "# $line " ;
3181 } elsif ( $virtdev && $map ->{ $virtdev }) {
3182 my $di = PVE
:: QemuServer
:: parse_drive
( $virtdev, $value );
3183 $di ->{ file
} = $map ->{ $virtdev };
3184 $value = PVE
:: QemuServer
:: print_drive
( $vmid, $di );
3185 print $outfd " $virtdev : $value\n " ;
3203 restore_cleanup
( " $tmpdir/qmrestore .stat" ) if ! $opts ->{ info
};
3210 rename $tmpfn, $conffile ||
3211 die "unable to commit configuration file ' $conffile ' \n " ;