Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions include/multipass/exceptions/start_exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,22 @@ namespace multipass
class StartException : public std::runtime_error
{
public:
StartException(const std::string& instance_name, const std::string& what)
: runtime_error(what), instance_name(instance_name)
StartException(const std::string& instance_name, const std::string& what, bool expected = false)
: runtime_error(what), instance_name(instance_name), expected{expected}
{
}

std::string name() const
{
return instance_name;
}
bool was_intentional() const
{
return expected;
}

private:
const std::string instance_name;
bool expected;
};
} // namespace multipass
2 changes: 2 additions & 0 deletions include/multipass/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ bool process_log_on_error(const QString& program,
multipass::logging::Level level = multipass::logging::Level::debug,
const int timeout = 30000);

bool expects_shutdown_from_cloud_init(const YAML::Node& user_data_config);

// networking helpers
void validate_server_address(const std::string& value);
bool valid_hostname(const std::string& name_string);
Expand Down
7 changes: 7 additions & 0 deletions src/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3592,6 +3592,13 @@ error_string mp::Daemon::async_wait_for_ssh_and_start_mounts_for(
persist_instances();
}
}
catch (const StartException& e)
{
if (!std::is_same_v<Reply, LaunchReply> || !e.was_intentional())
{
fmt::format_to(std::back_inserter(errors), "{}", e.what());
Comment on lines +3595 to +3599
}
}
Comment thread
tobe2098 marked this conversation as resolved.
catch (const std::exception& e)
{
fmt::format_to(std::back_inserter(errors), "{}", e.what());
Expand Down
14 changes: 7 additions & 7 deletions src/platform/backends/hyperv/hyperv_virtual_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ mp::HyperVVirtualMachine::HyperVVirtualMachine(const VirtualMachineDescription&
{
if (!power_shell->run({"Get-VM", "-Name", name}))
{
auto mem_size =
QString::number(desc.mem_size.in_bytes()); /* format documented in `Help(New-VM)`, under
auto mem_size = QString::number(
desc.mem_size.in_bytes()); /* format documented in `Help(New-VM)`, under
`-MemoryStartupBytes` option; */

power_shell->easy_run({QString("$switch = Get-VMSwitch -Id %1").arg(default_switch_guid)},
Expand Down Expand Up @@ -219,8 +219,8 @@ mp::HyperVVirtualMachine::HyperVVirtualMachine(const std::string& source_vm_name
// 'C:\ProgramData\Multipass\data\vault\instances\vm1-clone1\vm1\Virtual
// Machines\7735327A-A22F-4926-95A1-51757D650BB7.vmcx' -Copy -GenerateNewId -VhdDestinationPath
// "C:\ProgramData\Multipass\data\vault\instances\vm1-clone1\"
const fs::path exported_vm_path =
fs::path{dest_instance_dir.toStdString()} / fs::path{source_vm_name};
const fs::path exported_vm_path = fs::path{dest_instance_dir.toStdString()} /
fs::path{source_vm_name};
const fs::path vmcx_file_path = locate_vmcx_file(exported_vm_path);
// The next step needs to rename the instance, so we need to store the instance variable
// $imported_vm from the Import-VM step. Because we can not use vm name to uniquely identify the
Expand Down Expand Up @@ -248,8 +248,8 @@ mp::HyperVVirtualMachine::HyperVVirtualMachine(const std::string& source_vm_name
"Could not remove the cloud-init-config.iso file from the virtual machine");
// 5. Add-VMDvdDrive -VMName vm1-clone1 -Path
// 'C:\ProgramData\Multipass\data\vault\instances\vm1-clone1\cloud-init-config.iso'
const fs::path dest_cloud_init_path =
fs::path{dest_instance_dir.toStdString()} / cloud_init_file_name;
const fs::path dest_cloud_init_path = fs::path{dest_instance_dir.toStdString()} /
cloud_init_file_name;
power_shell->easy_run({"Add-VMDvdDrive",
"-VMName",
name,
Expand Down Expand Up @@ -350,7 +350,7 @@ void mp::HyperVVirtualMachine::start()
{
state = instance_state_for(power_shell.get(), name);
handle_state_update();
throw StartException{vm_name, output_err.toStdString()};
throw StartException{vm_name, output_err.toStdString(), false};
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/platform/backends/shared/base_virtual_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,14 @@ void mp::BaseVirtualMachine::detect_aborted_start()

std::string msg{"Instance shutdown during start"};
if (!saved_error_msg.empty())
{
msg += ": " + saved_error_msg;
saved_error_msg.clear();
}

saved_error_msg.clear();
throw StartException(vm_name, msg);
throw StartException(vm_name,
msg,
mpu::expects_shutdown_from_cloud_init(desc.user_data_config));
Comment thread
tobe2098 marked this conversation as resolved.
}
}

Expand Down
36 changes: 25 additions & 11 deletions src/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,11 +582,11 @@ std::pair<std::string, std::string> mp::utils::get_path_split(mp::SSHSession& se
{
std::string absolute{get_resolved_target(session, target)};

std::string existing =
MP_UTILS.run_in_ssh_session(session,
fmt::format("sudo /bin/bash -c 'P={:?}; while [ ! -d \"$P/\" "
"]; do P=\"${{P%/*}}\"; done; echo $P/'",
absolute));
std::string existing = MP_UTILS.run_in_ssh_session(
session,
fmt::format("sudo /bin/bash -c 'P={:?}; while [ ! -d \"$P/\" "
"]; do P=\"${{P%/*}}\"; done; echo $P/'",
absolute));

return {existing,
QDir(QString::fromStdString(existing))
Expand Down Expand Up @@ -690,11 +690,25 @@ auto mp::utils::find_bridge_with(const std::vector<mp::NetworkInterfaceInfo>& ne
const std::string& bridge_type)
-> std::optional<mp::NetworkInterfaceInfo>
{
const auto it =
std::find_if(std::cbegin(networks),
std::cend(networks),
[&target_network, &bridge_type](const NetworkInterfaceInfo& info) {
return info.type == bridge_type && info.has_link(target_network);
});
const auto it = std::find_if(std::cbegin(networks),
std::cend(networks),
[&target_network, &bridge_type](const NetworkInterfaceInfo& info) {
return info.type == bridge_type &&
info.has_link(target_network);
});
return it == std::cend(networks) ? std::nullopt : std::make_optional(*it);
}

bool mp::utils::expects_shutdown_from_cloud_init(const YAML::Node& user_data_config)
{
if (user_data_config["power_state"])
{
auto ps = user_data_config["power_state"];
if (ps["mode"])
{
std::string mode = ps["mode"].as<std::string>();
return (mode == "poweroff" || mode == "halt");
Comment on lines +702 to +710
}
}
return false;
}
Loading