]>
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/' , \
& parse_vm_config
);
40 PVE
:: JSONSchema
:: register_standard_option
( 'skiplock' , {
41 description
=> "Ignore locks - only root is allowed to use this option." ,
46 PVE
:: JSONSchema
:: register_standard_option
( 'pve-qm-stateuri' , {
47 description
=> "Some command save/restore state from this location." ,
53 #no warnings 'redefine';
55 unless ( 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
);
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
);
78 die ( "no fairsched syscall for this arch" );
80 require 'asm/ioctl.ph' ;
81 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined (& KVM_GET_API_VERSION
);
85 my ( $parent, $weight, $desired ) = @_ ;
87 return syscall (& __NR_fairsched_mknod
, int ( $parent ), int ( $weight ), int ( $desired ));
93 return syscall (& __NR_fairsched_rmnod
, int ( $id ));
97 my ( $pid, $newid ) = @_ ;
99 return syscall (& __NR_fairsched_mvpr
, int ( $pid ), int ( $newid ));
102 sub fairsched_vcpus
{
103 my ( $id, $vcpus ) = @_ ;
105 return syscall (& __NR_fairsched_vcpus
, int ( $id ), int ( $vcpus ));
109 my ( $id, $op, $rate ) = @_ ;
111 return syscall (& __NR_fairsched_rate
, int ( $id ), int ( $op ), int ( $rate ));
114 use constant FAIRSCHED_SET_RATE
=> 0 ;
115 use constant FAIRSCHED_DROP_RATE
=> 1 ;
116 use constant FAIRSCHED_GET_RATE
=> 2 ;
118 sub fairsched_cpulimit
{
119 my ( $id, $limit ) = @_ ;
121 my $cpulim1024 = int ( $limit * 1024 / 100 );
122 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
124 return fairsched_rate
( $id, $op, $cpulim1024 );
127 my $nodename = PVE
:: INotify
:: nodename
();
129 mkdir "/etc/pve/nodes/ $nodename " ;
130 my $confdir = "/etc/pve/nodes/ $nodename/qemu -server" ;
133 my $var_run_tmpdir = "/var/run/qemu-server" ;
134 mkdir $var_run_tmpdir ;
136 my $lock_dir = "/var/lock/qemu-server" ;
139 my $pcisysfs = "/sys/bus/pci" ;
145 description
=> "Specifies whether a VM will be started during system bootup." ,
151 description
=> "Automatic restart after crash (currently ignored)." ,
157 description
=> "Activate hotplug for disk and network device" ,
163 description
=> "Allow reboot. If set to '0' the VM exit on reboot." ,
169 description
=> "Lock/unlock the VM." ,
170 enum
=> [ qw(migrate backup) ],
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\n NOTE: This option is currently ignored." ,
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\n NOTE: You can disable fair-scheduler configuration by setting this to 0." ,
190 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device." ,
197 description
=> "Amount of target RAM for the VM in MB." ,
203 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file." ,
204 enum
=> PVE
:: Tools
:: kvmkeymaplist
(),
210 description
=> "Set a name for the VM. Only used on the configuration web interface." ,
215 description
=> "Description for the VM. Only used on the configuration web interface." ,
220 enum
=> [ qw(other wxp w2k w2k3 w2k8 wvista win7 l24 l26) ],
221 description
=> <<EODESC,
222 Used to enable special optimization/features for specific
225 other => unspecified OS
226 wxp => Microsoft Windows XP
227 w2k => Microsoft Windows 2000
228 w2k3 => Microsoft Windows 2003
229 w2k8 => Microsoft Windows 2008
230 wvista => Microsoft Windows Vista
231 win7 => Microsoft Windows 7
232 l24 => Linux 2.4 Kernel
233 l26 => Linux 2.6/3.X Kernel
235 other|l24|l26 ... no special behaviour
236 wxp|w2k|w2k3|w2k8|wvista|win7 ... use --localtime switch
242 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." ,
243 pattern
=> '[acdn]{1,4}' ,
248 type
=> 'string' , format
=> 'pve-qm-bootdisk' ,
249 description
=> "Enable booting from specified disk." ,
250 pattern
=> '(ide|scsi|virtio)\d+' ,
255 description
=> "The number of CPUs. Please use option -sockets instead." ,
262 description
=> "The number of CPU sockets." ,
269 description
=> "The number of cores per socket." ,
276 description
=> "Enable/disable ACPI." ,
282 description
=> "Enable/disable KVM hardware virtualization." ,
288 description
=> "Enable/disable time drift fix." ,
294 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS." ,
299 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution)." ,
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) ],
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)" ,
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})?)' ,
324 description
=> <<EODESCR,
325 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
327 args: -no-reboot -no-hpet
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." ,
339 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit." ,
343 migrate_downtime
=> {
346 description
=> "Set maximum tolerated downtime (in seconds) for migrations." ,
352 type
=> 'string' , format
=> 'pve-qm-drive' ,
353 typetext
=> 'volume' ,
354 description
=> "This is an alias for option -ide2" ,
358 description
=> "Emulated CPU type." ,
360 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom host) ],
365 # what about other qemu settings ?
367 #machine => 'string',
380 ##soundhw => 'string',
382 while ( my ( $k, $v ) = each %$confdesc ) {
383 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm- $k " , $v );
386 my $MAX_IDE_DISKS = 4 ;
387 my $MAX_SCSI_DISKS = 14 ;
388 my $MAX_VIRTIO_DISKS = 6 ;
389 my $MAX_SATA_DISKS = 6 ;
390 my $MAX_USB_DEVICES = 5 ;
392 my $MAX_UNUSED_DISKS = 8 ;
393 my $MAX_HOSTPCI_DEVICES = 2 ;
394 my $MAX_SERIAL_PORTS = 4 ;
395 my $MAX_PARALLEL_PORTS = 3 ;
397 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
398 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
399 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
404 type
=> 'string' , format
=> 'pve-qm-net' ,
405 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
406 description
=> <<EODESCR,
407 Specify network devices.
409 MODEL is one of: $nic_model_list_txt
411 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
412 automatically generated if not specified.
414 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
416 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'.
418 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
424 The DHCP server assign addresses to the guest starting from 10.0.2.15.
428 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
430 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
431 $confdesc ->{ "net $i " } = $netdesc ;
438 type
=> 'string' , format
=> 'pve-qm-drive' ,
439 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
440 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
442 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
446 type
=> 'string' , format
=> 'pve-qm-drive' ,
447 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
448 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
450 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
454 type
=> 'string' , format
=> 'pve-qm-drive' ,
455 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
456 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to 5)." ,
458 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-sata" , $satadesc );
462 type
=> 'string' , format
=> 'pve-qm-drive' ,
463 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
464 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
466 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
470 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
471 typetext
=> 'host=HOSTUSBDEVICE' ,
472 description
=> <<EODESCR,
473 Configure an USB device (n is 0 to 4). This can be used to
474 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
476 'bus-port(.port)*' (decimal numbers) or
477 'vendor_id:product_id' (hexadeciaml numbers)
479 You can use the 'lsusb -t' command to list existing usb devices.
481 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
485 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
489 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
490 typetext
=> "HOSTPCIDEVICE" ,
491 description
=> <<EODESCR,
492 Map host pci devices. HOSTPCIDEVICE syntax is:
494 'bus:dev.func' (hexadecimal numbers)
496 You can us the 'lspci' command to list existing pci devices.
498 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
500 Experimental: user reported problems with this option.
503 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
508 pattern
=> '/dev/ttyS\d+' ,
509 description
=> <<EODESCR,
510 Map host serial devices (n is 0 to 3).
512 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
514 Experimental: user reported problems with this option.
521 pattern
=> '/dev/parport\d+' ,
522 description
=> <<EODESCR,
523 Map host parallel devices (n is 0 to 2).
525 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
527 Experimental: user reported problems with this option.
531 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
532 $confdesc ->{ "parallel $i " } = $paralleldesc ;
535 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
536 $confdesc ->{ "serial $i " } = $serialdesc ;
539 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
540 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
543 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
544 $drivename_hash ->{ "ide $i " } = 1 ;
545 $confdesc ->{ "ide $i " } = $idedesc ;
548 for ( my $i = 0 ; $i < $MAX_SATA_DISKS ; $i++ ) {
549 $drivename_hash ->{ "sata $i " } = 1 ;
550 $confdesc ->{ "sata $i " } = $satadesc ;
553 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
554 $drivename_hash ->{ "scsi $i " } = 1 ;
555 $confdesc ->{ "scsi $i " } = $scsidesc ;
558 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
559 $drivename_hash ->{ "virtio $i " } = 1 ;
560 $confdesc ->{ "virtio $i " } = $virtiodesc ;
563 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
564 $confdesc ->{ "usb $i " } = $usbdesc ;
569 type
=> 'string' , format
=> 'pve-volume-id' ,
570 description
=> "Reference to unused volumes." ,
573 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
574 $confdesc ->{ "unused $i " } = $unuseddesc ;
577 my $kvm_api_version = 0 ;
581 return $kvm_api_version if $kvm_api_version ;
583 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
586 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
587 $kvm_api_version = $v ;
592 return $kvm_api_version ;
595 my $kvm_user_version ;
597 sub kvm_user_version
{
599 return $kvm_user_version if $kvm_user_version ;
601 $kvm_user_version = 'unknown' ;
603 my $tmp = `kvm -help 2>/dev/null` ;
605 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) / ) {
606 $kvm_user_version = $2 ;
609 return $kvm_user_version ;
613 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
616 # order is important - used to autoselect boot disk
617 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
618 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
619 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))),
620 ( map { "sata $_ " } ( 0 .. ( $MAX_SATA_DISKS - 1 ))));
623 sub valid_drivename
{
626 return defined ( $drivename_hash ->{ $dev });
631 return defined ( $confdesc ->{ $key });
635 return $nic_model_list ;
638 sub os_list_description
{
643 w2k
=> 'Windows 2000' ,
644 w2k3
=>, 'Windows 2003' ,
645 w2k8
=> 'Windows 2008' ,
646 wvista
=> 'Windows Vista' ,
653 sub disk_devive_info
{
656 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
664 } elsif ( $bus eq 'scsi' ) {
668 my $controller = int ( $index / $maxdev );
669 my $unit = $index % $maxdev ;
672 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
673 controller
=> $controller, unit
=> $unit, index => $index };
677 sub qemu_drive_name
{
678 my ( $dev, $media ) = @_ ;
680 my $info = disk_devive_info
( $dev );
683 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
684 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
685 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
686 $mediastr, $info ->{ unit
});
688 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
696 return $cdrom_path if $cdrom_path ;
698 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
699 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
700 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
704 my ( $storecfg, $vmid, $cdrom ) = @_ ;
706 if ( $cdrom eq 'cdrom' ) {
707 return get_cdrom_path
();
708 } elsif ( $cdrom eq 'none' ) {
710 } elsif ( $cdrom =~ m
|^/|) {
713 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
717 # try to convert old style file names to volume IDs
718 sub filename_to_volume_id
{
719 my ( $vmid, $file, $media ) = @_ ;
721 if (!( $file eq 'none' || $file eq 'cdrom' ||
722 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
724 return undef if $file =~ m
|/|;
726 if ( $media && $media eq 'cdrom' ) {
727 $file = "local:iso/ $file " ;
729 $file = "local: $vmid/$file " ;
736 sub verify_media_type
{
737 my ( $opt, $vtype, $media ) = @_ ;
742 if ( $media eq 'disk' ) {
744 } elsif ( $media eq 'cdrom' ) {
747 die "internal error" ;
750 return if ( $vtype eq $etype );
752 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
755 sub cleanup_drive_path
{
756 my ( $opt, $storecfg, $drive ) = @_ ;
758 # try to convert filesystem paths to volume IDs
760 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
761 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
762 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
763 ( $drive ->{ file
} !~ m/^\d+$/ )) {
764 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
765 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
766 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
767 verify_media_type
( $opt, $vtype, $drive ->{ media
});
768 $drive ->{ file
} = $volid ;
771 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
774 sub create_conf_nolock
{
775 my ( $vmid, $settings ) = @_ ;
777 my $filename = config_file
( $vmid );
779 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
781 my $defaults = load_defaults
();
783 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
784 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
787 foreach my $opt ( keys %$settings ) {
788 next if ! $confdesc ->{ $opt };
790 my $value = $settings ->{ $opt };
793 $data .= " $opt : $value\n " ;
796 PVE
:: Tools
:: file_set_contents
( $filename, $data );
799 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
800 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
801 # [,aio=native|threads]
804 my ( $key, $data ) = @_ ;
808 # $key may be undefined - used to verify JSON parameters
809 if (! defined ( $key )) {
810 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
812 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
813 $res ->{ interface
} = $1 ;
819 foreach my $p ( split ( /,/ , $data )) {
820 next if $p =~ m/^\s*$/ ;
822 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
823 my ( $k, $v ) = ( $1, $2 );
825 $k = 'file' if $k eq 'volume' ;
827 return undef if defined $res ->{ $k };
831 if (! $res ->{ file
} && $p !~ m/=/ ) {
839 return undef if ! $res ->{ file
};
841 return undef if $res ->{ cache
} &&
842 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback|unsafe)$/ ;
843 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
844 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
845 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
846 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
847 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
848 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
849 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
850 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
851 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
852 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
853 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
855 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
856 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
857 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
858 return undef if $res ->{ interface
} eq 'virtio' ;
861 # rerror does not work with scsi drives
862 if ( $res ->{ rerror
}) {
863 return undef if $res ->{ interface
} eq 'scsi' ;
869 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
872 my ( $vmid, $drive ) = @_ ;
875 foreach my $o ( @qemu_drive_options, 'backup' ) {
876 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
879 return " $drive ->{file} $opts " ;
882 sub print_drivedevice_full
{
883 my ( $storecfg, $vmid, $drive ) = @_ ;
888 if ( $drive ->{ interface
} eq 'virtio' ) {
889 my $pciaddr = print_pci_addr
( " $drive ->{interface} $drive ->{index}" );
890 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index} $pciaddr " ;
891 } elsif ( $drive ->{ interface
} eq 'scsi' ) {
893 my $controller = int ( $drive ->{ index } / $maxdev );
894 my $unit = $drive ->{ index } % $maxdev ;
895 my $devicetype = 'hd' ;
897 if ( drive_is_cdrom
( $drive )) {
900 if ( $drive ->{ file
} =~ m
|^/|) {
901 $path = $drive ->{ file
};
903 $path = PVE
:: Storage
:: path
( $storecfg, $drive ->{ file
});
905 if ( $path =~ m
|^ /dev/ | ) {
906 $devicetype = 'block' ;
910 $device = "scsi- $devicetype,bus =lsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
911 } elsif ( $drive ->{ interface
} eq 'ide' ){
913 my $controller = int ( $drive ->{ index } / $maxdev );
914 my $unit = $drive ->{ index } % $maxdev ;
915 my $devicetype = ( $drive ->{ media
} && $drive ->{ media
} eq 'cdrom' ) ?
"cd" : "hd" ;
917 $device = "ide- $devicetype,bus =ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
918 } elsif ( $drive ->{ interface
} eq 'sata' ){
919 my $controller = int ( $drive ->{ index } / $MAX_SATA_DISKS );
920 my $unit = $drive ->{ index } % $MAX_SATA_DISKS ;
921 $device = "ide-drive,bus=ahci $controller . $unit,drive =drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index}" ;
922 } elsif ( $drive ->{ interface
} eq 'usb' ) {
924 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
926 die "unsupported interface type" ;
929 $device .= ",bootindex= $drive ->{bootindex}" if $drive ->{ bootindex
};
934 sub print_drive_full
{
935 my ( $storecfg, $vmid, $drive ) = @_ ;
938 foreach my $o ( @qemu_drive_options ) {
939 next if $o eq 'bootindex' ;
940 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
943 # use linux-aio by default (qemu default is threads)
944 $opts .= ",aio=native" if ! $drive ->{ aio
};
947 my $volid = $drive ->{ file
};
948 if ( drive_is_cdrom
( $drive )) {
949 $path = get_iso_path
( $storecfg, $vmid, $volid );
951 if ( $volid =~ m
|^/|) {
954 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
956 if (! $drive ->{ cache
} && ( $path =~ m
|^ /dev/ | || $path =~ m
| \
. raw
$|)) {
957 $opts .= ",cache=none" ;
961 my $pathinfo = $path ?
"file= $path, " : '' ;
963 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
966 sub print_netdevice_full
{
967 my ( $vmid, $conf, $net, $netid ) = @_ ;
969 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
971 my $device = $net ->{ model
};
972 if ( $net ->{ model
} eq 'virtio' ) {
973 $device = 'virtio-net-pci' ;
976 # qemu > 0.15 always try to boot from network - we disable that by
977 # not loading the pxe rom file
978 my $extra = ( $bootorder !~ m/n/ ) ?
"romfile=," : '' ;
979 my $pciaddr = print_pci_addr
( " $netid " );
980 my $tmpstr = " $device,$ {extra}mac= $net ->{macaddr},netdev= $netid$pciaddr,id = $netid " ;
981 $tmpstr .= ",bootindex= $net ->{bootindex}" if $net ->{ bootindex
} ;
985 sub print_netdev_full
{
986 my ( $vmid, $conf, $net, $netid ) = @_ ;
989 if ( $netid =~ m/^net(\d+)$/ ) {
993 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
995 my $ifname = "tap${vmid}i $i " ;
997 # kvm uses TUNSETIFF ioctl, and that limits ifname length
998 die "interface name ' $ifname ' is too long (max 15 character) \n "
999 if length ( $ifname ) >= 16 ;
1001 my $vhostparam = '' ;
1002 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net ->{ model
} eq 'virtio' ;
1004 my $vmname = $conf ->{ name
} || "vm $vmid " ;
1006 if ( $net ->{ bridge
}) {
1007 return "type=tap,id= $netid,ifname =${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
1009 return "type=user,id= $netid,hostname = $vmname " ;
1013 sub drive_is_cdrom
{
1016 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
1023 return undef if ! $value ;
1027 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
1028 $res ->{ pciid
} = $value ;
1036 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1042 foreach my $kvp ( split ( /,/ , $data )) {
1044 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
1046 my $mac = uc ( $3 ) || PVE
:: Tools
:: random_ether_addr
();
1047 $res ->{ model
} = $model ;
1048 $res ->{ macaddr
} = $mac ;
1049 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
1050 $res ->{ bridge
} = $1 ;
1051 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
1059 return undef if ! $res ->{ model
};
1067 my $res = " $net ->{model}" ;
1068 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
1069 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
1070 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
1075 sub add_random_macs
{
1076 my ( $settings ) = @_ ;
1078 foreach my $opt ( keys %$settings ) {
1079 next if $opt !~ m/^net(\d+)$/ ;
1080 my $net = parse_net
( $settings ->{ $opt });
1082 $settings ->{ $opt } = print_net
( $net );
1086 sub add_unused_volume
{
1087 my ( $config, $volid, $vmid ) = @_ ;
1090 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1091 my $test = "unused $ind " ;
1092 if ( my $vid = $config ->{ $test }) {
1093 return if $vid eq $volid ; # do not add duplicates
1099 die "To many unused volume - please delete them first. \n " if ! $key ;
1101 PVE
:: QemuServer
:: change_config_nolock
( $vmid, { $key => $volid }, {}, 1 );
1102 $config ->{ $key } = $volid ;
1105 # fixme: remove all thos $noerr parameters?
1107 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1108 sub verify_bootdisk
{
1109 my ( $value, $noerr ) = @_ ;
1111 return $value if valid_drivename
( $value );
1113 return undef if $noerr ;
1115 die "invalid boot disk ' $value ' \n " ;
1118 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1120 my ( $value, $noerr ) = @_ ;
1122 return $value if parse_net
( $value );
1124 return undef if $noerr ;
1126 die "unable to parse network options \n " ;
1129 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1131 my ( $value, $noerr ) = @_ ;
1133 return $value if parse_drive
( undef , $value );
1135 return undef if $noerr ;
1137 die "unable to parse drive options \n " ;
1140 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1141 sub verify_hostpci
{
1142 my ( $value, $noerr ) = @_ ;
1144 return $value if parse_hostpci
( $value );
1146 return undef if $noerr ;
1148 die "unable to parse pci id \n " ;
1151 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1152 sub verify_watchdog
{
1153 my ( $value, $noerr ) = @_ ;
1155 return $value if parse_watchdog
( $value );
1157 return undef if $noerr ;
1159 die "unable to parse watchdog options \n " ;
1162 sub parse_watchdog
{
1165 return undef if ! $value ;
1169 foreach my $p ( split ( /,/ , $value )) {
1170 next if $p =~ m/^\s*$/ ;
1172 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1174 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1175 $res ->{ action
} = $2 ;
1184 sub parse_usb_device
{
1187 return undef if ! $value ;
1189 my @dl = split ( /,/ , $value );
1193 foreach my $v ( @dl ) {
1194 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1196 $res ->{ vendorid
} = $1 ;
1197 $res ->{ productid
} = $2 ;
1198 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1200 $res ->{ hostbus
} = $1 ;
1201 $res ->{ hostport
} = $2 ;
1206 return undef if ! $found ;
1211 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1212 sub verify_usb_device
{
1213 my ( $value, $noerr ) = @_ ;
1215 return $value if parse_usb_device
( $value );
1217 return undef if $noerr ;
1219 die "unable to parse usb device \n " ;
1222 # add JSON properties for create and set function
1223 sub json_config_properties
{
1226 foreach my $opt ( keys %$confdesc ) {
1227 $prop ->{ $opt } = $confdesc ->{ $opt };
1234 my ( $key, $value ) = @_ ;
1236 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1238 my $type = $confdesc ->{ $key }->{ type
};
1240 if (! defined ( $value )) {
1241 die "got undefined value \n " ;
1244 if ( $value =~ m/[\n\r]/ ) {
1245 die "property contains a line feed \n " ;
1248 if ( $type eq 'boolean' ) {
1249 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1250 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1251 die "type check ('boolean') failed - got ' $value ' \n " ;
1252 } elsif ( $type eq 'integer' ) {
1253 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1254 die "type check ('integer') failed - got ' $value ' \n " ;
1255 } elsif ( $type eq 'string' ) {
1256 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1257 if ( $fmt eq 'pve-qm-drive' ) {
1258 # special case - we need to pass $key to parse_drive()
1259 my $drive = parse_drive
( $key, $value );
1260 return $value if $drive ;
1261 die "unable to parse drive options \n " ;
1263 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1266 $value =~ s/^\"(.*)\"$/$1/ ;
1269 die "internal error"
1274 my ( $vmid, $code, @param ) = @_ ;
1276 my $filename = config_file_lock
( $vmid );
1278 my $res = lock_file
( $filename, 10 , $code, @param );
1285 sub cfs_config_path
{
1286 my ( $vmid, $node ) = @_ ;
1288 $node = $nodename if ! $node ;
1289 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1292 sub check_iommu_support
{
1293 #fixme : need to check IOMMU support
1294 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1302 my ( $vmid, $node ) = @_ ;
1304 my $cfspath = cfs_config_path
( $vmid, $node );
1305 return "/etc/pve/ $cfspath " ;
1308 sub config_file_lock
{
1311 return " $lock_dir/lock - $vmid .conf" ;
1317 my $conf = config_file
( $vmid );
1318 utime undef , undef , $conf ;
1322 my ( $storecfg, $vmid, $keep_empty_config ) = @_ ;
1324 my $conffile = config_file
( $vmid );
1326 my $conf = load_config
( $vmid );
1330 # only remove disks owned by this VM
1331 foreach_drive
( $conf, sub {
1332 my ( $ds, $drive ) = @_ ;
1334 return if drive_is_cdrom
( $drive );
1336 my $volid = $drive ->{ file
};
1337 return if ! $volid || $volid =~ m
|^/|;
1339 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1340 return if ! $path || ! $owner || ( $owner != $vmid );
1342 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1345 if ( $keep_empty_config ) {
1346 PVE
:: Tools
:: file_set_contents
( $conffile, "memory: 128 \n " );
1351 # also remove unused disk
1353 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1356 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1357 my ( $volid, $sid, $volname, $d ) = @_ ;
1358 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1368 sub load_diskinfo_old
{
1369 my ( $storecfg, $vmid, $conf ) = @_ ;
1375 foreach_drive
( $conf, sub {
1380 return if drive_is_cdrom
( $di );
1382 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1383 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1385 push @$vollist, $di ->{ file
};
1390 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1392 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1393 my ( $volid, $sid, $volname, $d ) = @_ ;
1394 $info ->{ $volid } = $d ;
1399 foreach my $ds ( keys %$res ) {
1400 my $di = $res ->{ $ds };
1402 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1403 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1412 my $cfspath = cfs_config_path
( $vmid );
1414 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1416 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1421 sub parse_vm_config
{
1422 my ( $filename, $raw ) = @_ ;
1424 return undef if ! defined ( $raw );
1427 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1430 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1431 || die "got strange filename ' $filename '" ;
1435 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1438 next if $line =~ m/^\#/ ;
1440 next if $line =~ m/^\s*$/ ;
1442 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1444 my $value = PVE
:: Tools
:: decode_text
( $2 );
1445 $res ->{ $key } = $value ;
1446 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1449 $res ->{ $key } = $value ;
1450 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1453 eval { $value = check_type
( $key, $value ); };
1455 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1457 my $fmt = $confdesc ->{ $key }->{ format
};
1458 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1459 my $v = parse_drive
( $key, $value );
1460 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1461 $v ->{ file
} = $volid ;
1462 $value = print_drive
( $vmid, $v );
1464 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1469 if ( $key eq 'cdrom' ) {
1470 $res ->{ ide2
} = $value ;
1472 $res ->{ $key } = $value ;
1478 # convert old smp to sockets
1479 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1480 $res ->{ sockets
} = $res ->{ smp
};
1488 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1490 lock_config
( $vmid, & change_config_nolock
, $settings, $unset, $skiplock );
1493 sub change_config_nolock
{
1494 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1498 $unset ->{ ide2
} = $unset ->{ cdrom
} if $unset ->{ cdrom
};
1500 check_lock
( $settings ) if ! $skiplock ;
1502 # we do not use 'smp' any longer
1503 if ( $settings ->{ sockets
}) {
1505 } elsif ( $settings ->{ smp
}) {
1506 $settings ->{ sockets
} = $settings ->{ smp
};
1510 my $new_volids = {};
1512 foreach my $key ( keys %$settings ) {
1513 next if $key eq 'digest' ;
1514 my $value = $settings ->{ $key };
1515 if ( $key eq 'description' ) {
1516 $value = PVE
:: Tools
:: encode_text
( $value );
1518 eval { $value = check_type
( $key, $value ); };
1519 die "unable to parse value of ' $key ' - $@ " if $@ ;
1520 if ( $key eq 'cdrom' ) {
1521 $res ->{ ide2
} = $value ;
1523 $res ->{ $key } = $value ;
1525 if ( valid_drivename
( $key )) {
1526 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1527 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1531 my $filename = config_file
( $vmid );
1532 my $tmpfn = " $filename . $$ .tmp" ;
1534 my $fh = new IO
:: File
( $filename, "r" ) ||
1535 die "unable to read config for VM $vmid\n " ;
1537 my $werror = "unable to write config for VM $vmid\n " ;
1539 my $out = new IO
:: File
( $tmpfn, "w" ) || die $werror ;
1545 while ( my $line = < $fh >) {
1547 if (( $line =~ m/^\#/ ) || ( $line =~ m/^\s*$/ )) {
1548 die $werror unless print $out $line ;
1552 if ( $line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/ ) {
1556 # remove 'unusedX' settings if we re-add a volume
1557 next if $key =~ m/^unused/ && $new_volids ->{ $value };
1559 # convert 'smp' to 'sockets'
1560 $key = 'sockets' if $key eq 'smp' ;
1562 next if $done ->{ $key };
1565 if ( defined ( $res ->{ $key })) {
1566 $value = $res ->{ $key };
1567 delete $res ->{ $key };
1569 if (! defined ( $unset ->{ $key })) {
1570 die $werror unless print $out " $key : $value\n " ;
1576 die "unable to parse config file: $line\n " ;
1579 foreach my $key ( keys %$res ) {
1581 if (! defined ( $unset ->{ $key })) {
1582 die $werror unless print $out " $key : $res ->{ $key } \n " ;
1597 if (! $out -> close ()) {
1598 $err = "close failed - $!\n " ;
1603 if (! rename ( $tmpfn, $filename )) {
1604 $err = "rename failed - $!\n " ;
1614 # we use static defaults from our JSON schema configuration
1615 foreach my $key ( keys %$confdesc ) {
1616 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1617 $res ->{ $key } = $default ;
1621 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1622 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1628 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1630 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1631 my $ids = $vmlist ->{ ids
};
1633 foreach my $vmid ( keys %$ids ) {
1634 my $d = $ids ->{ $vmid };
1635 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1636 next if ! $d ->{ type
} || $d ->{ type
} ne 'qemu' ;
1637 $res ->{ $vmid }->{ exists } = 1 ;
1642 # test if VM uses local resources (to prevent migration)
1643 sub check_local_resources
{
1644 my ( $conf, $noerr ) = @_ ;
1648 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1649 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1651 foreach my $k ( keys %$conf ) {
1652 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1655 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1663 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1667 my ( $pidfile, $pid ) = @_ ;
1669 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1673 return undef if ! $line ;
1674 my @param = split ( /\0/ , $line );
1676 my $cmd = $param [ 0 ];
1677 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1679 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1682 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1683 my $p = $param [ $i+1 ];
1684 return 1 if $p && ( $p eq $pidfile );
1693 my ( $vmid, $nocheck ) = @_ ;
1695 my $filename = config_file
( $vmid );
1697 die "unable to find configuration file for VM $vmid - no such machine \n "
1698 if ! $nocheck && ! - f
$filename ;
1700 my $pidfile = pidfile_name
( $vmid );
1702 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1707 my $mtime = $st -> mtime ;
1708 if ( $mtime > time ()) {
1709 warn "file ' $filename ' modified in future \n " ;
1712 if ( $line =~ m/^(\d+)$/ ) {
1714 if ( check_cmdline
( $pidfile, $pid )) {
1715 if ( my $pinfo = PVE
:: ProcFSTools
:: check_process_running
( $pid )) {
1727 my $vzlist = config_list
();
1729 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1731 while ( defined ( my $de = $fd -> read )) {
1732 next if $de !~ m/^(\d+)\.pid$/ ;
1734 next if ! defined ( $vzlist ->{ $vmid });
1735 if ( my $pid = check_running
( $vmid )) {
1736 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1743 my $storage_timeout_hash = {};
1746 my ( $storecfg, $conf ) = @_ ;
1748 my $bootdisk = $conf ->{ bootdisk
};
1749 return undef if ! $bootdisk ;
1750 return undef if ! valid_drivename
( $bootdisk );
1752 return undef if ! $conf ->{ $bootdisk };
1754 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1755 return undef if ! defined ( $drive );
1757 return undef if drive_is_cdrom
( $drive );
1759 my $volid = $drive ->{ file
};
1760 return undef if ! $volid ;
1766 if ( $volid =~ m
|^/|) {
1767 $path = $timeoutid = $volid ;
1770 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1771 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1779 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1780 if ( $last_timeout ) {
1781 if (( time () - $last_timeout ) < 30 ) {
1782 # skip storage with errors
1785 delete $storage_timeout_hash ->{ $timeoutid };
1788 my ( $size, $format, $used );
1790 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1792 if (! defined ( $format )) {
1794 $storage_timeout_hash ->{ $timeoutid } = time ();
1798 return wantarray ?
( $size, $used ) : $size ;
1801 my $last_proc_pid_stat ;
1804 my ( $opt_vmid ) = @_ ;
1808 my $storecfg = PVE
:: Storage
:: config
();
1810 my $list = vzlist
();
1811 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
( 1 );
1813 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1815 foreach my $vmid ( keys %$list ) {
1816 next if $opt_vmid && ( $vmid ne $opt_vmid );
1818 my $cfspath = cfs_config_path
( $vmid );
1819 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1822 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1824 # fixme: better status?
1825 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1827 my ( $size, $used ) = disksize
( $storecfg, $conf );
1828 if ( defined ( $size ) && defined ( $used )) {
1830 $d ->{ maxdisk
} = $size ;
1836 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1837 $d ->{ cpus
} = $cpucount if $d ->{ cpus
} > $cpucount ;
1839 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1840 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1850 $d ->{ diskwrite
} = 0 ;
1855 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1856 foreach my $dev ( keys %$netdev ) {
1857 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1859 my $d = $res ->{ $vmid };
1862 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1863 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1866 my $ctime = gettimeofday
;
1868 foreach my $vmid ( keys %$list ) {
1870 my $d = $res ->{ $vmid };
1871 my $pid = $d ->{ pid
};
1874 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1876 while ( defined ( my $line = < $fh >)) {
1877 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1882 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1883 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1886 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1887 next if ! $pstat ; # not running
1889 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
1891 $d ->{ uptime
} = int (( $uptime - $pstat ->{ starttime
})/ $cpuinfo ->{ user_hz
});
1893 if ( $pstat ->{ vsize
}) {
1894 $d ->{ mem
} = int (( $pstat ->{ rss
}/ $pstat ->{ vsize
})* $d ->{ maxmem
});
1897 my $old = $last_proc_pid_stat ->{ $pid };
1899 $last_proc_pid_stat ->{ $pid } = {
1907 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1909 if ( $dtime > 1000 ) {
1910 my $dutime = $used - $old ->{ used
};
1912 $d ->{ cpu
} = (( $dutime/$dtime )* $cpucount ) / $d ->{ cpus
};
1913 $last_proc_pid_stat ->{ $pid } = {
1919 $d ->{ cpu
} = $old ->{ cpu
};
1927 my ( $conf, $func ) = @_ ;
1929 foreach my $ds ( keys %$conf ) {
1930 next if ! valid_drivename
( $ds );
1932 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1935 & $func ( $ds, $drive );
1939 sub config_to_command
{
1940 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1944 my $kvmver = kvm_user_version
();
1945 my $vernum = 0 ; # unknown
1946 if ( $kvmver =~ m/^(\d+)\.(\d+)$/ ) {
1947 $vernum = $1*1000000+$2*1000 ;
1948 } elsif ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1949 $vernum = $1*1000000+$2*1000+$3 ;
1952 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 15000 ;
1954 my $have_ovz = - f
'/proc/vz/vestat' ;
1956 push @$cmd, '/usr/bin/kvm' ;
1958 push @$cmd, '-id' , $vmid ;
1962 my $socket = monitor_socket
( $vmid );
1963 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1964 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1966 $socket = vnc_socket
( $vmid );
1967 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1969 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1971 push @$cmd, '-daemonize' ;
1973 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1976 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1977 next if ! $conf ->{ "usb $i " };
1980 # include usb device config
1981 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2 ;
1983 # enable absolute mouse coordinates (needed by vnc)
1984 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1987 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' ;
1989 push @$cmd, '-usbdevice' , 'tablet' ;
1994 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1995 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1997 $pciaddr = print_pci_addr
( "hostpci $i " );
1998 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
2002 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
2003 my $d = parse_usb_device
( $conf ->{ "usb $i " });
2005 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
2006 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
2007 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
2008 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
2013 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
2014 if ( my $path = $conf ->{ "serial $i " }) {
2015 die "no such serial device \n " if ! - c
$path ;
2016 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
2017 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
2022 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
2023 if ( my $path = $conf ->{ "parallel $i " }) {
2024 die "no such parallel device \n " if ! - c
$path ;
2025 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
2026 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
2030 my $vmname = $conf ->{ name
} || "vm $vmid " ;
2032 push @$cmd, '-name' , $vmname ;
2035 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
2036 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2038 my $cores = $conf ->{ cores
} || 1 ;
2040 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2042 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2044 push @$cmd, '-nodefaults' ;
2046 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2048 my $bootindex_hash = {};
2050 foreach my $o ( split ( // , $bootorder )) {
2051 $bootindex_hash ->{ $o } = $i*100 ;
2055 push @$cmd, '-boot' , "menu=on" ;
2057 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2059 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2061 my $vga = $conf ->{ vga
};
2063 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2070 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2073 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2074 push @$cmd, '-tdf' if $tdf ;
2076 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2078 if ( my $ost = $conf ->{ ostype
}) {
2079 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2081 if ( $ost =~ m/^w/ ) { # windows
2082 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2084 # use rtc-td-hack when acpi is enabled
2085 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2086 push @$cmd, '-rtc-td-hack' ;
2097 push @$cmd, '-no-kvm' ;
2099 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2102 push @$cmd, '-localtime' if $conf ->{ localtime };
2104 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2106 push @$cmd, '-S' if $conf ->{ freeze
};
2108 # set keyboard layout
2109 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2110 push @$cmd, '-k' , $kb if $kb ;
2113 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2114 #push @$cmd, '-soundhw', 'es1370';
2115 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2116 $pciaddr = print_pci_addr
( "balloon0" );
2117 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2119 if ( $conf ->{ watchdog
}) {
2120 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2121 $pciaddr = print_pci_addr
( "watchdog" );
2122 my $watchdog = $wdopts ->{ model
} || 'i6300esb' ;
2123 push @$cmd, '-device' , " $watchdog$pciaddr " ;
2124 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2128 my $scsicontroller = {};
2129 my $ahcicontroller = {};
2131 foreach_drive
( $conf, sub {
2132 my ( $ds, $drive ) = @_ ;
2134 if ( PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 )) {
2135 push @$vollist, $drive ->{ file
};
2138 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2140 if ( drive_is_cdrom
( $drive )) {
2141 if ( $bootindex_hash ->{ d
}) {
2142 $drive ->{ bootindex
} = $bootindex_hash ->{ d
};
2143 $bootindex_hash ->{ d
} += 1 ;
2146 if ( $bootindex_hash ->{ c
}) {
2147 $drive ->{ bootindex
} = $bootindex_hash ->{ c
} if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2148 $bootindex_hash ->{ c
} += 1 ;
2152 if ( $drive ->{ interface
} eq 'scsi' ) {
2154 my $controller = int ( $drive ->{ index } / $maxdev );
2155 $pciaddr = print_pci_addr
( "lsi $controller " );
2156 push @$cmd, '-device' , "lsi,id=lsi $controller$pciaddr " if ! $scsicontroller ->{ $controller };
2157 $scsicontroller ->{ $controller }= 1 ;
2160 if ( $drive ->{ interface
} eq 'sata' ) {
2161 my $controller = int ( $drive ->{ index } / $MAX_SATA_DISKS );
2162 $pciaddr = print_pci_addr
( "ahci $controller " );
2163 push @$cmd, '-device' , "ahci,id=ahci $controller,multifunction =on $pciaddr " if ! $ahcicontroller ->{ $controller };
2164 $ahcicontroller ->{ $controller }= 1 ;
2167 push @$cmd, '-drive' , print_drive_full
( $storecfg, $vmid, $drive );
2168 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2171 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2173 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
2174 next if ! $conf ->{ "net $i " };
2175 my $d = parse_net
( $conf ->{ "net $i " });
2178 $use_virtio = 1 if $d ->{ model
} eq 'virtio' ;
2180 if ( $bootindex_hash ->{ n
}) {
2181 $d ->{ bootindex
} = $bootindex_hash ->{ n
};
2182 $bootindex_hash ->{ n
} += 1 ;
2185 my $netdevfull = print_netdev_full
( $vmid,$conf,$d, "net $i " );
2186 push @$cmd, '-netdev' , $netdevfull ;
2188 my $netdevicefull = print_netdevice_full
( $vmid,$conf,$d, "net $i " );
2189 push @$cmd, '-device' , $netdevicefull ;
2193 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2194 # when the VM uses virtio devices.
2195 if (! $use_virtio && $have_ovz ) {
2197 my $cpuunits = defined ( $conf ->{ cpuunits
}) ?
2198 $conf ->{ cpuunits
} : $defaults ->{ cpuunits
};
2200 push @$cmd, '-cpuunits' , $cpuunits if $cpuunits ;
2202 # fixme: cpulimit is currently ignored
2203 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2207 if ( $conf ->{ args
}) {
2208 my $aa = PVE
:: Tools
:: split_args
( $conf ->{ args
});
2212 return wantarray ?
( $cmd, $vollist ) : $cmd ;
2217 return "${var_run_tmpdir}/ $vmid .vnc" ;
2220 sub monitor_socket
{
2222 return "${var_run_tmpdir}/ $vmid .mon" ;
2227 return "${var_run_tmpdir}/ $vmid .pid" ;
2230 sub next_migrate_port
{
2232 for ( my $p = 60000 ; $p < 60010 ; $p++ ) {
2234 my $sock = IO
:: Socket
:: INET-
> new ( Listen
=> 5 ,
2235 LocalAddr
=> 'localhost' ,
2246 die "unable to find free migration port" ;
2249 sub vm_devices_list
{
2252 my $res = vm_monitor_command
( $vmid, "info pci" );
2254 my @lines = split ( " \n " , $res );
2260 foreach my $line ( @lines ) {
2262 if ( $line =~ m/^Bus (\d+), device (\d+), function (\d+):$/ ) {
2266 if ( $line =~ m/^id "([a-z][a-z_\-]*\d*)"$/ ) {
2268 $devices ->{ $id }->{ bus
}= $bus ;
2269 $devices ->{ $id }->{ addr
}= $addr ;
2277 my ( $storecfg, $conf, $vmid, $deviceid, $device ) = @_ ;
2278 return 1 if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2280 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2281 return undef if ! qemu_driveadd
( $storecfg, $vmid, $device );
2282 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2283 qemu_deviceadd
( $vmid, $devicefull );
2284 if (! qemu_deviceaddverify
( $vmid, $deviceid )) {
2285 qemu_drivedel
( $vmid, $deviceid );
2290 if ( $deviceid =~ m/^(lsi)(\d+)$/ ) {
2291 my $pciaddr = print_pci_addr
( $deviceid );
2292 my $devicefull = "lsi,id= $deviceid$pciaddr " ;
2293 qemu_deviceadd
( $vmid, $devicefull );
2294 return undef if (! qemu_deviceaddverify
( $vmid, $deviceid ));
2297 if ( $deviceid =~ m/^(scsi)(\d+)$/ ) {
2298 return undef if ! qemu_findorcreatelsi
( $storecfg,$conf, $vmid, $device );
2299 return undef if ! qemu_driveadd
( $storecfg, $vmid, $device );
2300 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2301 if (! qemu_deviceadd
( $vmid, $devicefull )) {
2302 qemu_drivedel
( $vmid, $deviceid );
2307 if ( $deviceid =~ m/^(net)(\d+)$/ ) {
2308 return undef if ! qemu_netdevadd
( $vmid, $conf, $device, $deviceid );
2309 my $netdevicefull = print_netdevice_full
( $vmid, $conf, $device, $deviceid );
2310 qemu_deviceadd
( $vmid, $netdevicefull );
2311 if (! qemu_deviceaddverify
( $vmid, $deviceid )) {
2312 qemu_netdevdel
( $vmid, $deviceid );
2320 sub vm_deviceunplug
{
2321 my ( $vmid, $conf, $deviceid ) = @_ ;
2323 return 1 if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2325 die "can't unplug bootdisk" if $conf ->{ bootdisk
} eq $deviceid ;
2327 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2328 return undef if ! qemu_drivedel
( $vmid, $deviceid );
2329 qemu_devicedel
( $vmid, $deviceid );
2330 return undef if ! qemu_devicedelverify
( $vmid, $deviceid );
2333 if ( $deviceid =~ m/^(lsi)(\d+)$/ ) {
2334 return undef if ! qemu_devicedel
( $vmid, $deviceid );
2337 if ( $deviceid =~ m/^(scsi)(\d+)$/ ) {
2338 return undef if ! qemu_devicedel
( $vmid, $deviceid );
2339 return undef if ! qemu_drivedel
( $vmid, $deviceid );
2342 if ( $deviceid =~ m/^(net)(\d+)$/ ) {
2343 return undef if ! qemu_netdevdel
( $vmid, $deviceid );
2344 qemu_devicedel
( $vmid, $deviceid );
2345 return undef if ! qemu_devicedelverify
( $vmid, $deviceid );
2351 sub qemu_deviceadd
{
2352 my ( $vmid, $devicefull ) = @_ ;
2354 my $ret = vm_monitor_command
( $vmid, "device_add $devicefull " );
2356 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2357 return 1 if $ret eq "" ;
2358 syslog
( "err" , "error on hotplug device : $ret " );
2363 sub qemu_devicedel
{
2364 my ( $vmid, $deviceid ) = @_ ;
2366 my $ret = vm_monitor_command
( $vmid, "device_del $deviceid " );
2368 return 1 if $ret eq "" ;
2369 syslog
( "err" , "detaching device $deviceid failed : $ret " );
2374 my ( $storecfg, $vmid, $device ) = @_ ;
2376 my $drive = print_drive_full
( $storecfg, $vmid, $device );
2377 my $ret = vm_monitor_command
( $vmid, "drive_add auto $drive " );
2378 # If the command succeeds qemu prints: "OK"
2379 if ( $ret !~ m/OK/s ) {
2380 syslog
( "err" , "adding drive failed: $ret " );
2387 my ( $vmid, $deviceid ) = @_ ;
2389 my $ret = vm_monitor_command
( $vmid, "drive_del drive- $deviceid " );
2391 if ( $ret =~ m/Device \'.*?\' not found/s ) {
2392 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2394 elsif ( $ret ne "" ) {
2395 syslog
( "err" , "deleting drive $deviceid failed : $ret " );
2401 sub qemu_deviceaddverify
{
2402 my ( $vmid,$deviceid ) = @_ ;
2404 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2405 my $devices_list = vm_devices_list
( $vmid );
2406 return 1 if defined ( $devices_list ->{ $deviceid });
2409 syslog
( "err" , "error on hotplug device $deviceid " );
2414 sub qemu_devicedelverify
{
2415 my ( $vmid,$deviceid ) = @_ ;
2417 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2418 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2419 my $devices_list = vm_devices_list
( $vmid );
2420 return 1 if ! defined ( $devices_list ->{ $deviceid });
2423 syslog
( "err" , "error on hot-unplugging device $deviceid " );
2427 sub qemu_findorcreatelsi
{
2428 my ( $storecfg, $conf, $vmid, $device ) = @_ ;
2431 my $controller = int ( $device ->{ index } / $maxdev );
2432 my $lsiid = "lsi $controller " ;
2433 my $devices_list = vm_devices_list
( $vmid );
2435 if (! defined ( $devices_list ->{ $lsiid })) {
2436 return undef if ! vm_deviceplug
( $storecfg, $conf, $vmid, $lsiid );
2441 sub qemu_netdevadd
{
2442 my ( $vmid, $conf, $device, $deviceid ) = @_ ;
2444 my $netdev = print_netdev_full
( $vmid, $conf, $device, $deviceid );
2445 my $ret = vm_monitor_command
( $vmid, "netdev_add $netdev " );
2448 #if the command succeeds, no output is sent. So any non-empty string shows an error
2449 return 1 if $ret eq "" ;
2450 syslog
( "err" , "adding netdev failed: $ret " );
2454 sub qemu_netdevdel
{
2455 my ( $vmid, $deviceid ) = @_ ;
2457 my $ret = vm_monitor_command
( $vmid, "netdev_del $deviceid " );
2459 #if the command succeeds, no output is sent. So any non-empty string shows an error
2460 return 1 if $ret eq "" ;
2461 syslog
( "err" , "deleting netdev failed: $ret " );
2466 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2468 lock_config
( $vmid, sub {
2469 my $conf = load_config
( $vmid );
2471 check_lock
( $conf ) if ! $skiplock ;
2473 die "VM $vmid already running \n " if check_running
( $vmid );
2476 my $migrate_port = 0 ;
2479 if ( $statefile eq 'tcp' ) {
2480 $migrate_port = next_migrate_port
();
2481 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2483 if (- f
$statefile ) {
2484 $migrate_uri = "exec:cat $statefile " ;
2486 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2491 my $defaults = load_defaults
();
2493 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2495 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2496 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2498 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2499 die "IOMMU not present \n " if ! check_iommu_support
();
2500 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2501 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2502 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2505 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2507 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2509 die "start failed: $err " if $err ;
2513 if ( $statefile eq 'tcp' ) {
2514 print "migration listens on port $migrate_port\n " ;
2517 # fixme: send resume - is that necessary ?
2518 eval { vm_monitor_command
( $vmid, "cont" ); };
2522 # always set migrate speed (overwrite kvm default of 32m)
2523 # we set a very hight default of 8192m which is basically unlimited
2524 my $migrate_speed = $defaults ->{ migrate_speed
} || 8192 ;
2525 $migrate_speed = $conf ->{ migrate_speed
} || $migrate_speed ;
2527 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2528 vm_monitor_command
( $vmid, $cmd );
2531 if ( my $migrate_downtime =
2532 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2533 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2534 eval { vm_monitor_command
( $vmid, $cmd ); };
2537 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2542 my ( $fh, $timeout ) = @_ ;
2544 my $sel = new IO
:: Select
;
2551 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2553 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2554 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2561 if (! defined ( $count )) {
2568 die "monitor read timeout \n " if ! scalar ( @ready );
2573 sub vm_monitor_command
{
2574 my ( $vmid, $cmdstr, $nocheck ) = @_ ;
2579 die "VM $vmid not running \n " if ! check_running
( $vmid, $nocheck );
2581 my $sname = monitor_socket
( $vmid );
2583 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2584 die "unable to connect to VM $vmid socket - $!\n " ;
2588 # hack: migrate sometime blocks the monitor (when migrate_downtime
2590 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2591 $timeout = 60 * 60 ; # 1 hour
2595 my $data = __read_avail
( $sock, $timeout );
2597 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2598 die "got unexpected qemu monitor banner \n " ;
2601 my $sel = new IO
:: Select
;
2604 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2605 die "monitor write error - timeout" ;
2608 my $fullcmd = " $cmdstr\r " ;
2611 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2612 die "monitor write error - $! " ;
2615 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2619 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2620 $timeout = 60 * 60 ; # 1 hour
2621 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2622 $timeout = 60 ; # note: cdrom mount command is slow
2624 if ( $res = __read_avail
( $sock, $timeout )) {
2626 my @lines = split ( " \r ? \n " , $res );
2628 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2630 $res = join ( " \n " , @lines );
2638 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2645 sub vm_commandline
{
2646 my ( $storecfg, $vmid ) = @_ ;
2648 my $conf = load_config
( $vmid );
2650 my $defaults = load_defaults
();
2652 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2654 return join ( ' ' , @$cmd );
2658 my ( $vmid, $skiplock ) = @_ ;
2660 lock_config
( $vmid, sub {
2662 my $conf = load_config
( $vmid );
2664 check_lock
( $conf ) if ! $skiplock ;
2666 vm_monitor_command
( $vmid, "system_reset" );
2670 sub get_vm_volumes
{
2674 foreach_drive
( $conf, sub {
2675 my ( $ds, $drive ) = @_ ;
2677 my ( $sid, $volname ) = PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 );
2680 my $volid = $drive ->{ file
};
2681 return if ! $volid || $volid =~ m
|^/|;
2683 push @$vollist, $volid ;
2689 sub vm_stop_cleanup
{
2690 my ( $storecfg, $vmid, $conf, $keepActive ) = @_ ;
2693 fairsched_rmnod
( $vmid ); # try to destroy group
2696 my $vollist = get_vm_volumes
( $conf );
2697 PVE
:: Storage
:: deactivate_volumes
( $storecfg, $vollist );
2700 warn $@ if $@ ; # avoid errors - just warn
2703 # Note: use $nockeck to skip tests if VM configuration file exists.
2704 # We need that when migration VMs to other nodes (files already moved)
2705 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
2707 my ( $storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive ) = @_ ;
2709 $timeout = 60 if ! defined ( $timeout );
2711 $force = 1 if ! defined ( $force ) && ! $shutdown ;
2713 lock_config
( $vmid, sub {
2715 my $pid = check_running
( $vmid, $nocheck );
2720 $conf = load_config
( $vmid );
2721 check_lock
( $conf ) if ! $skiplock ;
2726 vm_monitor_command
( $vmid, "system_powerdown" , $nocheck );
2728 vm_monitor_command
( $vmid, "quit" , $nocheck );
2735 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2740 if ( $count >= $timeout ) {
2742 warn "VM still running - terminating now with SIGTERM \n " ;
2745 die "VM quit/powerdown failed - got timeout \n " ;
2748 vm_stop_cleanup
( $storecfg, $vmid, $conf, $keepActive ) if $conf ;
2753 warn "VM quit/powerdown failed - terminating now with SIGTERM \n " ;
2756 die "VM quit/powerdown failed \n " ;
2764 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2769 if ( $count >= $timeout ) {
2770 warn "VM still running - terminating now with SIGKILL \n " ;
2775 vm_stop_cleanup
( $storecfg, $vmid, $conf, $keepActive ) if $conf ;
2780 my ( $vmid, $skiplock ) = @_ ;
2782 lock_config
( $vmid, sub {
2784 my $conf = load_config
( $vmid );
2786 check_lock
( $conf ) if ! $skiplock ;
2788 vm_monitor_command
( $vmid, "stop" );
2793 my ( $vmid, $skiplock ) = @_ ;
2795 lock_config
( $vmid, sub {
2797 my $conf = load_config
( $vmid );
2799 check_lock
( $conf ) if ! $skiplock ;
2801 vm_monitor_command
( $vmid, "cont" );
2806 my ( $vmid, $skiplock, $key ) = @_ ;
2808 lock_config
( $vmid, sub {
2810 my $conf = load_config
( $vmid );
2812 vm_monitor_command
( $vmid, "sendkey $key " );
2817 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2819 lock_config
( $vmid, sub {
2821 my $conf = load_config
( $vmid );
2823 check_lock
( $conf ) if ! $skiplock ;
2825 if (! check_running
( $vmid )) {
2826 fairsched_rmnod
( $vmid ); # try to destroy group
2827 destroy_vm
( $storecfg, $vmid );
2829 die "VM $vmid is running - destroy failed \n " ;
2835 my ( $storecfg, $timeout ) = @_ ;
2837 $timeout = 3 * 60 if ! $timeout ;
2839 my $cleanuphash = {};
2841 my $vzlist = vzlist
();
2843 foreach my $vmid ( keys %$vzlist ) {
2844 next if ! $vzlist ->{ $vmid }->{ pid
};
2846 $cleanuphash ->{ $vmid } = 1 ;
2851 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2852 syslog
( 'info' , $msg );
2855 foreach my $vmid ( keys %$vzlist ) {
2856 next if ! $vzlist ->{ $vmid }->{ pid
};
2857 eval { vm_monitor_command
( $vmid, "system_powerdown" ); };
2862 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2864 while (( $try < $maxtries ) && $count ) {
2870 foreach my $vmid ( keys %$vzlist ) {
2871 next if ! $vzlist ->{ $vmid }->{ pid
};
2879 foreach my $vmid ( keys %$vzlist ) {
2880 next if ! $vzlist ->{ $vmid }->{ pid
};
2882 warn "VM $vmid still running - sending stop now \n " ;
2883 eval { vm_monitor_command
( $vmid, "quit" ); };
2888 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2890 while (( $try < $maxtries ) && $count ) {
2896 foreach my $vmid ( keys %$vzlist ) {
2897 next if ! $vzlist ->{ $vmid }->{ pid
};
2905 foreach my $vmid ( keys %$vzlist ) {
2906 next if ! $vzlist ->{ $vmid }->{ pid
};
2908 warn "VM $vmid still running - terminating now with SIGTERM \n " ;
2909 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2914 # this is called by system shotdown scripts, so remaining
2915 # processes gets killed anyways (no need to send kill -9 here)
2919 foreach my $vmid ( keys %$cleanuphash ) {
2920 next if $vzlist ->{ $vmid }->{ pid
};
2922 my $conf = load_config
( $vmid );
2923 vm_stop_cleanup
( $storecfg, $vmid, $conf );
2928 $msg = "Qemu Server stopped \n " ;
2929 syslog
( 'info' , $msg );
2936 my ( $filename, $buf ) = @_ ;
2938 my $fh = IO
:: File-
> new ( $filename, "w" );
2939 return undef if ! $fh ;
2941 my $res = print $fh $buf ;
2948 sub pci_device_info
{
2953 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2954 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2956 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2957 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2959 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2960 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2962 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2963 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2968 product
=> $product,
2974 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2983 my $name = $dev ->{ name
};
2985 my $fn = " $pcisysfs/devices/$name/reset " ;
2987 return file_write
( $fn, "1" );
2990 sub pci_dev_bind_to_stub
{
2993 my $name = $dev ->{ name
};
2995 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2996 return 1 if - d
$testdir ;
2998 my $data = " $dev ->{vendor} $dev ->{product}" ;
2999 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
3001 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
3002 if (! file_write
( $fn, $name )) {
3003 return undef if - f
$fn ;
3006 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
3007 if (! - d
$testdir ) {
3008 return undef if ! file_write
( $fn, $name );
3014 sub print_pci_addr
{
3019 #addr1 : ide,parallel,serial (motherboard)
3020 #addr2 : first videocard
3021 balloon0
=> { bus
=> 0 , addr
=> 3 },
3022 watchdog
=> { bus
=> 0 , addr
=> 4 },
3023 lsi0
=> { bus
=> 0 , addr
=> 5 },
3024 lsi1
=> { bus
=> 0 , addr
=> 6 },
3025 ahci0
=> { bus
=> 0 , addr
=> 7 },
3026 virtio0
=> { bus
=> 0 , addr
=> 10 },
3027 virtio1
=> { bus
=> 0 , addr
=> 11 },
3028 virtio2
=> { bus
=> 0 , addr
=> 12 },
3029 virtio3
=> { bus
=> 0 , addr
=> 13 },
3030 virtio4
=> { bus
=> 0 , addr
=> 14 },
3031 virtio5
=> { bus
=> 0 , addr
=> 15 },
3032 hostpci0
=> { bus
=> 0 , addr
=> 16 },
3033 hostpci1
=> { bus
=> 0 , addr
=> 17 },
3034 net0
=> { bus
=> 0 , addr
=> 18 },
3035 net1
=> { bus
=> 0 , addr
=> 19 },
3036 net2
=> { bus
=> 0 , addr
=> 20 },
3037 net3
=> { bus
=> 0 , addr
=> 21 },
3038 net4
=> { bus
=> 0 , addr
=> 22 },
3039 net5
=> { bus
=> 0 , addr
=> 23 },
3040 #addr29 : usb-host (pve-usb.cfg)
3043 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
3044 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
3045 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
3052 my ( $vmid, $value ) = @_ ;
3054 vm_monitor_command
( $vmid, "balloon $value " );
3057 # vzdump restore implementaion
3059 sub archive_read_firstfile
{
3060 my $archive = shift ;
3062 die "ERROR: file ' $archive ' does not exist \n " if ! - f
$archive ;
3064 # try to detect archive type first
3065 my $pid = open ( TMP
, "tar tf ' $archive '|" ) ||
3066 die "unable to open file ' $archive ' \n " ;
3067 my $firstfile = < TMP
>;
3071 die "ERROR: archive contaions no data \n " if ! $firstfile ;
3077 sub restore_cleanup
{
3078 my $statfile = shift ;
3080 print STDERR
"starting cleanup \n " ;
3082 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3083 while ( defined ( my $line = < $fd >)) {
3084 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3087 if ( $volid =~ m
|^/|) {
3088 unlink $volid || die 'unlink failed \n ' ;
3090 my $cfg = cfs_read_file
( 'storage.cfg' );
3091 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
3093 print STDERR
"temporary volume ' $volid ' sucessfuly removed \n " ;
3095 print STDERR
"unable to cleanup ' $volid ' - $@ " if $@ ;
3097 print STDERR
"unable to parse line in statfile - $line " ;
3104 sub restore_archive
{
3105 my ( $archive, $vmid, $user, $opts ) = @_ ;
3107 if ( $archive ne '-' ) {
3108 my $firstfile = archive_read_firstfile
( $archive );
3109 die "ERROR: file ' $archive ' dos not lock like a QemuServer vzdump backup \n "
3110 if $firstfile ne 'qemu-server.conf' ;
3113 my $tocmd = "/usr/lib/qemu-server/qmextract" ;
3115 $tocmd .= " --storage " . PVE
:: Tools
:: shellquote
( $opts ->{ storage
}) if $opts ->{ storage
};
3116 $tocmd .= " --pool " . PVE
:: Tools
:: shellquote
( $opts ->{ pool
}) if $opts ->{ pool
};
3117 $tocmd .= ' --prealloc' if $opts ->{ prealloc
};
3118 $tocmd .= ' --info' if $opts ->{ info
};
3120 # tar option "xf" does not autodetect compression when read from STDIN,
3121 # so we pipe to zcat
3122 my $cmd = "zcat -f|tar xf " . PVE
:: Tools
:: shellquote
( $archive ) . " " .
3123 PVE
:: Tools
:: shellquote
( "--to-command= $tocmd " );
3125 my $tmpdir = "/var/tmp/vzdumptmp $$ " ;
3128 local $ENV { VZDUMP_TMPDIR
} = $tmpdir ;
3129 local $ENV { VZDUMP_VMID
} = $vmid ;
3130 local $ENV { VZDUMP_USER
} = $user ;
3132 my $conffile = PVE
:: QemuServer
:: config_file
( $vmid );
3133 my $tmpfn = " $conffile . $$ .tmp" ;
3135 # disable interrupts (always do cleanups)
3136 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = sub {
3137 print STDERR
"got interrupt - ignored \n " ;
3142 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = $SIG { PIPE
} = sub {
3143 die "interrupted by signal \n " ;
3146 if ( $archive eq '-' ) {
3147 print "extracting archive from STDIN \n " ;
3148 run_command
( $cmd, input
=> "<&STDIN" );
3150 print "extracting archive ' $archive ' \n " ;
3154 return if $opts ->{ info
};
3158 my $statfile = " $tmpdir/qmrestore .stat" ;
3159 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
3160 while ( defined ( my $line = < $fd >)) {
3161 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3162 $map ->{ $1 } = $2 if $1 ;
3164 print STDERR
"unable to parse line in statfile - $line\n " ;
3170 my $confsrc = " $tmpdir/qemu -server.conf" ;
3172 my $srcfd = new IO
:: File
( $confsrc, "r" ) ||
3173 die "unable to open file ' $confsrc ' \n " ;
3175 my $outfd = new IO
:: File
( $tmpfn, "w" ) ||
3176 die "unable to write config for VM $vmid\n " ;
3180 while ( defined ( my $line = < $srcfd >)) {
3181 next if $line =~ m/^\#vzdump\#/ ;
3182 next if $line =~ m/^lock:/ ;
3183 next if $line =~ m/^unused\d+:/ ;
3185 if (( $line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/ )) {
3186 # try to convert old 1.X settings
3187 my ( $id, $ind, $ethcfg ) = ( $1, $2, $3 );
3188 foreach my $devconfig ( PVE
:: Tools
:: split_list
( $ethcfg )) {
3189 my ( $model, $macaddr ) = split ( /\=/ , $devconfig );
3190 $macaddr = PVE
:: Tools
:: random_ether_addr
() if ! $macaddr || $opts ->{ unique
};
3193 bridge
=> "vmbr $ind " ,
3194 macaddr
=> $macaddr,
3196 my $netstr = print_net
( $net );
3197 print $outfd "net${netcount}: $netstr\n " ;
3200 } elsif (( $line =~ m/^(net\d+):\s*(\S+)\s*$/ ) && ( $opts ->{ unique
})) {
3201 my ( $id, $netstr ) = ( $1, $2 );
3202 my $net = parse_net
( $netstr );
3203 $net ->{ macaddr
} = PVE
:: Tools
:: random_ether_addr
() if $net ->{ macaddr
};
3204 $netstr = print_net
( $net );
3205 print $outfd " $id : $netstr\n " ;
3206 } elsif ( $line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/ ) {
3209 if ( $line =~ m/backup=no/ ) {
3210 print $outfd "# $line " ;
3211 } elsif ( $virtdev && $map ->{ $virtdev }) {
3212 my $di = PVE
:: QemuServer
:: parse_drive
( $virtdev, $value );
3213 $di ->{ file
} = $map ->{ $virtdev };
3214 $value = PVE
:: QemuServer
:: print_drive
( $vmid, $di );
3215 print $outfd " $virtdev : $value\n " ;
3233 restore_cleanup
( " $tmpdir/qmrestore .stat" ) if ! $opts ->{ info
};
3240 rename $tmpfn, $conffile ||
3241 die "unable to commit configuration file ' $conffile ' \n " ;