App-FuguVM

 view release on metacpan or  search on metacpan

lib/App/FuguVM/Guest.pm  view on Meta::CPAN

	my $state  = $self->{state};
	my $arch   = $self->_arch;

	my @cmd = ( $arch->qemu_binary );

	# Set the machine type of the architecture. Select the
	# accelerator by the host capability.
	push @cmd, '-M', $arch->machine;
	push @cmd, $self->_accel_args;

	# Memory and CPU
	push @cmd, '-m',   $config->{memory} // MEMORY_DEFAULT;
	push @cmd, '-smp', CPU_COUNT;

	# EFI firmware of the architecture. Both machines boot through
	# EFI, so a start without a firmware file cannot work. Fail
	# with a message rather than boot into the wrong firmware.
	my $firmware = $self->_find_efi_firmware;
	if ( !defined $firmware ) {
		$self->{log}->error(
			sprintf( "No EFI firmware for %s guests found",
				$self->_arch->name ) );
		return;
	}
	my @args = $self->_firmware_args($firmware);
	return unless @args;
	push @cmd, @args;

	# The main disk with the safe cache mode. The writethrough mode
	# syncs on each write.
	my $disk_path = $state->disk_path;
	push @cmd, '-drive',
	    "file=$disk_path,format=qcow2,if=virtio,cache=writethrough";

	# Boot image (CD-ROM) for installation
	push @cmd, $self->_media_args($boot_image);

	# Network with port forwarding, and the serial console on
	# telnet
	my $console_port = $state->get_runtime->{console_port};
	push @cmd, $self->_network_args;
	push @cmd, $self->_serial_args;

	# QMP control socket
	my $qmp_path = $self->_qmp_socket_path;
	unlink $qmp_path if -S $qmp_path;
	push @cmd, '-qmp', "unix:$qmp_path,server,nowait";

	# PID file for reliable tracking
	push @cmd, '-pidfile', $state->vm_pidfile->path;

	# No graphics display (headless)
	push @cmd, '-display', 'none';

	# Use Fugu::Process to spawn QEMU
	my $log_file = $state->vm_state_dir . '/qemu.log';
	my $result   = Fugu::Process->spawn_command(
		cmd       => \@cmd,
		daemonize => 1,
		stdout    => $log_file,
		stderr    => $log_file,
	);

	return unless $result->{success};

	# Wait until QEMU writes the PID file
	my $pid = Fugu::Timeout::wait_until(
		5, 0.1,
		sub {
			my $qemu_pid = $state->get_vm_pid;
			return $qemu_pid
			    if defined $qemu_pid
			    && Fugu::Process->is_alive($qemu_pid);
			return;
		} );

	unless ( defined $pid ) {
		$self->_dump_qemu_log($log_file);
		return;
	}

	# Arm the crash detection: was_unclean_shutdown reports true
	# when the state says running and the process is gone.
	$state->mark_running;

	# Make sure that QEMU accepts console connections before the
	# installer tries to attach. A QEMU that exited at startup, for
	# example with a bad accelerator or missing firmware, leaves the
	# port closed. This check fails fast with the QEMU log, not with
	# a long telnet timeout later.
	if ( defined $boot_image
		&& !$self->_wait_console_ready( $console_port, 30 ) )
	{
		$self->{log}
		    ->error( 'QEMU console port %d not listening after start',
			$console_port );
		$self->_dump_qemu_log($log_file);
		return;
	}

	return $pid;
}

# $self->_media_args($boot_image):
#	Return the QEMU arguments of the install media, or an empty
#	list when no media is attached. An autoinstall reboots
#	itself, and the miniroot is still attached. -no-reboot makes
#	the reboot an exit, so the guest cannot install a second
#	time.
sub _media_args ( $self, $boot_image = undef )
{
	return () if !defined $boot_image;

	my @args =
	    ( '-drive', "file=$boot_image,format=raw,if=virtio,readonly=on" );
	push @args, '-no-reboot'
	    if ( $self->{config}{install_mode} // '' ) eq 'autoinstall';

	return @args;
}



( run in 0.973 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )