Skip to content

Commit

Permalink
Merge pull request #3092 from canonical/delete-snapshot-cli
Browse files Browse the repository at this point in the history
[snapshots] Delete snapshot cli and daemon placeholder
  • Loading branch information
ricab committed Aug 29, 2023
2 parents e90a326 + 2ff8f24 commit 709ed4b
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 46 deletions.
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 @@ mp::InstanceNames cmd::add_instance_names(const mp::ArgParser* parser, const std
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());

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 @@ std::string cmd::Delete::name() const

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 @@ mp::ParseCode cmd::Delete::parse_args(mp::ArgParser* parser)
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;
}

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 @@ -1148,6 +1148,23 @@ bool is_ipv4_valid(const std::string& ipv4)
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());
}

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 @@ -1715,14 +1732,7 @@ try // clang-format on

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 @@ -2183,12 +2193,13 @@ try // clang-format on
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 @@ -2204,6 +2215,24 @@ try // clang-format on

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
2 changes: 1 addition & 1 deletion src/rpc/multipass.proto
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ message RestartReply {
}

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

0 comments on commit 709ed4b

Please sign in to comment.