Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[snapshots] Delete snapshot cli and daemon placeholder #3092

Merged
merged 5 commits into from
Jun 27, 2023
Merged
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
19 changes: 19 additions & 0 deletions src/client/cli/cmd/common_cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@
return instance_names;
}

std::vector<mp::InstanceSnapshotPair> cmd::add_instance_and_snapshot_names(const mp::ArgParser* parser)
{
std::vector<mp::InstanceSnapshotPair> instance_snapshot_names;
instance_snapshot_names.reserve(parser->positionalArguments().count());

for (const auto& arg : parser->positionalArguments())
{
mp::InstanceSnapshotPair inst_snap_name;
auto index = arg.indexOf('.');
inst_snap_name.set_instance_name(arg.left(index).toStdString());
if (index >= 0)
inst_snap_name.set_snapshot_name(arg.right(arg.length() - index - 1).toStdString());

Check warning on line 90 in src/client/cli/cmd/common_cli.cpp

View check run for this annotation

Codecov / codecov/patch

src/client/cli/cmd/common_cli.cpp#L90

Added line #L90 was not covered by tests

instance_snapshot_names.push_back(inst_snap_name);
}

return instance_snapshot_names;
}

mp::ParseCode cmd::handle_format_option(const mp::ArgParser* parser, mp::Formatter** chosen_formatter,
std::ostream& cerr)
{
Expand Down
1 change: 1 addition & 0 deletions src/client/cli/cmd/common_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const QString format_option_name{"format"};
ParseCode check_for_name_and_all_option_conflict(const ArgParser* parser, std::ostream& cerr, bool allow_empty = false);
InstanceNames add_instance_names(const ArgParser* parser);
InstanceNames add_instance_names(const ArgParser* parser, const std::string& default_name);
std::vector<InstanceSnapshotPair> add_instance_and_snapshot_names(const ArgParser* parser);
ParseCode handle_format_option(const ArgParser* parser, Formatter** chosen_formatter, std::ostream& cerr);
std::string instance_action_message_for(const InstanceNames& instance_names, const std::string& action_name);
ReturnCode run_cmd(const QStringList& args, const ArgParser* parser, std::ostream& cout, std::ostream& cerr);
Expand Down
34 changes: 21 additions & 13 deletions src/client/cli/cmd/delete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,24 +75,25 @@

QString cmd::Delete::short_help() const
{
return QStringLiteral("Delete instances");
return QStringLiteral("Delete instances and snapshots");
}

QString cmd::Delete::description() const
{
return QStringLiteral("Delete instances, to be purged with the \"purge\" command,\n"
"or recovered with the \"recover\" command.");
return QStringLiteral(
"Delete instances and snapshots. Instances can be purged immediately or later on,"
"with the \"purge\" command. Until they are purged, instances can be recovered"
"with the \"recover\" command. Snapshots cannot be recovered after deletion and must be purged at once.");
}

mp::ParseCode cmd::Delete::parse_args(mp::ArgParser* parser)
{
parser->addPositionalArgument("name", "Names of instances to delete", "<name> [<name> ...]");
parser->addPositionalArgument("name", "Names of instances and snapshots to delete",
"<instance>[.snapshot] [<instance>[.snapshot] ...]");

QCommandLineOption all_option(all_option_name, "Delete all instances");
parser->addOption(all_option);

QCommandLineOption purge_option({"p", "purge"}, "Purge instances immediately");
parser->addOption(purge_option);
QCommandLineOption all_option(all_option_name, "Delete all instances and snapshots");
QCommandLineOption purge_option({"p", "purge"}, "Purge specified instances and snapshots immediately");
parser->addOptions({all_option, purge_option});

auto status = parser->commandParse(this);
if (status != ParseCode::Ok)
Expand All @@ -102,11 +103,18 @@
if (parse_code != ParseCode::Ok)
return parse_code;

request.mutable_instance_names()->CopyFrom(add_instance_names(parser));

if (parser->isSet(purge_option))
request.set_purge(parser->isSet(purge_option));
for (const auto& item : add_instance_and_snapshot_names(parser))
{
request.set_purge(true);
if (item.has_snapshot_name() && !request.purge())
{
cerr << "Snapshots can only be purged (after deletion, they cannot be recovered). Please use the `--purge` "
"flag if that is what you want.\n";
return mp::ParseCode::CommandLineError;

Check warning on line 113 in src/client/cli/cmd/delete.cpp

View check run for this annotation

Codecov / codecov/patch

src/client/cli/cmd/delete.cpp#L111-L113

Added lines #L111 - L113 were not covered by tests
}

request.add_instances_snapshots()->CopyFrom(item);
}

return status;
}
23 changes: 0 additions & 23 deletions src/client/cli/cmd/info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,6 @@
namespace mp = multipass;
namespace cmd = multipass::cmd;

namespace
{
// TODO@snapshots move this to common_cli once required by other commands
std::vector<mp::InstanceSnapshotPair> add_instance_and_snapshot_names(const mp::ArgParser* parser)
{
std::vector<mp::InstanceSnapshotPair> instance_snapshot_names;
instance_snapshot_names.reserve(parser->positionalArguments().count());

for (const auto& arg : parser->positionalArguments())
{
mp::InstanceSnapshotPair inst_snap_name;
auto index = arg.indexOf('.');
inst_snap_name.set_instance_name(arg.left(index).toStdString());
if (index >= 0)
inst_snap_name.set_snapshot_name(arg.right(arg.length() - index - 1).toStdString());

instance_snapshot_names.push_back(inst_snap_name);
}

return instance_snapshot_names;
}
} // namespace

mp::ReturnCode cmd::Info::run(mp::ArgParser* parser)
{
auto ret = parse_args(parser);
Expand Down
47 changes: 38 additions & 9 deletions src/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,23 @@
return true;
}

template <typename Instances>
std::unordered_map<std::string, std::unordered_set<std::string>> map_snapshots_to_instances(const Instances& instances)
{
std::unordered_map<std::string, std::unordered_set<std::string>> instance_snapshots_map;

for (const auto& it : instances)
{
if (it.snapshot_name().empty())
instance_snapshots_map[it.instance_name()];
else if (const auto& entry = instance_snapshots_map.find(it.instance_name());
entry == instance_snapshots_map.end() || !entry->second.empty())
instance_snapshots_map[it.instance_name()].insert(it.snapshot_name());

Check warning on line 1174 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1172-L1174

Added lines #L1172 - L1174 were not covered by tests
}

return instance_snapshots_map;
}

void add_aliases(google::protobuf::RepeatedPtrField<mp::FindReply_ImageInfo>* container, const std::string& remote_name,
const mp::VMImageInfo& info, const std::string& default_remote)
{
Expand Down Expand Up @@ -1695,11 +1712,11 @@
{
mp::SSHSession session{vm.ssh_hostname(), vm.ssh_port(), vm_specs.ssh_username, *config->ssh_key_provider};

instance_info->set_load(mpu::run_in_ssh_session(session, "cat /proc/loadavg | cut -d ' ' -f1-3"));
instance_info->set_memory_usage(
mpu::run_in_ssh_session(session, "free -b | grep 'Mem:' | awk '{printf $3}'"));

Check warning on line 1717 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1715-L1717

Added lines #L1715 - L1717 were not covered by tests
info->set_memory_total(mpu::run_in_ssh_session(session, "free -b | grep 'Mem:' | awk '{printf $2}'"));
instance_info->set_disk_usage(

Check warning on line 1719 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1719

Added line #L1719 was not covered by tests
mpu::run_in_ssh_session(session, "df -t ext4 -t vfat --total -B1 --output=used | tail -n 1"));
info->set_disk_total(
mpu::run_in_ssh_session(session, "df -t ext4 -t vfat --total -B1 --output=size | tail -n 1"));
Expand All @@ -1709,60 +1726,60 @@
auto all_ipv4 = vm.get_all_ipv4(*config->ssh_key_provider);

if (is_ipv4_valid(management_ip))
instance_info->add_ipv4(management_ip);

Check warning on line 1729 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1729

Added line #L1729 was not covered by tests
else if (all_ipv4.empty())
instance_info->add_ipv4("N/A");

Check warning on line 1731 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1731

Added line #L1731 was not covered by tests

for (const auto& extra_ipv4 : all_ipv4)
if (extra_ipv4 != management_ip)
instance_info->add_ipv4(extra_ipv4);

Check warning on line 1735 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1735

Added line #L1735 was not covered by tests

auto current_release =
mpu::run_in_ssh_session(session, "cat /etc/os-release | grep 'PRETTY_NAME' | cut -d \\\" -f2");
instance_info->set_current_release(!current_release.empty() ? current_release : original_release);

Check warning on line 1739 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1739

Added line #L1739 was not covered by tests
}
return grpc::Status::OK;
};

std::unordered_map<std::string, std::unordered_set<std::string>> instance_snapshots_map;
auto fetch_snapshot_overview = [&](VirtualMachine& vm) {
fmt::memory_buffer errors;
const auto& name = vm.vm_name;

Check warning on line 1747 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1745-L1747

Added lines #L1745 - L1747 were not covered by tests

auto get_snapshot_info = [&](std::shared_ptr<const Snapshot> snapshot) {
auto overview = response.mutable_snapshot_overview()->add_overview();
auto fundamentals = overview->mutable_fundamentals();

Check warning on line 1751 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1749-L1751

Added lines #L1749 - L1751 were not covered by tests

overview->set_instance_name(name);
fundamentals->set_snapshot_name(snapshot->get_name());
fundamentals->set_parent(snapshot->get_parent_name());
fundamentals->set_comment(snapshot->get_comment());

Check warning on line 1756 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1753-L1756

Added lines #L1753 - L1756 were not covered by tests
// TODO@snapshots populate snapshot creation time once available
};

Check warning on line 1758 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1758

Added line #L1758 was not covered by tests

if (const auto& it = instance_snapshots_map.find(name);
it == instance_snapshots_map.end() || it->second.empty())

Check warning on line 1761 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1760-L1761

Added lines #L1760 - L1761 were not covered by tests
{
for (const auto& snapshot : vm.view_snapshots())
get_snapshot_info(snapshot);

Check warning on line 1764 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1763-L1764

Added lines #L1763 - L1764 were not covered by tests
}
else
{
for (const auto& snapshot : it->second)

Check warning on line 1768 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1768

Added line #L1768 was not covered by tests
{
try
{
get_snapshot_info(vm.get_snapshot(snapshot));

Check warning on line 1772 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1772

Added line #L1772 was not covered by tests
}
catch (const std::out_of_range&)

Check warning on line 1774 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1774

Added line #L1774 was not covered by tests
{
add_fmt_to(errors, "snapshot \"{}\" does not exist", snapshot);

Check warning on line 1776 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1776

Added line #L1776 was not covered by tests
}
}
}

return grpc_status_for(errors);
};

Check warning on line 1782 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L1781-L1782

Added lines #L1781 - L1782 were not covered by tests

auto [instance_selection, status] =
select_instances_and_react(operative_instances, deleted_instances, request->instances_snapshots(),
Expand All @@ -1770,14 +1787,7 @@

if (status.ok())
{
for (const auto& it : request->instances_snapshots())
{
if (it.snapshot_name().empty())
instance_snapshots_map[it.instance_name()];
else if (const auto& entry = instance_snapshots_map.find(it.instance_name());
entry == instance_snapshots_map.end() || !entry->second.empty())
instance_snapshots_map[it.instance_name()].insert(it.snapshot_name());
}
instance_snapshots_map = map_snapshots_to_instances(request->instances_snapshots());

// TODO@snapshots change cmd logic to include detailed snapshot info output
auto cmd =
Expand Down Expand Up @@ -2245,12 +2255,13 @@
DeleteReply response;

auto [instance_selection, status] =
select_instances_and_react(operative_instances, deleted_instances, request->instance_names().instance_name(),
select_instances_and_react(operative_instances, deleted_instances, request->instances_snapshots(),
InstanceGroup::All, require_existing_instances_reaction);

if (status.ok())
{
const bool purge = request->purge();
auto instance_snapshots_map = map_snapshots_to_instances(request->instances_snapshots());

for (const auto& vm_it : instance_selection.operative_selection)
{
Expand All @@ -2266,6 +2277,24 @@

if (purge)
{
// TODO@snapshots call method to delete snapshots
/*
if (const auto& it = instance_snapshots_map.find(name);
it == instance_snapshots_map.end() || it.second.empty())
{
// Delete instance and snapshots
// release_resources(name);
// response.add_purged_instances(name);
}
else
{
for (const auto& snapshot_name : instance_snapshots_map[name])
{
// Delete snapshot
}
}
*/

release_resources(name);
response.add_purged_instances(name);
}
Expand Down Expand Up @@ -2491,111 +2520,111 @@
status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));
}

void mp::Daemon::snapshot(const mp::SnapshotRequest* request,

Check warning on line 2523 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2523

Added line #L2523 was not covered by tests
grpc::ServerReaderWriterInterface<SnapshotReply, SnapshotRequest>* server,
std::promise<grpc::Status>* status_promise)
try
{
mpl::ClientLogger<SnapshotReply, SnapshotRequest> logger{mpl::level_from(request->verbosity_level()),
*config->logger, server};

Check warning on line 2529 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2529

Added line #L2529 was not covered by tests

const auto& instance_name = request->instance();
auto [instance_trail, status] = find_instance_and_react(operative_instances, deleted_instances, instance_name,
require_operative_instances_reaction);

Check warning on line 2533 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2531-L2533

Added lines #L2531 - L2533 were not covered by tests

if (status.ok())

Check warning on line 2535 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2535

Added line #L2535 was not covered by tests
{
assert(instance_trail.index() == 0);
auto* vm_ptr = std::get<0>(instance_trail)->second.get();
assert(vm_ptr);

Check warning on line 2539 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2537-L2539

Added lines #L2537 - L2539 were not covered by tests

using St = VirtualMachine::State;
if (auto state = vm_ptr->current_state(); state != St::off && state != St::stopped)
return status_promise->set_value(
grpc::Status{grpc::INVALID_ARGUMENT, "Multipass can only take snapshots of stopped instances."});

Check warning on line 2544 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2542-L2544

Added lines #L2542 - L2544 were not covered by tests

auto snapshot_name = request->snapshot();
if (!snapshot_name.empty() && !mp::utils::valid_hostname(snapshot_name))
return status_promise->set_value(
grpc::Status{grpc::INVALID_ARGUMENT, fmt::format(R"(Invalid snapshot name: "{}".)", snapshot_name)});

Check warning on line 2549 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2546-L2549

Added lines #L2546 - L2549 were not covered by tests

const auto spec_it = vm_instance_specs.find(instance_name);
assert(spec_it != vm_instance_specs.end() && "missing instance specs");

Check warning on line 2552 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2551-L2552

Added lines #L2551 - L2552 were not covered by tests

SnapshotReply reply;

Check warning on line 2554 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2554

Added line #L2554 was not covered by tests

{
const auto snapshot = vm_ptr->take_snapshot(instance_directory(instance_name, *config), spec_it->second,
snapshot_name, request->comment());

Check warning on line 2558 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2557-L2558

Added lines #L2557 - L2558 were not covered by tests

reply.set_snapshot(snapshot->get_name());

Check warning on line 2560 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2560

Added line #L2560 was not covered by tests
}

server->Write(reply);

Check warning on line 2563 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2563

Added line #L2563 was not covered by tests
}

status_promise->set_value(status);

Check warning on line 2566 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2566

Added line #L2566 was not covered by tests
}
catch (const SnapshotNameTaken& e)

Check warning on line 2568 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2568

Added line #L2568 was not covered by tests
{
status_promise->set_value(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, e.what(), ""));

Check warning on line 2570 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2570

Added line #L2570 was not covered by tests
}
catch (const std::exception& e)

Check warning on line 2572 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2572

Added line #L2572 was not covered by tests
{
status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));

Check warning on line 2574 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2574

Added line #L2574 was not covered by tests
}

