]>
git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer.pm
e0ec830e0d92d12b1b99d74310c7f7f6b5297c97
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" ;
141 my $keymaphash = PVE
:: Tools
:: kvmkeymaps
();
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
=> [ keys %$keymaphash ],
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." ,
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." ,
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 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_USB_DEVICES = 5 ;
393 my $MAX_UNUSED_DISKS = 8 ;
394 my $MAX_HOSTPCI_DEVICES = 2 ;
395 my $MAX_SERIAL_PORTS = 4 ;
396 my $MAX_PARALLEL_PORTS = 3 ;
398 my $nic_model_list = [ 'rtl8139' , 'ne2k_pci' , 'e1000' , 'pcnet' , 'virtio' ,
399 'ne2k_isa' , 'i82551' , 'i82557b' , 'i82559er' ];
400 my $nic_model_list_txt = join ( ' ' , sort @$nic_model_list );
405 type
=> 'string' , format
=> 'pve-qm-net' ,
406 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]" ,
407 description
=> <<EODESCR,
408 Specify network devices.
410 MODEL is one of: $nic_model_list_txt
412 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
413 automatically generated if not specified.
415 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
417 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'.
419 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
425 The DHCP server assign addresses to the guest starting from 10.0.2.15.
429 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-net" , $netdesc );
431 for ( my $i = 0 ; $i < $MAX_NETS ; $i++ ) {
432 $confdesc ->{ "net $i " } = $netdesc ;
439 type
=> 'string' , format
=> 'pve-qm-drive' ,
440 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
441 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to 3)." ,
443 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-ide" , $idedesc );
447 type
=> 'string' , format
=> 'pve-qm-drive' ,
448 typetext
=> '[volume=]volume,] [,media=cdrom|disk|block] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
449 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to 13)." ,
451 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-scsi" , $scsidesc );
455 type
=> 'string' , format
=> 'pve-qm-drive' ,
456 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,aio=native|threads]' ,
457 description
=> "Use volume as VIRTIO hard disk (n is 0 to 5)." ,
459 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-virtio" , $virtiodesc );
463 type
=> 'string' , format
=> 'pve-qm-usb-device' ,
464 typetext
=> 'host=HOSTUSBDEVICE' ,
465 description
=> <<EODESCR,
466 Configure an USB device (n is 0 to 4). This can be used to
467 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
469 'bus-port(.port)*' (decimal numbers) or
470 'vendor_id:product_id' (hexadeciaml numbers)
472 You can use the 'lsusb -t' command to list existing usb devices.
474 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
478 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-usb" , $usbdesc );
482 type
=> 'string' , format
=> 'pve-qm-hostpci' ,
483 typetext
=> "HOSTPCIDEVICE" ,
484 description
=> <<EODESCR,
485 Map host pci devices. HOSTPCIDEVICE syntax is:
487 'bus:dev.func' (hexadecimal numbers)
489 You can us the 'lspci' command to list existing pci devices.
491 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
493 Experimental: user reported problems with this option.
496 PVE
:: JSONSchema
:: register_standard_option
( "pve-qm-hostpci" , $hostpcidesc );
501 pattern
=> '/dev/ttyS\d+' ,
502 description
=> <<EODESCR,
503 Map host serial devices (n is 0 to 3).
505 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
507 Experimental: user reported problems with this option.
514 pattern
=> '/dev/parport\d+' ,
515 description
=> <<EODESCR,
516 Map host parallel devices (n is 0 to 2).
518 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
520 Experimental: user reported problems with this option.
524 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
525 $confdesc ->{ "parallel $i " } = $paralleldesc ;
528 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
529 $confdesc ->{ "serial $i " } = $serialdesc ;
532 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
533 $confdesc ->{ "hostpci $i " } = $hostpcidesc ;
536 for ( my $i = 0 ; $i < $MAX_IDE_DISKS ; $i++ ) {
537 $drivename_hash ->{ "ide $i " } = 1 ;
538 $confdesc ->{ "ide $i " } = $idedesc ;
541 for ( my $i = 0 ; $i < $MAX_SCSI_DISKS ; $i++ ) {
542 $drivename_hash ->{ "scsi $i " } = 1 ;
543 $confdesc ->{ "scsi $i " } = $scsidesc ;
546 for ( my $i = 0 ; $i < $MAX_VIRTIO_DISKS ; $i++ ) {
547 $drivename_hash ->{ "virtio $i " } = 1 ;
548 $confdesc ->{ "virtio $i " } = $virtiodesc ;
551 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
552 $confdesc ->{ "usb $i " } = $usbdesc ;
557 type
=> 'string' , format
=> 'pve-volume-id' ,
558 description
=> "Reference to unused volumes." ,
561 for ( my $i = 0 ; $i < $MAX_UNUSED_DISKS ; $i++ ) {
562 $confdesc ->{ "unused $i " } = $unuseddesc ;
565 my $kvm_api_version = 0 ;
569 return $kvm_api_version if $kvm_api_version ;
571 my $fh = IO
:: File-
> new ( "</dev/kvm" ) ||
574 if ( my $v = $fh -> ioctl ( KVM_GET_API_VERSION
(), 0 )) {
575 $kvm_api_version = $v ;
580 return $kvm_api_version ;
583 my $kvm_user_version ;
585 sub kvm_user_version
{
587 return $kvm_user_version if $kvm_user_version ;
589 $kvm_user_version = 'unknown' ;
591 my $tmp = `kvm -help 2>/dev/null` ;
593 if ( $tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?) / ) {
594 $kvm_user_version = $2 ;
597 return $kvm_user_version ;
601 my $kernel_has_vhost_net = - c
'/dev/vhost-net' ;
604 # order is important - used to autoselect boot disk
605 return (( map { "ide $_ " } ( 0 .. ( $MAX_IDE_DISKS - 1 ))),
606 ( map { "scsi $_ " } ( 0 .. ( $MAX_SCSI_DISKS - 1 ))),
607 ( map { "virtio $_ " } ( 0 .. ( $MAX_VIRTIO_DISKS - 1 ))));
610 sub valid_drivename
{
613 return defined ( $drivename_hash ->{ $dev });
618 return defined ( $confdesc ->{ $key });
622 return $nic_model_list ;
625 sub os_list_description
{
630 w2k
=> 'Windows 2000' ,
631 w2k3
=>, 'Windows 2003' ,
632 w2k8
=> 'Windows 2008' ,
633 wvista
=> 'Windows Vista' ,
640 sub disk_devive_info
{
643 die "unknown disk device format ' $dev '" if $dev !~ m/^(ide|scsi|virtio)(\d+)$/ ;
651 } elsif ( $bus eq 'scsi' ) {
655 my $controller = int ( $index / $maxdev );
656 my $unit = $index % $maxdev ;
659 return { bus
=> $bus, desc
=> uc ( $bus ) . " $controller : $unit " ,
660 controller
=> $controller, unit
=> $unit, index => $index };
664 sub qemu_drive_name
{
665 my ( $dev, $media ) = @_ ;
667 my $info = disk_devive_info
( $dev );
670 if (( $info ->{ bus
} eq 'ide' ) || ( $info ->{ bus
} eq 'scsi' )) {
671 $mediastr = ( $media eq 'cdrom' ) ?
"-cd" : "-hd" ;
672 return sprintf ( " %s%i%s%i " , $info ->{ bus
}, $info ->{ controller
},
673 $mediastr, $info ->{ unit
});
675 return sprintf ( " %s%i " , $info ->{ bus
}, $info ->{ index });
683 return $cdrom_path if $cdrom_path ;
685 return $cdrom_path = "/dev/cdrom" if - l
"/dev/cdrom" ;
686 return $cdrom_path = "/dev/cdrom1" if - l
"/dev/cdrom1" ;
687 return $cdrom_path = "/dev/cdrom2" if - l
"/dev/cdrom2" ;
691 my ( $storecfg, $vmid, $cdrom ) = @_ ;
693 if ( $cdrom eq 'cdrom' ) {
694 return get_cdrom_path
();
695 } elsif ( $cdrom eq 'none' ) {
697 } elsif ( $cdrom =~ m
|^/|) {
700 return PVE
:: Storage
:: path
( $storecfg, $cdrom );
704 # try to convert old style file names to volume IDs
705 sub filename_to_volume_id
{
706 my ( $vmid, $file, $media ) = @_ ;
708 if (!( $file eq 'none' || $file eq 'cdrom' ||
709 $file =~ m
|^ /dev/ .+| || $file =~ m/^([^:]+):(.+)$/ )) {
711 return undef if $file =~ m
|/|;
713 if ( $media && $media eq 'cdrom' ) {
714 $file = "local:iso/ $file " ;
716 $file = "local: $vmid/$file " ;
723 sub verify_media_type
{
724 my ( $opt, $vtype, $media ) = @_ ;
729 if ( $media eq 'disk' ) {
731 } elsif ( $media eq 'cdrom' ) {
734 die "internal error" ;
737 return if ( $vtype eq $etype );
739 raise_param_exc
({ $opt => "unexpected media type ( $vtype != $etype )" });
742 sub cleanup_drive_path
{
743 my ( $opt, $storecfg, $drive ) = @_ ;
745 # try to convert filesystem paths to volume IDs
747 if (( $drive ->{ file
} !~ m/^(cdrom|none)$/ ) &&
748 ( $drive ->{ file
} !~ m
|^ /dev/ .+|) &&
749 ( $drive ->{ file
} !~ m/^([^:]+):(.+)$/ ) &&
750 ( $drive ->{ file
} !~ m/^\d+$/ )) {
751 my ( $vtype, $volid ) = PVE
:: Storage
:: path_to_volume_id
( $storecfg, $drive ->{ file
});
752 raise_param_exc
({ $opt => "unable to associate path ' $drive ->{file}' to any storage" }) if ! $vtype ;
753 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $vtype eq 'iso' ;
754 verify_media_type
( $opt, $vtype, $drive ->{ media
});
755 $drive ->{ file
} = $volid ;
758 $drive ->{ media
} = 'cdrom' if ! $drive ->{ media
} && $drive ->{ file
} =~ m/^(cdrom|none)$/ ;
761 sub create_conf_nolock
{
762 my ( $vmid, $settings ) = @_ ;
764 my $filename = config_file
( $vmid );
766 die "configuration file ' $filename ' already exists \n " if - f
$filename ;
768 my $defaults = load_defaults
();
770 $settings ->{ name
} = "vm $vmid " if ! $settings ->{ name
};
771 $settings ->{ memory
} = $defaults ->{ memory
} if ! $settings ->{ memory
};
774 foreach my $opt ( keys %$settings ) {
775 next if ! $confdesc ->{ $opt };
777 my $value = $settings ->{ $opt };
780 $data .= " $opt : $value\n " ;
783 PVE
:: Tools
:: file_set_contents
( $filename, $data );
786 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
787 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
788 # [,aio=native|threads]
791 my ( $key, $data ) = @_ ;
795 # $key may be undefined - used to verify JSON parameters
796 if (! defined ( $key )) {
797 $res ->{ interface
} = 'unknown' ; # should not harm when used to verify parameters
799 } elsif ( $key =~ m/^([^\d]+)(\d+)$/ ) {
800 $res ->{ interface
} = $1 ;
806 foreach my $p ( split ( /,/ , $data )) {
807 next if $p =~ m/^\s*$/ ;
809 if ( $p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio)=(.+)$/ ) {
810 my ( $k, $v ) = ( $1, $2 );
812 $k = 'file' if $k eq 'volume' ;
814 return undef if defined $res ->{ $k };
818 if (! $res ->{ file
} && $p !~ m/=/ ) {
826 return undef if ! $res ->{ file
};
828 return undef if $res ->{ cache
} &&
829 $res ->{ cache
} !~ m/^(off|none|writethrough|writeback|unsafe)$/ ;
830 return undef if $res ->{ snapshot
} && $res ->{ snapshot
} !~ m/^(on|off)$/ ;
831 return undef if $res ->{ cyls
} && $res ->{ cyls
} !~ m/^\d+$/ ;
832 return undef if $res ->{ heads
} && $res ->{ heads
} !~ m/^\d+$/ ;
833 return undef if $res ->{ secs
} && $res ->{ secs
} !~ m/^\d+$/ ;
834 return undef if $res ->{ media
} && $res ->{ media
} !~ m/^(disk|cdrom)$/ ;
835 return undef if $res ->{ trans
} && $res ->{ trans
} !~ m/^(none|lba|auto)$/ ;
836 return undef if $res ->{ format
} && $res ->{ format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/ ;
837 return undef if $res ->{ rerror
} && $res ->{ rerror
} !~ m/^(ignore|report|stop)$/ ;
838 return undef if $res ->{ werror
} && $res ->{ werror
} !~ m/^(enospc|ignore|report|stop)$/ ;
839 return undef if $res ->{ backup
} && $res ->{ backup
} !~ m/^(yes|no)$/ ;
840 return undef if $res ->{ aio
} && $res ->{ aio
} !~ m/^(native|threads)$/ ;
842 if ( $res ->{ media
} && ( $res ->{ media
} eq 'cdrom' )) {
843 return undef if $res ->{ snapshot
} || $res ->{ trans
} || $res ->{ format
};
844 return undef if $res ->{ heads
} || $res ->{ secs
} || $res ->{ cyls
};
845 return undef if $res ->{ interface
} eq 'virtio' ;
848 # rerror does not work with scsi drives
849 if ( $res ->{ rerror
}) {
850 return undef if $res ->{ interface
} eq 'scsi' ;
856 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio) ;
859 my ( $vmid, $drive ) = @_ ;
862 foreach my $o ( @qemu_drive_options, 'backup' ) {
863 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
866 return " $drive ->{file} $opts " ;
869 sub print_drivedevice_full
{
870 my ( $storecfg, $vmid, $drive ) = @_ ;
875 if ( $drive ->{ interface
} eq 'virtio' ) {
876 my $pciaddr = print_pci_addr
( " $drive ->{interface} $drive ->{index}" );
877 $device = "virtio-blk-pci,drive=drive- $drive ->{interface} $drive ->{index},id= $drive ->{interface} $drive ->{index} $pciaddr " ;
878 } elsif ( $drive ->{ interface
} eq 'scsi' ) {
880 my $controller = int ( $drive ->{ index } / $maxdev );
881 my $unit = $drive ->{ index } % $maxdev ;
882 my $devicetype = 'hd' ;
883 if ( $drive ->{ media
}) {
884 if ( $drive ->{ media
} eq 'cdrom' ) {
886 } elsif ( $drive ->{ media
} eq 'block' ) {
887 $devicetype = 'block' ;
891 $device = "scsi- $devicetype,bus =scsi $controller .0,scsi-id= $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
892 } elsif ( $drive ->{ interface
} eq 'ide' ){
894 my $controller = int ( $drive ->{ index } / $maxdev );
895 my $unit = $drive ->{ index } % $maxdev ;
896 my $devicetype = ( $drive ->{ media
} && $drive ->{ media
} eq 'cdrom' ) ?
"cd" : "hd" ;
898 $device = "ide- $devicetype,bus =ide. $controller,unit = $unit,drive =drive- $drive ->{interface} $drive ->{index},id=device- $drive ->{interface} $drive ->{index}" ;
899 } elsif ( $drive ->{ interface
} eq 'usb' ) {
901 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
903 die "unsupported interface type" ;
909 sub print_drive_full
{
910 my ( $storecfg, $vmid, $drive ) = @_ ;
913 foreach my $o ( @qemu_drive_options ) {
914 $opts .= ", $o = $drive ->{ $o }" if $drive ->{ $o };
917 # use linux-aio by default (qemu default is threads)
918 $opts .= ",aio=native" if ! $drive ->{ aio
};
921 my $volid = $drive ->{ file
};
922 if ( drive_is_cdrom
( $drive )) {
923 $path = get_iso_path
( $storecfg, $vmid, $volid );
925 if ( $volid =~ m
|^/|) {
928 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
932 my $pathinfo = $path ?
"file= $path, " : '' ;
934 return "${pathinfo}if=none,id=drive- $drive ->{interface} $drive ->{index} $opts " ;
941 return $drive && $drive ->{ media
} && ( $drive ->{ media
} eq 'cdrom' );
948 return undef if ! $value ;
952 if ( $value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/ ) {
953 $res ->{ pciid
} = $value ;
961 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
967 foreach my $kvp ( split ( /,/ , $data )) {
969 if ( $kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i ) {
971 my $mac = uc ( $3 ) || PVE
:: Tools
:: random_ether_addr
();
972 $res ->{ model
} = $model ;
973 $res ->{ macaddr
} = $mac ;
974 } elsif ( $kvp =~ m/^bridge=(\S+)$/ ) {
976 } elsif ( $kvp =~ m/^rate=(\d+(\.\d+)?)$/ ) {
984 return undef if ! $res ->{ model
};
992 my $res = " $net ->{model}" ;
993 $res .= "= $net ->{macaddr}" if $net ->{ macaddr
};
994 $res .= ",bridge= $net ->{bridge}" if $net ->{ bridge
};
995 $res .= ",rate= $net ->{rate}" if $net ->{ rate
};
1000 sub add_random_macs
{
1001 my ( $settings ) = @_ ;
1003 foreach my $opt ( keys %$settings ) {
1004 next if $opt !~ m/^net(\d+)$/ ;
1005 my $net = parse_net
( $settings ->{ $opt });
1007 $settings ->{ $opt } = print_net
( $net );
1011 sub add_unused_volume
{
1012 my ( $config, $res, $volid ) = @_ ;
1015 for ( my $ind = $MAX_UNUSED_DISKS - 1 ; $ind >= 0 ; $ind --) {
1016 my $test = "unused $ind " ;
1017 if ( my $vid = $config ->{ $test }) {
1018 return if $vid eq $volid ; # do not add duplicates
1024 die "To many unused volume - please delete them first. \n " if ! $key ;
1026 $res ->{ $key } = $volid ;
1029 # fixme: remove all thos $noerr parameters?
1031 PVE
:: JSONSchema
:: register_format
( 'pve-qm-bootdisk' , \
& verify_bootdisk
);
1032 sub verify_bootdisk
{
1033 my ( $value, $noerr ) = @_ ;
1035 return $value if valid_drivename
( $value );
1037 return undef if $noerr ;
1039 die "invalid boot disk ' $value ' \n " ;
1042 PVE
:: JSONSchema
:: register_format
( 'pve-qm-net' , \
& verify_net
);
1044 my ( $value, $noerr ) = @_ ;
1046 return $value if parse_net
( $value );
1048 return undef if $noerr ;
1050 die "unable to parse network options \n " ;
1053 PVE
:: JSONSchema
:: register_format
( 'pve-qm-drive' , \
& verify_drive
);
1055 my ( $value, $noerr ) = @_ ;
1057 return $value if parse_drive
( undef , $value );
1059 return undef if $noerr ;
1061 die "unable to parse drive options \n " ;
1064 PVE
:: JSONSchema
:: register_format
( 'pve-qm-hostpci' , \
& verify_hostpci
);
1065 sub verify_hostpci
{
1066 my ( $value, $noerr ) = @_ ;
1068 return $value if parse_hostpci
( $value );
1070 return undef if $noerr ;
1072 die "unable to parse pci id \n " ;
1075 PVE
:: JSONSchema
:: register_format
( 'pve-qm-watchdog' , \
& verify_watchdog
);
1076 sub verify_watchdog
{
1077 my ( $value, $noerr ) = @_ ;
1079 return $value if parse_watchdog
( $value );
1081 return undef if $noerr ;
1083 die "unable to parse watchdog options \n " ;
1086 sub parse_watchdog
{
1089 return undef if ! $value ;
1093 foreach my $p ( split ( /,/ , $value )) {
1094 next if $p =~ m/^\s*$/ ;
1096 if ( $p =~ m/^(model=)?(i6300esb|ib700)$/ ) {
1098 } elsif ( $p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/ ) {
1099 $res ->{ action
} = $2 ;
1108 sub parse_usb_device
{
1111 return undef if ! $value ;
1113 my @dl = split ( /,/ , $value );
1117 foreach my $v ( @dl ) {
1118 if ( $v =~ m/^host=([0-9A-Fa-f]{4}):([0-9A-Fa-f]{4})$/ ) {
1120 $res ->{ vendorid
} = $1 ;
1121 $res ->{ productid
} = $2 ;
1122 } elsif ( $v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/ ) {
1124 $res ->{ hostbus
} = $1 ;
1125 $res ->{ hostport
} = $2 ;
1130 return undef if ! $found ;
1135 PVE
:: JSONSchema
:: register_format
( 'pve-qm-usb-device' , \
& verify_usb_device
);
1136 sub verify_usb_device
{
1137 my ( $value, $noerr ) = @_ ;
1139 return $value if parse_usb_device
( $value );
1141 return undef if $noerr ;
1143 die "unable to parse usb device \n " ;
1146 # add JSON properties for create and set function
1147 sub json_config_properties
{
1150 foreach my $opt ( keys %$confdesc ) {
1151 $prop ->{ $opt } = $confdesc ->{ $opt };
1158 my ( $key, $value ) = @_ ;
1160 die "unknown setting ' $key ' \n " if ! $confdesc ->{ $key };
1162 my $type = $confdesc ->{ $key }->{ type
};
1164 if (! defined ( $value )) {
1165 die "got undefined value \n " ;
1168 if ( $value =~ m/[\n\r]/ ) {
1169 die "property contains a line feed \n " ;
1172 if ( $type eq 'boolean' ) {
1173 return 1 if ( $value eq '1' ) || ( $value =~ m/^(on|yes|true)$/i );
1174 return 0 if ( $value eq '0' ) || ( $value =~ m/^(off|no|false)$/i );
1175 die "type check ('boolean') failed - got ' $value ' \n " ;
1176 } elsif ( $type eq 'integer' ) {
1177 return int ( $1 ) if $value =~ m/^(\d+)$/ ;
1178 die "type check ('integer') failed - got ' $value ' \n " ;
1179 } elsif ( $type eq 'string' ) {
1180 if ( my $fmt = $confdesc ->{ $key }->{ format
}) {
1181 if ( $fmt eq 'pve-qm-drive' ) {
1182 # special case - we need to pass $key to parse_drive()
1183 my $drive = parse_drive
( $key, $value );
1184 return $value if $drive ;
1185 die "unable to parse drive options \n " ;
1187 PVE
:: JSONSchema
:: check_format
( $fmt, $value );
1190 $value =~ s/^\"(.*)\"$/$1/ ;
1193 die "internal error"
1198 my ( $vmid, $code, @param ) = @_ ;
1200 my $filename = config_file_lock
( $vmid );
1202 my $res = lock_file
( $filename, 10 , $code, @param );
1209 sub cfs_config_path
{
1210 my ( $vmid, $node ) = @_ ;
1212 $node = $nodename if ! $node ;
1213 return "nodes/ $node/qemu -server/ $vmid .conf" ;
1216 sub check_iommu_support
{
1217 #fixme : need to check IOMMU support
1218 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1226 my ( $vmid, $node ) = @_ ;
1228 my $cfspath = cfs_config_path
( $vmid, $node );
1229 return "/etc/pve/ $cfspath " ;
1232 sub config_file_lock
{
1235 return " $lock_dir/lock - $vmid .conf" ;
1241 my $conf = config_file
( $vmid );
1242 utime undef , undef , $conf ;
1246 my ( $storecfg, $vmid, $settings, $conf, $default_storage ) = @_ ;
1251 foreach_drive
( $settings, sub {
1252 my ( $ds, $disk ) = @_ ;
1254 return if drive_is_cdrom
( $disk );
1256 my $file = $disk ->{ file
};
1258 if ( $file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/ ) {
1259 my $storeid = $2 || $default_storage ;
1261 my $defformat = PVE
:: Storage
:: storage_default_format
( $storecfg, $storeid );
1262 my $fmt = $disk ->{ format
} || $defformat ;
1263 syslog
( 'info' , "VM $vmid creating new disk - size is $size GB" );
1265 my $volid = PVE
:: Storage
:: vdisk_alloc
( $storecfg, $storeid, $vmid,
1266 $fmt, undef , $size*1024*1024 );
1268 $disk ->{ file
} = $volid ;
1269 delete $disk ->{ format
}; # no longer needed
1270 push @$vollist, $volid ;
1271 $settings ->{ $ds } = PVE
:: QemuServer
:: print_drive
( $vmid, $disk );
1274 if ( $disk ->{ file
} =~ m
|^ /dev/ .+|) {
1275 $path = $disk ->{ file
};
1277 $path = PVE
:: Storage
:: path
( $storecfg, $disk ->{ file
});
1279 if (!(- f
$path || - b
$path )) {
1280 die "image ' $path ' does not exists \n " ;
1283 PVE
:: QemuServer
:: vm_deviceadd
( $storecfg, $conf, $vmid, $ds, $disk ) if defined ( $conf );
1290 syslog
( 'err' , "VM $vmid creating disks failed" );
1291 foreach my $volid ( @$vollist ) {
1292 eval { PVE
:: Storage
:: vdisk_free
( $storecfg, $volid ); };
1302 my ( $storecfg, $vmid, $keep_empty_config ) = @_ ;
1304 my $conffile = config_file
( $vmid );
1306 my $conf = load_config
( $vmid );
1310 # only remove disks owned by this VM
1311 foreach_drive
( $conf, sub {
1312 my ( $ds, $drive ) = @_ ;
1314 return if drive_is_cdrom
( $drive );
1316 my $volid = $drive ->{ file
};
1317 return if ! $volid || $volid =~ m
|^/|;
1319 my ( $path, $owner ) = PVE
:: Storage
:: path
( $storecfg, $volid );
1320 return if ! $path || ! $owner || ( $owner != $vmid );
1322 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1325 if ( $keep_empty_config ) {
1326 PVE
:: Tools
:: file_set_contents
( $conffile, "memory: 128 \n " );
1331 # also remove unused disk
1333 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid );
1336 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1337 my ( $volid, $sid, $volname, $d ) = @_ ;
1338 PVE
:: Storage
:: vdisk_free
( $storecfg, $volid );
1348 sub load_diskinfo_old
{
1349 my ( $storecfg, $vmid, $conf ) = @_ ;
1355 foreach_drive
( $conf, sub {
1360 return if drive_is_cdrom
( $di );
1362 if ( $di ->{ file
} =~ m
|^ /dev/ .+|) {
1363 $info ->{ $di ->{ file
}}->{ size
} = PVE
:: Storage
:: file_size_info
( $di ->{ file
});
1365 push @$vollist, $di ->{ file
};
1370 my $dl = PVE
:: Storage
:: vdisk_list
( $storecfg, undef , $vmid, $vollist );
1372 PVE
:: Storage
:: foreach_volid
( $dl, sub {
1373 my ( $volid, $sid, $volname, $d ) = @_ ;
1374 $info ->{ $volid } = $d ;
1379 foreach my $ds ( keys %$res ) {
1380 my $di = $res ->{ $ds };
1382 $res ->{ $ds }->{ disksize
} = $info ->{ $di ->{ file
}} ?
1383 $info ->{ $di ->{ file
}}->{ size
} / ( 1024 * 1024 ) : 0 ;
1392 my $cfspath = cfs_config_path
( $vmid );
1394 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath );
1396 die "no such VM (' $vmid ') \n " if ! defined ( $conf );
1401 sub parse_vm_config
{
1402 my ( $filename, $raw ) = @_ ;
1404 return undef if ! defined ( $raw );
1407 digest
=> Digest
:: SHA1
:: sha1_hex
( $raw ),
1410 $filename =~ m
| /qemu-server/ ( \d
+) \
. conf
$|
1411 || die "got strange filename ' $filename '" ;
1415 while ( $raw && $raw =~ s/^(.*?)(\n|$)// ) {
1418 next if $line =~ m/^\#/ ;
1420 next if $line =~ m/^\s*$/ ;
1422 if ( $line =~ m/^(description):\s*(.*\S)\s*$/ ) {
1424 my $value = PVE
:: Tools
:: decode_text
( $2 );
1425 $res ->{ $key } = $value ;
1426 } elsif ( $line =~ m/^(args):\s*(.*\S)\s*$/ ) {
1429 $res ->{ $key } = $value ;
1430 } elsif ( $line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/ ) {
1433 eval { $value = check_type
( $key, $value ); };
1435 warn "vm $vmid - unable to parse value of ' $key ' - $@ " ;
1437 my $fmt = $confdesc ->{ $key }->{ format
};
1438 if ( $fmt && $fmt eq 'pve-qm-drive' ) {
1439 my $v = parse_drive
( $key, $value );
1440 if ( my $volid = filename_to_volume_id
( $vmid, $v ->{ file
}, $v ->{ media
})) {
1441 $v ->{ file
} = $volid ;
1442 $value = print_drive
( $vmid, $v );
1444 warn "vm $vmid - unable to parse value of ' $key ' \n " ;
1449 if ( $key eq 'cdrom' ) {
1450 $res ->{ ide2
} = $value ;
1452 $res ->{ $key } = $value ;
1458 # convert old smp to sockets
1459 if ( $res ->{ smp
} && ! $res ->{ sockets
}) {
1460 $res ->{ sockets
} = $res ->{ smp
};
1468 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1470 lock_config
( $vmid, & change_config_nolock
, $settings, $unset, $skiplock );
1473 sub change_config_nolock
{
1474 my ( $vmid, $settings, $unset, $skiplock ) = @_ ;
1478 $unset ->{ ide2
} = $unset ->{ cdrom
} if $unset ->{ cdrom
};
1480 check_lock
( $settings ) if ! $skiplock ;
1482 # we do not use 'smp' any longer
1483 if ( $settings ->{ sockets
}) {
1485 } elsif ( $settings ->{ smp
}) {
1486 $settings ->{ sockets
} = $settings ->{ smp
};
1490 my $new_volids = {};
1492 foreach my $key ( keys %$settings ) {
1493 next if $key eq 'digest' ;
1494 my $value = $settings ->{ $key };
1495 if ( $key eq 'description' ) {
1496 $value = PVE
:: Tools
:: encode_text
( $value );
1498 eval { $value = check_type
( $key, $value ); };
1499 die "unable to parse value of ' $key ' - $@ " if $@ ;
1500 if ( $key eq 'cdrom' ) {
1501 $res ->{ ide2
} = $value ;
1503 $res ->{ $key } = $value ;
1505 if ( valid_drivename
( $key )) {
1506 my $drive = PVE
:: QemuServer
:: parse_drive
( $key, $value );
1507 $new_volids ->{ $drive ->{ file
}} = 1 if $drive && $drive ->{ file
};
1511 my $filename = config_file
( $vmid );
1512 my $tmpfn = " $filename . $$ .tmp" ;
1514 my $fh = new IO
:: File
( $filename, "r" ) ||
1515 die "unable to read config for VM $vmid\n " ;
1517 my $werror = "unable to write config for VM $vmid\n " ;
1519 my $out = new IO
:: File
( $tmpfn, "w" ) || die $werror ;
1525 while ( my $line = < $fh >) {
1527 if (( $line =~ m/^\#/ ) || ( $line =~ m/^\s*$/ )) {
1528 die $werror unless print $out $line ;
1532 if ( $line =~ m/^([a-z][a-z_]*\d*):\s*(.*\S)\s*$/ ) {
1536 # remove 'unusedX' settings if we re-add a volume
1537 next if $key =~ m/^unused/ && $new_volids ->{ $value };
1539 # convert 'smp' to 'sockets'
1540 $key = 'sockets' if $key eq 'smp' ;
1542 next if $done ->{ $key };
1545 if ( defined ( $res ->{ $key })) {
1546 $value = $res ->{ $key };
1547 delete $res ->{ $key };
1549 if (! defined ( $unset ->{ $key })) {
1550 die $werror unless print $out " $key : $value\n " ;
1556 die "unable to parse config file: $line\n " ;
1559 foreach my $key ( keys %$res ) {
1561 if (! defined ( $unset ->{ $key })) {
1562 die $werror unless print $out " $key : $res ->{ $key } \n " ;
1577 if (! $out -> close ()) {
1578 $err = "close failed - $!\n " ;
1583 if (! rename ( $tmpfn, $filename )) {
1584 $err = "rename failed - $!\n " ;
1594 # we use static defaults from our JSON schema configuration
1595 foreach my $key ( keys %$confdesc ) {
1596 if ( defined ( my $default = $confdesc ->{ $key }->{ default })) {
1597 $res ->{ $key } = $default ;
1601 my $conf = PVE
:: Cluster
:: cfs_read_file
( 'datacenter.cfg' );
1602 $res ->{ keyboard
} = $conf ->{ keyboard
} if $conf ->{ keyboard
};
1608 my $vmlist = PVE
:: Cluster
:: get_vmlist
();
1610 return $res if ! $vmlist || ! $vmlist ->{ ids
};
1611 my $ids = $vmlist ->{ ids
};
1613 foreach my $vmid ( keys %$ids ) {
1614 my $d = $ids ->{ $vmid };
1615 next if ! $d ->{ node
} || $d ->{ node
} ne $nodename ;
1616 next if ! $d ->{ type
} || $d ->{ type
} ne 'qemu' ;
1617 $res ->{ $vmid }->{ exists } = 1 ;
1622 # test if VM uses local resources (to prevent migration)
1623 sub check_local_resources
{
1624 my ( $conf, $noerr ) = @_ ;
1628 $loc_res = 1 if $conf ->{ hostusb
}; # old syntax
1629 $loc_res = 1 if $conf ->{ hostpci
}; # old syntax
1631 foreach my $k ( keys %$conf ) {
1632 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/ ;
1635 die "VM uses local resources \n " if $loc_res && ! $noerr ;
1643 die "VM is locked ( $conf ->{lock}) \n " if $conf ->{ lock };
1647 my ( $pidfile, $pid ) = @_ ;
1649 my $fh = IO
:: File-
> new ( "/proc/ $pid/cmdline " , "r" );
1653 return undef if ! $line ;
1654 my @param = split ( /\0/ , $line );
1656 my $cmd = $param [ 0 ];
1657 return if ! $cmd || ( $cmd !~ m
| kvm
$|);
1659 for ( my $i = 0 ; $i < scalar ( @param ); $i++ ) {
1662 if (( $p eq '-pidfile' ) || ( $p eq '--pidfile' )) {
1663 my $p = $param [ $i+1 ];
1664 return 1 if $p && ( $p eq $pidfile );
1673 my ( $vmid, $nocheck ) = @_ ;
1675 my $filename = config_file
( $vmid );
1677 die "unable to find configuration file for VM $vmid - no such machine \n "
1678 if ! $nocheck && ! - f
$filename ;
1680 my $pidfile = pidfile_name
( $vmid );
1682 if ( my $fd = IO
:: File-
> new ( "< $pidfile " )) {
1687 my $mtime = $st -> mtime ;
1688 if ( $mtime > time ()) {
1689 warn "file ' $filename ' modified in future \n " ;
1692 if ( $line =~ m/^(\d+)$/ ) {
1694 if ( check_cmdline
( $pidfile, $pid )) {
1695 if ( my $pinfo = PVE
:: ProcFSTools
:: check_process_running
( $pid )) {
1707 my $vzlist = config_list
();
1709 my $fd = IO
:: Dir-
> new ( $var_run_tmpdir ) || return $vzlist ;
1711 while ( defined ( my $de = $fd -> read )) {
1712 next if $de !~ m/^(\d+)\.pid$/ ;
1714 next if ! defined ( $vzlist ->{ $vmid });
1715 if ( my $pid = check_running
( $vmid )) {
1716 $vzlist ->{ $vmid }->{ pid
} = $pid ;
1723 my $storage_timeout_hash = {};
1726 my ( $storecfg, $conf ) = @_ ;
1728 my $bootdisk = $conf ->{ bootdisk
};
1729 return undef if ! $bootdisk ;
1730 return undef if ! valid_drivename
( $bootdisk );
1732 return undef if ! $conf ->{ $bootdisk };
1734 my $drive = parse_drive
( $bootdisk, $conf ->{ $bootdisk });
1735 return undef if ! defined ( $drive );
1737 return undef if drive_is_cdrom
( $drive );
1739 my $volid = $drive ->{ file
};
1740 return undef if ! $volid ;
1746 if ( $volid =~ m
|^/|) {
1747 $path = $timeoutid = $volid ;
1749 $storeid = $timeoutid = PVE
:: Storage
:: parse_volume_id
( $volid );
1750 $path = PVE
:: Storage
:: path
( $storecfg, $volid );
1753 my $last_timeout = $storage_timeout_hash ->{ $timeoutid };
1754 if ( $last_timeout ) {
1755 if (( time () - $last_timeout ) < 30 ) {
1756 # skip storage with errors
1759 delete $storage_timeout_hash ->{ $timeoutid };
1762 my ( $size, $format, $used );
1764 ( $size, $format, $used ) = PVE
:: Storage
:: file_size_info
( $path, 1 );
1766 if (! defined ( $format )) {
1768 $storage_timeout_hash ->{ $timeoutid } = time ();
1772 return wantarray ?
( $size, $used ) : $size ;
1775 my $last_proc_pid_stat ;
1778 my ( $opt_vmid ) = @_ ;
1782 my $storecfg = PVE
:: Storage
:: config
();
1784 my $list = vzlist
();
1785 my ( $uptime ) = PVE
:: ProcFSTools
:: read_proc_uptime
( 1 );
1787 my $cpucount = $cpuinfo ->{ cpus
} || 1 ;
1789 foreach my $vmid ( keys %$list ) {
1790 next if $opt_vmid && ( $vmid ne $opt_vmid );
1792 my $cfspath = cfs_config_path
( $vmid );
1793 my $conf = PVE
:: Cluster
:: cfs_read_file
( $cfspath ) || {};
1796 $d ->{ pid
} = $list ->{ $vmid }->{ pid
};
1798 # fixme: better status?
1799 $d ->{ status
} = $list ->{ $vmid }->{ pid
} ?
'running' : 'stopped' ;
1801 my ( $size, $used ) = disksize
( $storecfg, $conf );
1802 if ( defined ( $size ) && defined ( $used )) {
1804 $d ->{ maxdisk
} = $size ;
1810 $d ->{ cpus
} = ( $conf ->{ sockets
} || 1 ) * ( $conf ->{ cores
} || 1 );
1811 $d ->{ cpus
} = $cpucount if $d ->{ cpus
} > $cpucount ;
1813 $d ->{ name
} = $conf ->{ name
} || "VM $vmid " ;
1814 $d ->{ maxmem
} = $conf ->{ memory
} ?
$conf ->{ memory
}*( 1024 * 1024 ) : 0 ;
1824 $d ->{ diskwrite
} = 0 ;
1829 my $netdev = PVE
:: ProcFSTools
:: read_proc_net_dev
();
1830 foreach my $dev ( keys %$netdev ) {
1831 next if $dev !~ m/^tap([1-9]\d*)i/ ;
1833 my $d = $res ->{ $vmid };
1836 $d ->{ netout
} += $netdev ->{ $dev }->{ receive
};
1837 $d ->{ netin
} += $netdev ->{ $dev }->{ transmit
};
1840 my $ctime = gettimeofday
;
1842 foreach my $vmid ( keys %$list ) {
1844 my $d = $res ->{ $vmid };
1845 my $pid = $d ->{ pid
};
1848 if ( my $fh = IO
:: File-
> new ( "/proc/ $pid/io " , "r" )) {
1850 while ( defined ( my $line = < $fh >)) {
1851 if ( $line =~ m/^([rw]char):\s+(\d+)$/ ) {
1856 $d ->{ diskread
} = $data ->{ rchar
} || 0 ;
1857 $d ->{ diskwrite
} = $data ->{ wchar
} || 0 ;
1860 my $pstat = PVE
:: ProcFSTools
:: read_proc_pid_stat
( $pid );
1861 next if ! $pstat ; # not running
1863 my $used = $pstat ->{ utime } + $pstat ->{ stime
};
1865 $d ->{ uptime
} = int (( $uptime - $pstat ->{ starttime
})/ $cpuinfo ->{ user_hz
});
1867 if ( $pstat ->{ vsize
}) {
1868 $d ->{ mem
} = int (( $pstat ->{ rss
}/ $pstat ->{ vsize
})* $d ->{ maxmem
});
1871 my $old = $last_proc_pid_stat ->{ $pid };
1873 $last_proc_pid_stat ->{ $pid } = {
1881 my $dtime = ( $ctime - $old ->{ time }) * $cpucount * $cpuinfo ->{ user_hz
};
1883 if ( $dtime > 1000 ) {
1884 my $dutime = $used - $old ->{ used
};
1886 $d ->{ cpu
} = (( $dutime/$dtime )* $cpucount ) / $d ->{ cpus
};
1887 $last_proc_pid_stat ->{ $pid } = {
1893 $d ->{ cpu
} = $old ->{ cpu
};
1901 my ( $conf, $func ) = @_ ;
1903 foreach my $ds ( keys %$conf ) {
1904 next if ! valid_drivename
( $ds );
1906 my $drive = parse_drive
( $ds, $conf ->{ $ds });
1909 & $func ( $ds, $drive );
1913 sub config_to_command
{
1914 my ( $storecfg, $vmid, $conf, $defaults, $migrate_uri ) = @_ ;
1918 my $kvmver = kvm_user_version
();
1919 my $vernum = 0 ; # unknown
1920 if ( $kvmver =~ m/^(\d+)\.(\d+)$/ ) {
1921 $vernum = $1*1000000+$2*1000 ;
1922 } elsif ( $kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/ ) {
1923 $vernum = $1*1000000+$2*1000+$3 ;
1926 die "detected old qemu-kvm binary ( $kvmver ) \n " if $vernum < 15000 ;
1928 my $have_ovz = - f
'/proc/vz/vestat' ;
1930 push @$cmd, '/usr/bin/kvm' ;
1932 push @$cmd, '-id' , $vmid ;
1936 my $socket = monitor_socket
( $vmid );
1937 push @$cmd, '-chardev' , "socket,id=monitor,path= $socket,server,nowait " ;
1938 push @$cmd, '-mon' , "chardev=monitor,mode=readline" ;
1940 $socket = vnc_socket
( $vmid );
1941 push @$cmd, '-vnc' , "unix: $socket,x509,password " ;
1943 push @$cmd, '-pidfile' , pidfile_name
( $vmid );
1945 push @$cmd, '-daemonize' ;
1947 push @$cmd, '-incoming' , $migrate_uri if $migrate_uri ;
1949 # include usb device config
1950 push @$cmd, '-readconfig' , '/usr/share/qemu-server/pve-usb.cfg' ;
1952 # enable absolute mouse coordinates (needed by vnc)
1953 my $tablet = defined ( $conf ->{ tablet
}) ?
$conf ->{ tablet
} : $defaults ->{ tablet
};
1954 push @$cmd, '-device' , 'usb-tablet,bus=ehci.0,port=6' if $tablet ;
1957 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
1958 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
1960 $pciaddr = print_pci_addr
( "hostpci $i " );
1961 push @$cmd, '-device' , "pci-assign,host= $d ->{pciid},id=hostpci $i$pciaddr " ;
1965 for ( my $i = 0 ; $i < $MAX_USB_DEVICES ; $i++ ) {
1966 my $d = parse_usb_device
( $conf ->{ "usb $i " });
1968 if ( $d ->{ vendorid
} && $d ->{ productid
}) {
1969 push @$cmd, '-device' , "usb-host,vendorid= $d ->{vendorid},productid= $d ->{productid}" ;
1970 } elsif ( defined ( $d ->{ hostbus
}) && defined ( $d ->{ hostport
})) {
1971 push @$cmd, '-device' , "usb-host,hostbus= $d ->{hostbus},hostport= $d ->{hostport}" ;
1976 for ( my $i = 0 ; $i < $MAX_SERIAL_PORTS ; $i++ ) {
1977 if ( my $path = $conf ->{ "serial $i " }) {
1978 die "no such serial device \n " if ! - c
$path ;
1979 push @$cmd, '-chardev' , "tty,id=serial $i,path = $path " ;
1980 push @$cmd, '-device' , "isa-serial,chardev=serial $i " ;
1985 for ( my $i = 0 ; $i < $MAX_PARALLEL_PORTS ; $i++ ) {
1986 if ( my $path = $conf ->{ "parallel $i " }) {
1987 die "no such parallel device \n " if ! - c
$path ;
1988 push @$cmd, '-chardev' , "parport,id=parallel $i,path = $path " ;
1989 push @$cmd, '-device' , "isa-parallel,chardev=parallel $i " ;
1993 my $vmname = $conf ->{ name
} || "vm $vmid " ;
1995 push @$cmd, '-name' , $vmname ;
1998 $sockets = $conf ->{ smp
} if $conf ->{ smp
}; # old style - no longer iused
1999 $sockets = $conf ->{ sockets
} if $conf ->{ sockets
};
2001 my $cores = $conf ->{ cores
} || 1 ;
2005 push @$cmd, '-smp' , "sockets= $sockets,cores = $cores " ;
2007 push @$cmd, '-cpu' , $conf ->{ cpu
} if $conf ->{ cpu
};
2009 push @$cmd, '-nodefaults' ;
2011 my $bootorder = $conf ->{ boot
} || $confdesc ->{ boot
}->{ default };
2012 push @$cmd, '-boot' , "menu=on,order= $bootorder " ;
2014 push @$cmd, '-no-acpi' if defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 ;
2016 push @$cmd, '-no-reboot' if defined ( $conf ->{ reboot
}) && $conf ->{ reboot
} == 0 ;
2018 my $vga = $conf ->{ vga
};
2020 if ( $conf ->{ ostype
} && ( $conf ->{ ostype
} eq 'win7' || $conf ->{ ostype
} eq 'w2k8' )) {
2027 push @$cmd, '-vga' , $vga if $vga ; # for kvm 77 and later
2030 my $tdf = defined ( $conf ->{ tdf
}) ?
$conf ->{ tdf
} : $defaults ->{ tdf
};
2031 push @$cmd, '-tdf' if $tdf ;
2033 my $nokvm = defined ( $conf ->{ kvm
}) && $conf ->{ kvm
} == 0 ?
1 : 0 ;
2035 if ( my $ost = $conf ->{ ostype
}) {
2036 # other, wxp, w2k, w2k3, w2k8, wvista, win7, l24, l26
2038 if ( $ost =~ m/^w/ ) { # windows
2039 push @$cmd, '-localtime' if ! defined ( $conf ->{ localtime });
2041 # use rtc-td-hack when acpi is enabled
2042 if (!( defined ( $conf ->{ acpi
}) && $conf ->{ acpi
} == 0 )) {
2043 push @$cmd, '-rtc-td-hack' ;
2054 push @$cmd, '-no-kvm' ;
2056 die "No accelerator found! \n " if ! $cpuinfo ->{ hvm
};
2059 push @$cmd, '-localtime' if $conf ->{ localtime };
2061 push @$cmd, '-startdate' , $conf ->{ startdate
} if $conf ->{ startdate
};
2063 push @$cmd, '-S' if $conf ->{ freeze
};
2065 # set keyboard layout
2066 my $kb = $conf ->{ keyboard
} || $defaults ->{ keyboard
};
2067 push @$cmd, '-k' , $kb if $kb ;
2070 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2071 #push @$cmd, '-soundhw', 'es1370';
2072 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2073 $pciaddr = print_pci_addr
( "balloon0" );
2074 push @$cmd, '-device' , "virtio-balloon-pci,id=balloon0 $pciaddr " if $conf ->{ balloon
};
2076 if ( $conf ->{ watchdog
}) {
2077 my $wdopts = parse_watchdog
( $conf ->{ watchdog
});
2078 $pciaddr = print_pci_addr
( "watchdog" );
2079 my $watchdog = $wdopts ->{ model
} || 'i6300esb' ;
2080 push @$cmd, '-device' , " $watchdog$pciaddr " ;
2081 push @$cmd, '-watchdog-action' , $wdopts ->{ action
} if $wdopts ->{ action
};
2085 my $scsicontroller = {};
2087 foreach_drive
( $conf, sub {
2088 my ( $ds, $drive ) = @_ ;
2090 if ( PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 )) {
2091 push @$vollist, $drive ->{ file
};
2094 $use_virtio = 1 if $ds =~ m/^virtio/ ;
2095 if ( $drive ->{ interface
} eq 'scsi' ) {
2097 my $controller = int ( $drive ->{ index } / $maxdev );
2098 $pciaddr = print_pci_addr
( "scsi $controller " );
2099 push @$cmd, '-device' , "lsi,id=scsi $controller$pciaddr " if ! $scsicontroller ->{ $controller };
2100 $scsicontroller ->{ $controller }= 1 ;
2102 my $tmp = print_drive_full
( $storecfg, $vmid, $drive );
2103 $tmp .= ",boot=on" if $conf ->{ bootdisk
} && ( $conf ->{ bootdisk
} eq $ds );
2104 push @$cmd, '-drive' , $tmp ;
2105 push @$cmd, '-device' , print_drivedevice_full
( $storecfg,$vmid, $drive );
2108 push @$cmd, '-m' , $conf ->{ memory
} || $defaults ->{ memory
};
2112 foreach my $k ( sort keys %$conf ) {
2113 next if $k !~ m/^net(\d+)$/ ;
2116 die "got strange net id ' $i ' \n " if $i >= ${ MAX_NETS
};
2118 if ( $conf ->{ "net $i " } && ( my $net = parse_net
( $conf ->{ "net $i " }))) {
2122 my $ifname = "tap${vmid}i $i " ;
2124 # kvm uses TUNSETIFF ioctl, and that limits ifname length
2125 die "interface name ' $ifname ' is too long (max 15 character) \n "
2126 if length ( $ifname ) >= 16 ;
2128 my $device = $net ->{ model
};
2129 my $vhostparam = '' ;
2130 if ( $net ->{ model
} eq 'virtio' ) {
2132 $device = 'virtio-net-pci' ;
2133 $vhostparam = ',vhost=on' if $kernel_has_vhost_net ;
2136 if ( $net ->{ bridge
}) {
2137 push @$cmd, '-netdev' , "type=tap,id=${k},ifname=${ifname},script=/var/lib/qemu-server/pve-bridge $vhostparam " ;
2139 push @$cmd, '-netdev' , "type=user,id=${k},hostname= $vmname " ;
2142 # qemu > 0.15 always try to boot from network - we disable that by
2143 # not loading the pxe rom file
2144 my $extra = (! $conf ->{ boot
} || ( $conf ->{ boot
} !~ m/n/ )) ?
2146 $pciaddr = print_pci_addr
( "${k}" );
2147 push @$cmd, '-device' , " $device,$ {extra}mac= $net ->{macaddr},netdev=${k} $pciaddr " ;
2151 push @$cmd, '-net' , 'none' if ! $foundnet ;
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 ) = @_ ;
2238 return if ! check_running
( $vmid ) || ! $conf ->{ hotplug
} || $conf ->{ $deviceid };
2240 if ( $deviceid =~ m/^(virtio)(\d+)$/ ) {
2242 my $drive = print_drive_full
( $storecfg, $vmid, $device );
2243 my $ret = vm_monitor_command
( $vmid, "drive_add auto $drive " );
2244 # If the command succeeds qemu prints: "OK"
2245 if ( $ret !~ m/OK/s ) {
2246 die "adding drive failed: $ret " ;
2249 my $devicefull = print_drivedevice_full
( $storecfg, $vmid, $device );
2250 $ret = vm_monitor_command
( $vmid, "device_add $devicefull " );
2252 # Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
2253 die 'error on hotplug device : $ret ' if $ret ne "" ;
2256 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2257 my $devices_list = vm_devices_list
( $vmid );
2258 return if defined ( $devices_list ->{ $deviceid });
2262 die "error on hotplug device $deviceid " ;
2266 my ( $vmid, $conf, $deviceid ) = @_ ;
2268 return if ! check_running
( $vmid ) || ! $conf ->{ hotplug
};
2270 die "can't unplug bootdisk" if $conf ->{ bootdisk
} eq $deviceid ;
2272 if ( $deviceid =~ m/^(virtio)(\d+)$/ ){
2274 my $ret = vm_monitor_command
( $vmid, "drive_del drive- $deviceid " );
2276 if ( $ret =~ m/Device \'.*?\' not found/s ) {
2277 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2279 elsif ( $ret ne "" ) {
2280 die "deleting drive $deviceid failed : $ret " ;
2283 $ret = vm_monitor_command
( $vmid, "device_del $deviceid " );
2285 die 'detaching device $deviceid failed : $ret ' if $ret ne "" ;
2289 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2290 for ( my $i = 0 ; $i <= 5 ; $i++ ) {
2291 my $devices_list = vm_devices_list
( $vmid );
2292 return if ! defined ( $devices_list ->{ $deviceid });
2295 die "error on hot-plugging device $deviceid " ;
2301 my ( $storecfg, $vmid, $statefile, $skiplock ) = @_ ;
2303 lock_config
( $vmid, sub {
2304 my $conf = load_config
( $vmid );
2306 check_lock
( $conf ) if ! $skiplock ;
2308 die "VM $vmid already running \n " if check_running
( $vmid );
2311 my $migrate_port = 0 ;
2314 if ( $statefile eq 'tcp' ) {
2315 $migrate_port = next_migrate_port
();
2316 $migrate_uri = "tcp:localhost:${migrate_port}" ;
2318 if (- f
$statefile ) {
2319 $migrate_uri = "exec:cat $statefile " ;
2321 warn "state file ' $statefile ' does not exist - doing normal startup \n " ;
2326 my $defaults = load_defaults
();
2328 my ( $cmd, $vollist ) = config_to_command
( $storecfg, $vmid, $conf, $defaults, $migrate_uri );
2330 for ( my $i = 0 ; $i < $MAX_HOSTPCI_DEVICES ; $i++ ) {
2331 my $d = parse_hostpci
( $conf ->{ "hostpci $i " });
2333 my $info = pci_device_info
( "0000: $d ->{pciid}" );
2334 die "IOMMU not present \n " if ! check_iommu_support
();
2335 die "no pci device info for device ' $d ->{pciid}' \n " if ! $info ;
2336 die "can't unbind pci device ' $d ->{pciid}' \n " if ! pci_dev_bind_to_stub
( $info );
2337 die "can't reset pci device ' $d ->{pciid}' \n " if ! pci_dev_reset
( $info );
2340 PVE
:: Storage
:: activate_volumes
( $storecfg, $vollist );
2342 eval { run_command
( $cmd, timeout
=> $migrate_uri ?
undef : 30 ); };
2344 die "start failed: $err " if $err ;
2348 if ( $statefile eq 'tcp' ) {
2349 print "migration listens on port $migrate_port\n " ;
2352 # fixme: send resume - is that necessary ?
2353 eval { vm_monitor_command
( $vmid, "cont" ); };
2357 # always set migrate speed (overwrite kvm default of 32m)
2358 # we set a very hight default of 8192m which is basically unlimited
2359 my $migrate_speed = $defaults ->{ migrate_speed
} || 8192 ;
2360 $migrate_speed = $conf ->{ migrate_speed
} || $migrate_speed ;
2362 my $cmd = "migrate_set_speed ${migrate_speed}m" ;
2363 vm_monitor_command
( $vmid, $cmd );
2366 if ( my $migrate_downtime =
2367 $conf ->{ migrate_downtime
} || $defaults ->{ migrate_downtime
}) {
2368 my $cmd = "migrate_set_downtime ${migrate_downtime}" ;
2369 eval { vm_monitor_command
( $vmid, $cmd ); };
2372 vm_balloonset
( $vmid, $conf ->{ balloon
}) if $conf ->{ balloon
};
2377 my ( $fh, $timeout ) = @_ ;
2379 my $sel = new IO
:: Select
;
2386 while ( scalar ( @ready = $sel -> can_read ( $timeout ))) {
2388 if ( $count = $fh -> sysread ( $buf, 8192 )) {
2389 if ( $buf =~ /^(.*)\(qemu\) $/s ) {
2396 if (! defined ( $count )) {
2403 die "monitor read timeout \n " if ! scalar ( @ready );
2408 sub vm_monitor_command
{
2409 my ( $vmid, $cmdstr, $nocheck ) = @_ ;
2414 die "VM $vmid not running \n " if ! check_running
( $vmid, $nocheck );
2416 my $sname = monitor_socket
( $vmid );
2418 my $sock = IO
:: Socket
:: UNIX-
> new ( Peer
=> $sname ) ||
2419 die "unable to connect to VM $vmid socket - $!\n " ;
2423 # hack: migrate sometime blocks the monitor (when migrate_downtime
2425 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2426 $timeout = 60 * 60 ; # 1 hour
2430 my $data = __read_avail
( $sock, $timeout );
2432 if ( $data !~ m/^QEMU\s+(\S+)\s+monitor\s/ ) {
2433 die "got unexpected qemu monitor banner \n " ;
2436 my $sel = new IO
:: Select
;
2439 if (! scalar ( my @ready = $sel -> can_write ( $timeout ))) {
2440 die "monitor write error - timeout" ;
2443 my $fullcmd = " $cmdstr\r " ;
2446 if (!( $b = $sock -> syswrite ( $fullcmd )) || ( $b != length ( $fullcmd ))) {
2447 die "monitor write error - $! " ;
2450 return if ( $cmdstr eq 'q' ) || ( $cmdstr eq 'quit' );
2454 if ( $cmdstr =~ m/^(info\s+migrate|migrate\s)/ ) {
2455 $timeout = 60 * 60 ; # 1 hour
2456 } elsif ( $cmdstr =~ m/^(eject|change)/ ) {
2457 $timeout = 60 ; # note: cdrom mount command is slow
2459 if ( $res = __read_avail
( $sock, $timeout )) {
2461 my @lines = split ( " \r ? \n " , $res );
2463 shift @lines if $lines [ 0 ] !~ m/^unknown command/ ; # skip echo
2465 $res = join ( " \n " , @lines );
2473 syslog
( "err" , "VM $vmid monitor command failed - $err " );
2480 sub vm_commandline
{
2481 my ( $storecfg, $vmid ) = @_ ;
2483 my $conf = load_config
( $vmid );
2485 my $defaults = load_defaults
();
2487 my $cmd = config_to_command
( $storecfg, $vmid, $conf, $defaults );
2489 return join ( ' ' , @$cmd );
2493 my ( $vmid, $skiplock ) = @_ ;
2495 lock_config
( $vmid, sub {
2497 my $conf = load_config
( $vmid );
2499 check_lock
( $conf ) if ! $skiplock ;
2501 vm_monitor_command
( $vmid, "system_reset" );
2505 sub get_vm_volumes
{
2509 foreach_drive
( $conf, sub {
2510 my ( $ds, $drive ) = @_ ;
2512 my ( $sid, $volname ) = PVE
:: Storage
:: parse_volume_id
( $drive ->{ file
}, 1 );
2515 my $volid = $drive ->{ file
};
2516 return if ! $volid || $volid =~ m
|^/|;
2518 push @$vollist, $volid ;
2524 sub vm_stop_cleanup
{
2525 my ( $storecfg, $vmid, $conf ) = @_ ;
2527 fairsched_rmnod
( $vmid ); # try to destroy group
2529 my $vollist = get_vm_volumes
( $conf );
2530 PVE
:: Storage
:: deactivate_volumes
( $storecfg, $vollist );
2534 my ( $storecfg, $vmid, $skiplock, $timeout ) = @_ ;
2536 $timeout = 60 if ! $timeout ;
2538 lock_config
( $vmid, sub {
2540 my $conf = load_config
( $vmid );
2542 check_lock
( $conf ) if ! $skiplock ;
2544 vm_monitor_command
( $vmid, "system_powerdown" );
2546 my $pid = check_running
( $vmid );
2548 if ( $pid && $timeout ) {
2549 print "waiting until VM $vmid stopps (PID $pid ) \n " ;
2552 while (( $count < $timeout ) && check_running
( $vmid )) {
2557 die "shutdown failed - got timeout \n " if check_running
( $vmid );
2560 vm_stop_cleanup
( $storecfg, $vmid, $conf );
2564 # Note: use $nockeck to skip tests if VM configuration file exists.
2565 # We need that when migration VMs to other nodes (files already moved)
2567 my ( $storecfg, $vmid, $skiplock, $nocheck, $timeout ) = @_ ;
2569 $timeout = 60 if ! $timeout ;
2571 lock_config
( $vmid, sub {
2573 my $pid = check_running
( $vmid, $nocheck );
2578 $conf = load_config
( $vmid );
2579 check_lock
( $conf ) if ! $skiplock ;
2582 eval { vm_monitor_command
( $vmid, "quit" , $nocheck ); };
2587 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2592 if ( $count >= $timeout ) {
2593 warn "VM still running - terminating now with SIGTERM \n " ;
2597 warn "VM quit failed - terminating now with SIGTERM \n " ;
2605 while (( $count < $timeout ) && check_running
( $vmid, $nocheck )) {
2610 if ( $count >= $timeout ) {
2611 warn "VM still running - terminating now with SIGKILL \n " ;
2616 vm_stop_cleanup
( $storecfg, $vmid, $conf ) if $conf ;
2621 my ( $vmid, $skiplock ) = @_ ;
2623 lock_config
( $vmid, sub {
2625 my $conf = load_config
( $vmid );
2627 check_lock
( $conf ) if ! $skiplock ;
2629 vm_monitor_command
( $vmid, "stop" );
2634 my ( $vmid, $skiplock ) = @_ ;
2636 lock_config
( $vmid, sub {
2638 my $conf = load_config
( $vmid );
2640 check_lock
( $conf ) if ! $skiplock ;
2642 vm_monitor_command
( $vmid, "cont" );
2647 my ( $vmid, $skiplock, $key ) = @_ ;
2649 lock_config
( $vmid, sub {
2651 my $conf = load_config
( $vmid );
2653 vm_monitor_command
( $vmid, "sendkey $key " );
2658 my ( $storecfg, $vmid, $skiplock ) = @_ ;
2660 lock_config
( $vmid, sub {
2662 my $conf = load_config
( $vmid );
2664 check_lock
( $conf ) if ! $skiplock ;
2666 if (! check_running
( $vmid )) {
2667 fairsched_rmnod
( $vmid ); # try to destroy group
2668 destroy_vm
( $storecfg, $vmid );
2670 die "VM $vmid is running - destroy failed \n " ;
2676 my ( $storecfg, $timeout ) = @_ ;
2678 $timeout = 3 * 60 if ! $timeout ;
2680 my $cleanuphash = {};
2682 my $vzlist = vzlist
();
2684 foreach my $vmid ( keys %$vzlist ) {
2685 next if ! $vzlist ->{ $vmid }->{ pid
};
2687 $cleanuphash ->{ $vmid } = 1 ;
2692 my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs \n " ;
2693 syslog
( 'info' , $msg );
2696 foreach my $vmid ( keys %$vzlist ) {
2697 next if ! $vzlist ->{ $vmid }->{ pid
};
2698 eval { vm_monitor_command
( $vmid, "system_powerdown" ); };
2703 my $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2705 while (( $try < $maxtries ) && $count ) {
2711 foreach my $vmid ( keys %$vzlist ) {
2712 next if ! $vzlist ->{ $vmid }->{ pid
};
2720 foreach my $vmid ( keys %$vzlist ) {
2721 next if ! $vzlist ->{ $vmid }->{ pid
};
2723 warn "VM $vmid still running - sending stop now \n " ;
2724 eval { vm_monitor_command
( $vmid, "quit" ); };
2729 $maxtries = int (( $timeout + $wt - 1 )/ $wt );
2731 while (( $try < $maxtries ) && $count ) {
2737 foreach my $vmid ( keys %$vzlist ) {
2738 next if ! $vzlist ->{ $vmid }->{ pid
};
2746 foreach my $vmid ( keys %$vzlist ) {
2747 next if ! $vzlist ->{ $vmid }->{ pid
};
2749 warn "VM $vmid still running - terminating now with SIGTERM \n " ;
2750 kill 15 , $vzlist ->{ $vmid }->{ pid
};
2755 # this is called by system shotdown scripts, so remaining
2756 # processes gets killed anyways (no need to send kill -9 here)
2760 foreach my $vmid ( keys %$cleanuphash ) {
2761 next if $vzlist ->{ $vmid }->{ pid
};
2763 my $conf = load_config
( $vmid );
2764 vm_stop_cleanup
( $storecfg, $vmid, $conf );
2769 $msg = "Qemu Server stopped \n " ;
2770 syslog
( 'info' , $msg );
2777 my ( $filename, $buf ) = @_ ;
2779 my $fh = IO
:: File-
> new ( $filename, "w" );
2780 return undef if ! $fh ;
2782 my $res = print $fh $buf ;
2789 sub pci_device_info
{
2794 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/ ;
2795 my ( $domain, $bus, $slot, $func ) = ( $1, $2, $3, $4 );
2797 my $irq = file_read_firstline
( " $pcisysfs/devices/$name/irq " );
2798 return undef if ! defined ( $irq ) || $irq !~ m/^\d+$/ ;
2800 my $vendor = file_read_firstline
( " $pcisysfs/devices/$name/vendor " );
2801 return undef if ! defined ( $vendor ) || $vendor !~ s/^0x// ;
2803 my $product = file_read_firstline
( " $pcisysfs/devices/$name/device " );
2804 return undef if ! defined ( $product ) || $product !~ s/^0x// ;
2809 product
=> $product,
2815 has_fl_reset
=> - f
" $pcisysfs/devices/$name/reset " || 0 ,
2824 my $name = $dev ->{ name
};
2826 my $fn = " $pcisysfs/devices/$name/reset " ;
2828 return file_write
( $fn, "1" );
2831 sub pci_dev_bind_to_stub
{
2834 my $name = $dev ->{ name
};
2836 my $testdir = " $pcisysfs/drivers/pci -stub/ $name " ;
2837 return 1 if - d
$testdir ;
2839 my $data = " $dev ->{vendor} $dev ->{product}" ;
2840 return undef if ! file_write
( " $pcisysfs/drivers/pci -stub/new_id" , $data );
2842 my $fn = " $pcisysfs/devices/$name/driver/unbind " ;
2843 if (! file_write
( $fn, $name )) {
2844 return undef if - f
$fn ;
2847 $fn = " $pcisysfs/drivers/pci -stub/bind" ;
2848 if (! - d
$testdir ) {
2849 return undef if ! file_write
( $fn, $name );
2855 sub print_pci_addr
{
2860 #addr1 : ide,parallel,serial (motherboard)
2861 #addr2 : first videocard
2862 balloon0
=> { bus
=> 0 , addr
=> 3 },
2863 watchdog
=> { bus
=> 0 , addr
=> 4 },
2864 scsi0
=> { bus
=> 0 , addr
=> 5 },
2865 scsi1
=> { bus
=> 0 , addr
=> 6 },
2866 virtio0
=> { bus
=> 0 , addr
=> 10 },
2867 virtio1
=> { bus
=> 0 , addr
=> 11 },
2868 virtio2
=> { bus
=> 0 , addr
=> 12 },
2869 virtio3
=> { bus
=> 0 , addr
=> 13 },
2870 virtio4
=> { bus
=> 0 , addr
=> 14 },
2871 virtio5
=> { bus
=> 0 , addr
=> 15 },
2872 hostpci0
=> { bus
=> 0 , addr
=> 16 },
2873 hostpci1
=> { bus
=> 0 , addr
=> 17 },
2874 net0
=> { bus
=> 0 , addr
=> 18 },
2875 net1
=> { bus
=> 0 , addr
=> 19 },
2876 net2
=> { bus
=> 0 , addr
=> 20 },
2877 net3
=> { bus
=> 0 , addr
=> 21 },
2878 net4
=> { bus
=> 0 , addr
=> 22 },
2879 net5
=> { bus
=> 0 , addr
=> 23 },
2880 #addr29 : usb-host (pve-usb.cfg)
2883 if ( defined ( $devices ->{ $id }->{ bus
}) && defined ( $devices ->{ $id }->{ addr
})) {
2884 my $addr = sprintf ( "0x %x " , $devices ->{ $id }->{ addr
});
2885 $res = ",bus=pci. $devices ->{ $id }->{bus},addr= $addr " ;
2892 my ( $vmid, $value ) = @_ ;
2894 vm_monitor_command
( $vmid, "balloon $value " );
2897 # vzdump restore implementaion
2899 sub archive_read_firstfile
{
2900 my $archive = shift ;
2902 die "ERROR: file ' $archive ' does not exist \n " if ! - f
$archive ;
2904 # try to detect archive type first
2905 my $pid = open ( TMP
, "tar tf ' $archive '|" ) ||
2906 die "unable to open file ' $archive ' \n " ;
2907 my $firstfile = < TMP
>;
2911 die "ERROR: archive contaions no data \n " if ! $firstfile ;
2917 sub restore_cleanup
{
2918 my $statfile = shift ;
2920 print STDERR
"starting cleanup \n " ;
2922 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
2923 while ( defined ( my $line = < $fd >)) {
2924 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
2927 if ( $volid =~ m
|^/|) {
2928 unlink $volid || die 'unlink failed \n ' ;
2930 my $cfg = cfs_read_file
( 'storage.cfg' );
2931 PVE
:: Storage
:: vdisk_free
( $cfg, $volid );
2933 print STDERR
"temporary volume ' $volid ' sucessfuly removed \n " ;
2935 print STDERR
"unable to cleanup ' $volid ' - $@ " if $@ ;
2937 print STDERR
"unable to parse line in statfile - $line " ;
2944 sub restore_archive
{
2945 my ( $archive, $vmid, $opts ) = @_ ;
2947 if ( $archive ne '-' ) {
2948 my $firstfile = archive_read_firstfile
( $archive );
2949 die "ERROR: file ' $archive ' dos not lock like a QemuServer vzdump backup \n "
2950 if $firstfile ne 'qemu-server.conf' ;
2953 my $tocmd = "/usr/lib/qemu-server/qmextract" ;
2955 $tocmd .= " --storage " . PVE
:: Tools
:: shellquote
( $opts ->{ storage
}) if $opts ->{ storage
};
2956 $tocmd .= ' --prealloc' if $opts ->{ prealloc
};
2957 $tocmd .= ' --info' if $opts ->{ info
};
2959 # tar option "xf" does not autodetect compression when read fron STDIN,
2960 # so we pipe to zcat
2961 my $cmd = "zcat -f|tar xf " . PVE
:: Tools
:: shellquote
( $archive ) . " " .
2962 PVE
:: Tools
:: shellquote
( "--to-command= $tocmd " );
2964 my $tmpdir = "/var/tmp/vzdumptmp $$ " ;
2967 local $ENV { VZDUMP_TMPDIR
} = $tmpdir ;
2968 local $ENV { VZDUMP_VMID
} = $vmid ;
2970 my $conffile = PVE
:: QemuServer
:: config_file
( $vmid );
2971 my $tmpfn = " $conffile . $$ .tmp" ;
2973 # disable interrupts (always do cleanups)
2974 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = sub {
2975 print STDERR
"got interrupt - ignored \n " ;
2980 local $SIG { INT
} = $SIG { TERM
} = $SIG { QUIT
} = $SIG { HUP
} = $SIG { PIPE
} = sub {
2981 die "interrupted by signal \n " ;
2984 if ( $archive eq '-' ) {
2985 print "extracting archive from STDIN \n " ;
2986 run_command
( $cmd, input
=> "<&STDIN" );
2988 print "extracting archive ' $archive ' \n " ;
2992 return if $opts ->{ info
};
2996 my $statfile = " $tmpdir/qmrestore .stat" ;
2997 if ( my $fd = IO
:: File-
> new ( $statfile, "r" )) {
2998 while ( defined ( my $line = < $fd >)) {
2999 if ( $line =~ m/vzdump:([^\s:]*):(\S+)$/ ) {
3000 $map ->{ $1 } = $2 if $1 ;
3002 print STDERR
"unable to parse line in statfile - $line\n " ;
3008 my $confsrc = " $tmpdir/qemu -server.conf" ;
3010 my $srcfd = new IO
:: File
( $confsrc, "r" ) ||
3011 die "unable to open file ' $confsrc ' \n " ;
3013 my $outfd = new IO
:: File
( $tmpfn, "w" ) ||
3014 die "unable to write config for VM $vmid\n " ;
3018 while ( defined ( my $line = < $srcfd >)) {
3019 next if $line =~ m/^\#vzdump\#/ ;
3020 next if $line =~ m/^lock:/ ;
3021 next if $line =~ m/^unused\d+:/ ;
3023 if (( $line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/ )) {
3024 # try to convert old 1.X settings
3025 my ( $id, $ind, $ethcfg ) = ( $1, $2, $3 );
3026 foreach my $devconfig ( PVE
:: Tools
:: split_list
( $ethcfg )) {
3027 my ( $model, $macaddr ) = split ( /\=/ , $devconfig );
3028 $macaddr = PVE
:: Tools
:: random_ether_addr
() if ! $macaddr || $opts ->{ unique
};
3031 bridge
=> "vmbr $ind " ,
3032 macaddr
=> $macaddr,
3034 my $netstr = print_net
( $net );
3035 print $outfd "net${netcount}: $netstr\n " ;
3038 } elsif (( $line =~ m/^(net\d+):\s*(\S+)\s*$/ ) && ( $opts ->{ unique
})) {
3039 my ( $id, $netstr ) = ( $1, $2 );
3040 my $net = parse_net
( $netstr );
3041 $net ->{ macaddr
} = PVE
:: Tools
:: random_ether_addr
() if $net ->{ macaddr
};
3042 $netstr = print_net
( $net );
3043 print $outfd " $id : $netstr\n " ;
3044 } elsif ( $line =~ m/^((ide|scsi|virtio)\d+):\s*(\S+)\s*$/ ) {
3047 if ( $line =~ m/backup=no/ ) {
3048 print $outfd "# $line " ;
3049 } elsif ( $virtdev && $map ->{ $virtdev }) {
3050 my $di = PVE
:: QemuServer
:: parse_drive
( $virtdev, $value );
3051 $di ->{ file
} = $map ->{ $virtdev };
3052 $value = PVE
:: QemuServer
:: print_drive
( $vmid, $di );
3053 print $outfd " $virtdev : $value\n " ;
3071 restore_cleanup
( " $tmpdir/qmrestore .stat" ) if ! $opts ->{ info
};
3078 rename $tmpfn, $conffile ||
3079 die "unable to commit configuration file ' $conffile ' \n " ;