Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
37 changes: 37 additions & 0 deletions include/multipass/new_release_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef MULTIPASS_NEW_RELEASE_INFO_H
#define MULTIPASS_NEW_RELEASE_INFO_H

#include <QMetaType>
#include <QUrl>

namespace multipass
{

struct NewReleaseInfo
{
QString version;
QUrl url;
};

} // namespace multipass

Q_DECLARE_METATYPE(multipass::NewReleaseInfo)

#endif // MULTIPASS_NEW_RELEASE_INFO_H
4 changes: 3 additions & 1 deletion include/multipass/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define MULTIPASS_PLATFORM_H

#include <multipass/logging/logger.h>
#include <multipass/update_prompt.h>
#include <multipass/virtual_machine_factory.h>

#include <libssh/sftp.h>
Expand All @@ -34,6 +35,7 @@ namespace platform
std::string default_server_address();
VirtualMachineFactory::UPtr vm_backend(const Path& data_dir);
logging::Logger::UPtr make_logger(logging::Level level);
UpdatePrompt::UPtr make_update_prompt();
int chown(const char* path, unsigned int uid, unsigned int gid);
bool symlink(const char* target, const char* link, bool is_dir);
bool link(const char* target, const char* link);
Expand All @@ -43,5 +45,5 @@ bool is_alias_supported(const std::string& alias, const std::string& remote);
bool is_remote_supported(const std::string& remote);
bool is_image_url_supported();
} // namespace platform
}
} // namespace multipass
#endif // MULTIPASS_PLATFORM_H
43 changes: 43 additions & 0 deletions include/multipass/qt_delete_later_unique_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef QT_DELETE_LATER_UNIQUE_PTR_H
#define QT_DELETE_LATER_UNIQUE_PTR_H

#include <memory>
#include <QObject>

namespace multipass
{

/*
* A unique_ptr for Qt objects that are more safely cleaned up on the event loop
* e.g. QThread
*/

struct QtDeleteLater {
void operator()(QObject *o) {
o->deleteLater();
}
};

template<typename T>
using qt_delete_later_unique_ptr = std::unique_ptr<T, QtDeleteLater>;

} // namespace

#endif // QT_DELETE_LATER_UNIQUE_PTR_H
39 changes: 39 additions & 0 deletions include/multipass/update_prompt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef MULTIPASS_UPDATE_PROMPT_H
#define MULTIPASS_UPDATE_PROMPT_H

#include <memory>

namespace multipass
{
class UpdateInfo;

class UpdatePrompt
{
public:
using UPtr = std::unique_ptr<UpdatePrompt>;
virtual ~UpdatePrompt() = default;

virtual bool time_to_show() = 0;
virtual void populate(UpdateInfo *update_info) = 0;
virtual void populate_if_time_to_show(UpdateInfo *update_info) = 0;
};
} // namespace multipass

#endif // MULTIPASS_UPDATE_PROMPT_H
20 changes: 20 additions & 0 deletions src/client/cmd/common_cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,23 @@ mp::ReturnCode cmd::standard_failure_handler_for(const std::string& command, std

return return_code_for(status.error_code());
}

bool cmd::update_available(const multipass::UpdateInfo& update_info)
{
return update_info.version() != "";
}

std::string cmd::update_notice(const multipass::UpdateInfo& update_info)
{
if (update_available(update_info))
{
return "\n** A new Multipass version " + update_info.version() +
" is available! **\n"
"** Find out more: " +
update_info.url() + "\n";
}
else
{
return std::string();
}
}
4 changes: 4 additions & 0 deletions src/client/cmd/common_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ ParseCode handle_format_option(ArgParser* parser, Formatter** chosen_formatter,
std::string instance_action_message_for(const InstanceNames& instance_names, const std::string& action_name);
ReturnCode standard_failure_handler_for(const std::string& command, std::ostream& cerr, const grpc::Status& status,
const std::string& error_details = std::string());

// helpers for update handling
bool update_available(const UpdateInfo& update_info);
std::string update_notice(const UpdateInfo& update_info);
} // namespace cmd
} // namespace multipass