void mp::Daemon::restore(const mp::RestoreRequest* request,

Check warning on line 2577 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2577

Added line #L2577 was not covered by tests
grpc::ServerReaderWriterInterface<RestoreReply, RestoreRequest>* server,
std::promise<grpc::Status>* status_promise)
try
{
mpl::ClientLogger<RestoreReply, RestoreRequest> logger{mpl::level_from(request->verbosity_level()), *config->logger,
server};

Check warning on line 2583 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2582-L2583

Added lines #L2582 - L2583 were not covered by tests

RestoreReply reply;
const auto& instance_name = request->instance();
auto [instance_trail, status] = find_instance_and_react(operative_instances, deleted_instances, instance_name,
require_operative_instances_reaction);

Check warning on line 2588 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2585-L2588

Added lines #L2585 - L2588 were not covered by tests

if (status.ok())

Check warning on line 2590 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2590

Added line #L2590 was not covered by tests
{
assert(instance_trail.index() == 0);
auto* vm_ptr = std::get<0>(instance_trail)->second.get();
assert(vm_ptr);

Check warning on line 2594 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2592-L2594

Added lines #L2592 - L2594 were not covered by tests

using St = VirtualMachine::State;
if (auto state = vm_ptr->current_state(); state != St::off && state != St::stopped)
return status_promise->set_value(
grpc::Status{grpc::INVALID_ARGUMENT, "Multipass can only restore snapshots of stopped instances."});

Check warning on line 2599 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2597-L2599

Added lines #L2597 - L2599 were not covered by tests

auto spec_it = vm_instance_specs.find(instance_name);
assert(spec_it != vm_instance_specs.end() && "missing instance specs");

Check warning on line 2602 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2601-L2602

Added lines #L2601 - L2602 were not covered by tests

const auto& vm_dir = instance_directory(instance_name, *config);
if (!request->destructive())

Check warning on line 2605 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2604-L2605

Added lines #L2604 - L2605 were not covered by tests
{
reply_msg(server, fmt::format("Taking snapshot before restoring {}", instance_name));

Check warning on line 2607 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2607

Added line #L2607 was not covered by tests

const auto snapshot = vm_ptr->take_snapshot(vm_dir, spec_it->second, "",
fmt::format("Before restoring {}", request->snapshot()));

Check warning on line 2610 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2609-L2610

Added lines #L2609 - L2610 were not covered by tests

reply_msg(server, fmt::format("Snapshot taken: {}.{}", instance_name, snapshot->get_name()),

Check warning on line 2612 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2612

Added line #L2612 was not covered by tests
/* sticky = */ true);
}

reply_msg(server, "Restoring snapshot");
vm_ptr->restore_snapshot(vm_dir, request->snapshot(), spec_it->second);
persist_instances();

Check warning on line 2618 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2616-L2618

Added lines #L2616 - L2618 were not covered by tests

server->Write(reply);

Check warning on line 2620 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2620

Added line #L2620 was not covered by tests
}

status_promise->set_value(status);

Check warning on line 2623 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2623

Added line #L2623 was not covered by tests
}
catch (const std::exception& e)

