mirror of
				https://git.proxmox.com/git/qemu-server
				synced 2025-11-04 14:09:12 +00:00 
			
		
		
		
	This reverts commit d4e1e1f862.
It's bogus, the VM start timeout is only starting to tick after we
started the TPM already...
		
	
			
		
			
				
	
	
		
			165 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
package PVE::QemuServer::Helpers;
 | 
						|
 | 
						|
use strict;
 | 
						|
use warnings;
 | 
						|
 | 
						|
use File::stat;
 | 
						|
 | 
						|
use PVE::INotify;
 | 
						|
use PVE::ProcFSTools;
 | 
						|
 | 
						|
use base 'Exporter';
 | 
						|
our @EXPORT_OK = qw(
 | 
						|
min_version
 | 
						|
config_aware_timeout
 | 
						|
);
 | 
						|
 | 
						|
my $nodename = PVE::INotify::nodename();
 | 
						|
 | 
						|
# Paths and directories
 | 
						|
 | 
						|
our $var_run_tmpdir = "/var/run/qemu-server";
 | 
						|
mkdir $var_run_tmpdir;
 | 
						|
 | 
						|
sub qmp_socket {
 | 
						|
    my ($vmid, $qga) = @_;
 | 
						|
    my $sockettype = $qga ? 'qga' : 'qmp';
 | 
						|
    return "${var_run_tmpdir}/$vmid.$sockettype";
 | 
						|
}
 | 
						|
 | 
						|
sub pidfile_name {
 | 
						|
    my ($vmid) = @_;
 | 
						|
    return "${var_run_tmpdir}/$vmid.pid";
 | 
						|
}
 | 
						|
 | 
						|
sub vnc_socket {
 | 
						|
    my ($vmid) = @_;
 | 
						|
    return "${var_run_tmpdir}/$vmid.vnc";
 | 
						|
}
 | 
						|
 | 
						|
# Parse the cmdline of a running kvm/qemu process and return arguments as hash
 | 
						|
sub parse_cmdline {
 | 
						|
    my ($pid) = @_;
 | 
						|
 | 
						|
    my $fh = IO::File->new("/proc/$pid/cmdline", "r");
 | 
						|
    if (defined($fh)) {
 | 
						|
	my $line = <$fh>;
 | 
						|
	$fh->close;
 | 
						|
	return if !$line;
 | 
						|
	my @param = split(/\0/, $line);
 | 
						|
 | 
						|
	my $cmd = $param[0];
 | 
						|
	return if !$cmd || ($cmd !~ m|kvm$| && $cmd !~ m@(?:^|/)qemu-system-[^/]+$@);
 | 
						|
 | 
						|
	my $phash = {};
 | 
						|
	my $pending_cmd;
 | 
						|
	for (my $i = 0; $i < scalar (@param); $i++) {
 | 
						|
	    my $p = $param[$i];
 | 
						|
	    next if !$p;
 | 
						|
 | 
						|
	    if ($p =~ m/^--?(.*)$/) {
 | 
						|
		if ($pending_cmd) {
 | 
						|
		    $phash->{$pending_cmd} = {};
 | 
						|
		}
 | 
						|
		$pending_cmd = $1;
 | 
						|
	    } elsif ($pending_cmd) {
 | 
						|
		$phash->{$pending_cmd} = { value => $p };
 | 
						|
		$pending_cmd = undef;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	return $phash;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
sub vm_running_locally {
 | 
						|
    my ($vmid) = @_;
 | 
						|
 | 
						|
    my $pidfile = pidfile_name($vmid);
 | 
						|
 | 
						|
    if (my $fd = IO::File->new("<$pidfile")) {
 | 
						|
	my $st = stat($fd);
 | 
						|
	my $line = <$fd>;
 | 
						|
	close($fd);
 | 
						|
 | 
						|
	my $mtime = $st->mtime;
 | 
						|
	if ($mtime > time()) {
 | 
						|
	    warn "file '$pidfile' modified in future\n";
 | 
						|
	}
 | 
						|
 | 
						|
	if ($line =~ m/^(\d+)$/) {
 | 
						|
	    my $pid = $1;
 | 
						|
	    my $cmdline = parse_cmdline($pid);
 | 
						|
	    if ($cmdline && defined($cmdline->{pidfile}) && $cmdline->{pidfile}->{value}
 | 
						|
		&& $cmdline->{pidfile}->{value} eq $pidfile) {
 | 
						|
		if (my $pinfo = PVE::ProcFSTools::check_process_running($pid)) {
 | 
						|
		    return $pid;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
sub min_version {
 | 
						|
    my ($verstr, $major, $minor, $pve) = @_;
 | 
						|
 | 
						|
    if ($verstr =~ m/^(\d+)\.(\d+)(?:\.(\d+))?(?:\+pve(\d+))?/) {
 | 
						|
	return 1 if version_cmp($1, $major, $2, $minor, $4, $pve) >= 0;
 | 
						|
	return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    die "internal error: cannot check version of invalid string '$verstr'";
 | 
						|
}
 | 
						|
 | 
						|
# gets in pairs the versions you want to compares, i.e.:
 | 
						|
# ($a-major, $b-major, $a-minor, $b-minor, $a-extra, $b-extra, ...)
 | 
						|
# returns 0 if same, -1 if $a is older than $b, +1 if $a is newer than $b
 | 
						|
sub version_cmp {
 | 
						|
    my @versions = @_;
 | 
						|
 | 
						|
    my $size = scalar(@versions);
 | 
						|
 | 
						|
    return 0 if $size == 0;
 | 
						|
 | 
						|
    if ($size & 1) {
 | 
						|
	my (undef, $fn, $line) = caller(0);
 | 
						|
	die "cannot compare odd count of versions, called from $fn:$line\n";
 | 
						|
    }
 | 
						|
 | 
						|
    for (my $i = 0; $i < $size; $i += 2) {
 | 
						|
	my ($a, $b) = splice(@versions, 0, 2);
 | 
						|
	$a //= 0;
 | 
						|
	$b //= 0;
 | 
						|
 | 
						|
	return 1 if $a > $b;
 | 
						|
	return -1 if $a < $b;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
sub config_aware_timeout {
 | 
						|
    my ($config, $is_suspended) = @_;
 | 
						|
    my $memory = $config->{memory};
 | 
						|
    my $timeout = 30;
 | 
						|
 | 
						|
    # Based on user reported startup time for vm with 512GiB @ 4-5 minutes
 | 
						|
    if (defined($memory) && $memory > 30720) {
 | 
						|
	$timeout = int($memory/1024);
 | 
						|
    }
 | 
						|
 | 
						|
    if ($is_suspended && $timeout < 300) {
 | 
						|
	$timeout = 300;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($config->{hugepages} && $timeout < 150) {
 | 
						|
	$timeout = 150;
 | 
						|
    }
 | 
						|
 | 
						|
    return $timeout;
 | 
						|
}
 | 
						|
 | 
						|
1;
 |