Expand Down
6 changes: 5 additions & 1 deletion src/client/cmd/launch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,11 @@ mp::ReturnCode cmd::Launch::request_launch()
auto on_success = [this, &spinner](mp::LaunchReply& reply) {
spinner.stop();

if (reply.metrics_pending())
if (term->is_live() && update_available(reply.update_info()))
{
cout << update_notice(reply.update_info());
}
else if (reply.metrics_pending())
{
if (term->is_live())
{
Expand Down
3 changes: 3 additions & 0 deletions src/client/cmd/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ mp::ReturnCode cmd::List::run(mp::ArgParser* parser)
auto on_success = [this](ListReply& reply) {
cout << chosen_formatter->format(reply);

if (term->is_live())
cout << update_notice(reply.update_info());

return ReturnCode::Ok;
};

Expand Down
9 changes: 7 additions & 2 deletions src/client/cmd/start.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ mp::ReturnCode cmd::Start::run(mp::ArgParser* parser)

AnimatedSpinner spinner{cout};

auto on_success = [&spinner](mp::StartReply& reply) {
auto on_success = [&spinner, this](mp::StartReply& reply) {
spinner.stop();
if (term->is_live())
cout << update_notice(reply.update_info());
return ReturnCode::Ok;
};

Expand Down Expand Up @@ -72,7 +74,10 @@ mp::ReturnCode cmd::Start::run(mp::ArgParser* parser)
return dispatch(&RpcMethod::start, request, on_success, on_failure, streaming_callback);
}

std::string cmd::Start::name() const { return "start"; }
std::string cmd::Start::name() const
{
return "start";
}

QString cmd::Start::short_help() const
{
Expand Down
13 changes: 9 additions & 4 deletions src/client/cmd/version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
*/

#include "version.h"
#include <multipass/version.h>
#include "common_cli.h"
#include <multipass/cli/argparser.h>
#include <multipass/version.h>

namespace mp = multipass;
namespace cmd = multipass::cmd;
Expand All @@ -34,8 +35,9 @@ mp::ReturnCode cmd::Version::run(mp::ArgParser* parser)
cout << "multipass " << multipass::version_string << "\n";

auto on_success = [this](mp::VersionReply& reply) {
cout << "multipassd " << reply.version();
cout << "\n";
cout << "multipassd " << reply.version() << "\n";
if (term->is_live())
cout << update_notice(reply.update_info());
return ReturnCode::Ok;
};

Expand All @@ -46,7 +48,10 @@ mp::ReturnCode cmd::Version::run(mp::ArgParser* parser)
return dispatch(&RpcMethod::version, request, on_success, on_failure);
}

std::string cmd::Version::name() const { return "version"; }
std::string cmd::Version::name() const
{
return "version";
}

QString cmd::Version::short_help() const
{
Expand Down
19 changes: 14 additions & 5 deletions src/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,7 @@ try // clang-format on
{
mpl::ClientLogger<ListReply> logger{mpl::level_from(request->verbosity_level()), *config->logger, server};
ListReply response;
config->update_prompt->populate_if_time_to_show(response.mutable_update_info());

auto status_for = [](mp::VirtualMachine::State state) {
switch (state)
Expand Down Expand Up @@ -1331,17 +1332,17 @@ try // clang-format on
mpl::ClientLogger<RecoverReply> logger{mpl::level_from(request->verbosity_level()), *config->logger, server};

const auto instances_and_status =
find_requested_instances(request->instance_names().instance_name(), deleted_instances,
std::bind(&Daemon::check_instance_exists, this, std::placeholders::_1));
find_requested_instances(request->instance_names().instance_name(), deleted_instances,
std::bind(&Daemon::check_instance_exists, this, std::placeholders::_1));
const auto& instances = instances_and_status.first; // use structured bindings instead in C++17
const auto& status = instances_and_status.second; // idem

if(status.ok())
if (status.ok())
{
for (const auto& name : instances)
{
auto it = deleted_instances.find(name);
if(it != std::end(deleted_instances))
if (it != std::end(deleted_instances))
{
assert(vm_instance_specs[name].deleted);
vm_instance_specs[name].deleted = false;
Expand Down Expand Up @@ -1532,6 +1533,13 @@ try // clang-format on
if (update_instance_db)
persist_instances();

if (config->update_prompt->time_to_show())
{
StartReply start_reply;
config->update_prompt->populate(start_reply.mutable_update_info());
server->Write(start_reply);
}

return grpc_status_for(errors);
}
catch (const std::exception& e)
Expand Down Expand Up @@ -1791,6 +1799,7 @@ grpc::Status mp::Daemon::version(grpc::ServerContext* context, const VersionRequ

VersionReply reply;
reply.set_version(multipass::version_string);
config->update_prompt->populate(reply.mutable_update_info());
server->Write(reply);
return grpc::Status::OK;
}
Expand Down Expand Up @@ -1986,7 +1995,7 @@ std::string mp::Daemon::check_instance_operational(const std::string& instance_n

std::string mp::Daemon::check_instance_exists(const std::string& instance_name) const
{
if(vm_instances.find(instance_name) == std::cend(vm_instances) &&
if (vm_instances.find(instance_name) == std::cend(vm_instances) &&
deleted_instances.find(instance_name) == std::cend(deleted_instances))
return fmt::format("instance \"{}\" does not exist\n", instance_name);

Expand Down
4 changes: 3 additions & 1 deletion src/daemon/daemon_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ std::unique_ptr<const mp::DaemonConfig> mp::DaemonConfigBuilder::build()
url_downloader = std::make_unique<URLDownloader>(cache_directory, std::chrono::seconds{10});
if (factory == nullptr)
factory = platform::vm_backend(data_directory);
if (update_prompt == nullptr)
update_prompt = platform::make_update_prompt();
if (image_hosts.empty())
{
image_hosts.push_back(std::make_unique<mp::CustomVMImageHost>(url_downloader.get(), manifest_ttl));
Expand Down Expand Up @@ -115,6 +117,6 @@ std::unique_ptr<const mp::DaemonConfig> mp::DaemonConfigBuilder::build()
return std::unique_ptr<const DaemonConfig>(
new DaemonConfig{std::move(url_downloader), std::move(factory), std::move(image_hosts), std::move(vault),
std::move(name_generator), std::move(ssh_key_provider), std::move(cert_provider),
std::move(client_cert_store), multiplexing_logger, cache_directory,
std::move(client_cert_store), std::move(update_prompt), multiplexing_logger, cache_directory,
data_directory, server_address, ssh_username, connection_type, image_refresh_timer});
}
3 changes: 3 additions & 0 deletions src/daemon/daemon_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <multipass/rpc/multipass.grpc.pb.h>
#include <multipass/rpc_connection_type.h>
#include <multipass/ssh/ssh_key_provider.h>
#include <multipass/update_prompt.h>
#include <multipass/url_downloader.h>
#include <multipass/virtual_machine_factory.h>
#include <multipass/vm_image_host.h>
Expand All @@ -49,6 +50,7 @@ struct DaemonConfig
const std::unique_ptr<SSHKeyProvider> ssh_key_provider;
const std::unique_ptr<CertProvider> cert_provider;
const std::unique_ptr<CertStore> client_cert_store;
const std::unique_ptr<UpdatePrompt> update_prompt;
const std::shared_ptr<logging::MultiplexingLogger> logger;
const multipass::Path cache_directory;
const multipass::Path data_directory;
Expand All @@ -68,6 +70,7 @@ struct DaemonConfigBuilder
std::unique_ptr<SSHKeyProvider> ssh_key_provider;
std::unique_ptr<CertProvider> cert_provider;
std::unique_ptr<CertStore> client_cert_store;
std::unique_ptr<UpdatePrompt> update_prompt;
std::unique_ptr<logging::Logger> logger;
multipass::Path cache_directory;
multipass::Path data_directory;
Expand Down
4 changes: 4 additions & 0 deletions src/platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ target_link_libraries(platform
include_directories(platform
backends)

target_link_libraries(platform
update)

add_subdirectory(backends)
add_subdirectory(client)
add_subdirectory(console)
add_subdirectory(logger)
add_subdirectory(update)
6 changes: 6 additions & 0 deletions src/platform/platform_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "backends/shared/linux/process.h"
#include "backends/shared/linux/process_factory.h"
#include "logger/journald_logger.h"
#include <disabled_update_prompt.h>

namespace mp = multipass;

Expand Down Expand Up @@ -60,6 +61,11 @@ mp::VirtualMachineFactory::UPtr mp::platform::vm_backend(const mp::Path& data_di
throw std::runtime_error("Invalid virtualization driver set in the environment");
}

mp::UpdatePrompt::UPtr mp::platform::make_update_prompt()
{
return std::make_unique<DisabledUpdatePrompt>();
}

mp::logging::Logger::UPtr mp::platform::make_logger(mp::logging::Level level)
{
return std::make_unique<logging::JournaldLogger>(level);
Expand Down
Loading