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 )