Check warning on line 2625 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2625

Added line #L2625 was not covered by tests
{
status_promise->set_value(grpc::Status(grpc::StatusCode::INTERNAL, e.what(), ""));

Check warning on line 2627 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2627

Added line #L2627 was not covered by tests
}

void mp::Daemon::on_shutdown()
Expand Down Expand Up @@ -3099,9 +3128,9 @@
{
for (auto& [_, mount] : mounts[name])
{
if (!mount->is_mount_managed_by_backend())

Check warning on line 3131 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3131

Added line #L3131 was not covered by tests
{
mount->deactivate(/*force=*/true);

Check warning on line 3133 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3133

Added line #L3133 was not covered by tests
}
}
}
Expand Down Expand Up @@ -3280,15 +3309,15 @@
}

template <typename Reply, typename Request>
void mp::Daemon::reply_msg(grpc::ServerReaderWriterInterface<Reply, Request>* server, std::string&& msg, bool sticky)

Check warning on line 3312 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3312

Added line #L3312 was not covered by tests
{
Reply reply{};
if (sticky)
reply.set_reply_message(fmt::format("{}\n", std::forward<decltype(msg)>(msg)));

Check warning on line 3316 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3314-L3316

Added lines #L3314 - L3316 were not covered by tests
else
reply.set_reply_message(std::forward<decltype(msg)>(msg));

Check warning on line 3318 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3318

Added line #L3318 was not covered by tests

server->Write(reply);

Check warning on line 3320 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3320

Added line #L3320 was not covered by tests
}

grpc::Status mp::Daemon::migrate_from_hyperkit(grpc::ServerReaderWriterInterface<SetReply, SetRequest>* server)
Expand Down Expand Up @@ -3361,26 +3390,26 @@
for (const auto& [vm_name, vm_specs] : vm_instance_specs)
{
if (deleted_instances.find(vm_name) != deleted_instances.cend())
reply_msg(server, fmt::format("Cannot migrate {}: instance is deleted", vm_name), /* sticky = */ true);

Check warning on line 3393 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3393

Added line #L3393 was not covered by tests
else if (auto st = operative_instances[vm_name]->current_state();
st != VirtualMachine::State::off && st != VirtualMachine::State::stopped)
reply_msg(server, fmt::format("Cannot migrate {}: instance needs to be stopped", vm_name),

Check warning on line 3396 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3396

Added line #L3396 was not covered by tests
/* sticky = */ true);
else if (auto key = QString::fromStdString(vm_name);
qemu_instances_json.contains(key) || qemu_instance_images_json.contains(key))
reply_msg(server, fmt::format("Cannot migrate {}: name already taken by a qemu instance", vm_name),

Check warning on line 3400 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3400

Added line #L3400 was not covered by tests
/* sticky = */ true);
else if (const auto vm_image = fetch_image_for(vm_name, config->factory->fetch_type(), *config->vault);
vm_image.original_release.find("16.04") != std::string::npos &&
!vm_image.image_path.contains("uefi", Qt::CaseInsensitive))
reply_msg(server,
fmt::format("Cannot migrate {}: old Xenial instances (launched before 1.11) cannot be migrated :/"

Check warning on line 3406 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3405-L3406

Added lines #L3405 - L3406 were not covered by tests
" consider extracting your data manually.",
vm_name),
/* sticky = */ true);
else
{
reply_msg(server, fmt::format("Migrating instance from hyperkit to qemu: {}", vm_name));

Check warning on line 3412 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3412

Added line #L3412 was not covered by tests

// Copy instance image to qemu vault
const auto target_directory = fmt::format("{}/{}", qemu_instances_dir, vm_name);
Expand Down Expand Up @@ -3521,6 +3550,6 @@
fmt::join(instances_migrated, separator), hint_delete);
}

reply_msg(server, std::move(outcome_summary), /* sticky = */ true);

Check warning on line 3553 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L3553

Added line #L3553 was not covered by tests
return ret;
}
2 changes: 1 addition & 1 deletion src/rpc/multipass.proto
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ message RestartReply {
}

message DeleteRequest {
InstanceNames instance_names = 1;
repeated InstanceSnapshotPair instances_snapshots = 1;
bool purge = 2;
int32 verbosity_level = 3;
}
Expand Down
Loading