Skip to content

Commit

Permalink
[image vault] have image vault reference factory for instance directo…
Browse files Browse the repository at this point in the history
…ries
  • Loading branch information
sharder996 committed Jun 21, 2023
1 parent 6229b9c commit 7af15d3
Show file tree
Hide file tree
Showing 18 changed files with 191 additions and 168 deletions.
2 changes: 1 addition & 1 deletion include/multipass/vm_image_vault.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class VMImageVault : private DisabledCopyMove
virtual ~VMImageVault() = default;
virtual VMImage fetch_image(const FetchType& fetch_type, const Query& query, const PrepareAction& prepare,
const ProgressMonitor& monitor, const bool unlock,
const std::optional<std::string>& checksum) = 0;
const std::optional<std::string>& checksum, const Path& download_dir) = 0;
virtual void remove(const std::string& name) = 0;
virtual bool has_record_for(const std::string& name) = 0;
virtual void prune_expired_images() = 0;
Expand Down
18 changes: 10 additions & 8 deletions src/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,14 +449,15 @@ QJsonObject vm_spec_to_json(const mp::VMSpecs& specs)
return json;
}

auto fetch_image_for(const std::string& name, const mp::FetchType& fetch_type, mp::VMImageVault& vault)
auto fetch_image_for(const std::string& name, mp::VirtualMachineFactory& factory, mp::VMImageVault& vault)
{
auto stub_prepare = [](const mp::VMImage&) -> mp::VMImage { return {}; };
auto stub_progress = [](int download_type, int progress) { return true; };

mp::Query query{name, "", false, "", mp::Query::Type::Alias, false};

return vault.fetch_image(fetch_type, query, stub_prepare, stub_progress, false, std::nullopt);
return vault.fetch_image(factory.fetch_type(), query, stub_prepare, stub_progress, false, std::nullopt,
factory.get_instance_directory_name(name));
}

auto try_mem_size(const std::string& val) -> std::optional<mp::MemorySize>
Expand Down Expand Up @@ -1286,7 +1287,7 @@ mp::Daemon::Daemon(std::unique_ptr<const DaemonConfig> the_config)
continue;
}

auto vm_image = fetch_image_for(name, config->factory->fetch_type(), *config->vault);
auto vm_image = fetch_image_for(name, *config->factory, *config->vault);
if (!vm_image.image_path.isEmpty() && !QFile::exists(vm_image.image_path))
{
mpl::log(mpl::Level::warning, category,
Expand Down Expand Up @@ -1629,7 +1630,7 @@ try // clang-format on
info->mutable_instance_status()->set_status(grpc_instance_status_for(present_state));
}

auto vm_image = fetch_image_for(name, config->factory->fetch_type(), *config->vault);
auto vm_image = fetch_image_for(name, *config->factory, *config->vault);
auto original_release = vm_image.original_release;

if (!vm_image.id.empty() && original_release.empty())
Expand Down Expand Up @@ -1817,7 +1818,7 @@ try // clang-format on
entry->mutable_instance_status()->set_status(grpc_instance_status_for(present_state));

// FIXME: Set the release to the cached current version when supported
auto vm_image = fetch_image_for(name, config->factory->fetch_type(), *config->vault);
auto vm_image = fetch_image_for(name, *config->factory, *config->vault);
auto current_release = vm_image.original_release;

if (!vm_image.id.empty() && current_release.empty())
Expand Down Expand Up @@ -2912,8 +2913,9 @@ void mp::Daemon::create_vm(const CreateRequest* request,
if (!vm_desc.image.id.empty())
checksum = vm_desc.image.id;

auto vm_image = config->vault->fetch_image(fetch_type, query, prepare_action, progress_monitor,
launch_from_blueprint, checksum);
auto vm_image =
config->vault->fetch_image(fetch_type, query, prepare_action, progress_monitor, launch_from_blueprint,
checksum, config->factory->get_instance_directory_name(name));

const auto image_size = config->vault->minimum_image_size_for(vm_image.id);
vm_desc.disk_space = compute_final_image_size(
Expand Down Expand Up @@ -3354,7 +3356,7 @@ grpc::Status mp::Daemon::migrate_from_hyperkit(grpc::ServerReaderWriterInterface
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),
/* sticky = */ true);
else if (const auto vm_image = fetch_image_for(vm_name, config->factory->fetch_type(), *config->vault);
else if (const auto vm_image = fetch_image_for(vm_name, *config->factory, *config->vault);
vm_image.original_release.find("16.04") != std::string::npos &&
!vm_image.image_path.contains("uefi", Qt::CaseInsensitive))
reply_msg(server,
Expand Down
37 changes: 17 additions & 20 deletions src/daemon/default_vm_image_vault.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ mp::DefaultVMImageVault::DefaultVMImageVault(std::vector<VMImageHost*> image_hos
url_downloader{downloader},
cache_dir{QDir(cache_dir_path).filePath("vault")},
data_dir{QDir(data_dir_path).filePath("vault")},
instances_dir(data_dir.filePath("instances")),
images_dir(cache_dir.filePath("images")),
days_to_expire{days_to_expire},
prepared_image_records{load_db(cache_dir.filePath(image_db_name))},
Expand All @@ -262,7 +261,8 @@ mp::DefaultVMImageVault::~DefaultVMImageVault()

mp::VMImage mp::DefaultVMImageVault::fetch_image(const FetchType& fetch_type, const Query& query,
const PrepareAction& prepare, const ProgressMonitor& monitor,
const bool unlock, const std::optional<std::string>& checksum)
const bool unlock, const std::optional<std::string>& checksum,
const mp::Path& download_dir)
{
{
std::lock_guard<decltype(fetch_mutex)> lock{fetch_mutex};
Expand Down Expand Up @@ -290,11 +290,11 @@ mp::VMImage mp::DefaultVMImageVault::fetch_image(const FetchType& fetch_type, co

if (source_image.image_path.endsWith(".xz"))
{
source_image.image_path = extract_image_from(query.name, source_image, monitor);
source_image.image_path = extract_image_from(query.name, source_image, monitor, download_dir);
}
else
{
source_image = image_instance_from(query.name, source_image);
source_image = image_instance_from(query.name, source_image, download_dir);
}

if (fetch_type == FetchType::ImageKernelAndInitrd)
Expand Down Expand Up @@ -343,7 +343,7 @@ mp::VMImage mp::DefaultVMImageVault::fetch_image(const FetchType& fetch_type, co

if (last_modified.isValid() && (last_modified.toString().toStdString() == record.image.release_date))
{
return finalize_image_records(query, record.image, id);
return finalize_image_records(query, record.image, id, download_dir);
}
}

Expand Down Expand Up @@ -408,7 +408,7 @@ mp::VMImage mp::DefaultVMImageVault::fetch_image(const FetchType& fetch_type, co
const auto prepared_image = record.second.image;
try
{
return finalize_image_records(query, prepared_image, record.first);
return finalize_image_records(query, prepared_image, record.first, download_dir);
}
catch (const std::exception& e)
{
Expand Down Expand Up @@ -446,7 +446,7 @@ mp::VMImage mp::DefaultVMImageVault::fetch_image(const FetchType& fetch_type, co
auto prepared_image = future.result();
std::lock_guard<decltype(fetch_mutex)> lock{fetch_mutex};
in_progress_image_fetches.erase(id);
return finalize_image_records(query, prepared_image, id);
return finalize_image_records(query, prepared_image, id, download_dir);
}
catch (const std::exception&)
{
Expand Down Expand Up @@ -551,7 +551,8 @@ void mp::DefaultVMImageVault::update_images(const FetchType& fetch_type, const P
mpl::log(mpl::Level::info, category, fmt::format("Updating {} source image to latest", record.query.release));
try
{
fetch_image(fetch_type, record.query, prepare, monitor, false, std::nullopt);
fetch_image(fetch_type, record.query, prepare, monitor, false, std::nullopt,
QFileInfo{record.image.image_path}.absolutePath());

// Remove old image
std::lock_guard<decltype(fetch_mutex)> lock{fetch_mutex};
Expand Down Expand Up @@ -654,26 +655,22 @@ mp::VMImage mp::DefaultVMImageVault::download_and_prepare_source_image(
}

QString mp::DefaultVMImageVault::extract_image_from(const std::string& instance_name, const VMImage& source_image,
const ProgressMonitor& monitor)
const ProgressMonitor& monitor, const mp::Path& dest_dir)
{
const auto name = QString::fromStdString(instance_name);
const QDir output_dir{MP_UTILS.make_dir(instances_dir, name)};
QFileInfo file_info{source_image.image_path};
const auto image_name = file_info.fileName().remove(".xz");
const auto image_path = output_dir.filePath(image_name);
const auto image_path = QDir(dest_dir).filePath(image_name);

return mp::vault::extract_image(image_path, monitor);
}

mp::VMImage mp::DefaultVMImageVault::image_instance_from(const std::string& instance_name,
const VMImage& prepared_image)
const VMImage& prepared_image, const mp::Path& dest_dir)
{
auto name = QString::fromStdString(instance_name);
auto output_dir = MP_UTILS.make_dir(instances_dir, name);

return {mp::vault::copy(prepared_image.image_path, output_dir),
mp::vault::copy(prepared_image.kernel_path, output_dir),
mp::vault::copy(prepared_image.initrd_path, output_dir),
return {mp::vault::copy(prepared_image.image_path, dest_dir),
mp::vault::copy(prepared_image.kernel_path, dest_dir),
mp::vault::copy(prepared_image.initrd_path, dest_dir),
prepared_image.id,
prepared_image.original_release,
prepared_image.current_release,
Expand Down Expand Up @@ -708,13 +705,13 @@ std::optional<QFuture<mp::VMImage>> mp::DefaultVMImageVault::get_image_future(co
}

mp::VMImage mp::DefaultVMImageVault::finalize_image_records(const Query& query, const VMImage& prepared_image,
const std::string& id)
const std::string& id, const mp::Path& dest_dir)
{
VMImage vm_image;

if (!query.name.empty())
{
vm_image = image_instance_from(query.name, prepared_image);
vm_image = image_instance_from(query.name, prepared_image, dest_dir);
instance_image_records[query.name] = {vm_image, query, std::chrono::system_clock::now()};
}

Expand Down
12 changes: 6 additions & 6 deletions src/daemon/default_vm_image_vault.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class DefaultVMImageVault final : public BaseVMImageVault
~DefaultVMImageVault();

VMImage fetch_image(const FetchType& fetch_type, const Query& query, const PrepareAction& prepare,
const ProgressMonitor& monitor, const bool unlock,
const std::optional<std::string>& checksum) override;
const ProgressMonitor& monitor, const bool unlock, const std::optional<std::string>& checksum,
const Path& download_dir) override;
void remove(const std::string& name) override;
bool has_record_for(const std::string& name) override;
void prune_expired_images() override;
Expand All @@ -61,24 +61,24 @@ class DefaultVMImageVault final : public BaseVMImageVault
MemorySize minimum_image_size_for(const std::string& id) override;

private:
VMImage image_instance_from(const std::string& name, const VMImage& prepared_image);
VMImage image_instance_from(const std::string& name, const VMImage& prepared_image, const Path& dest_dir);
VMImage download_and_prepare_source_image(const VMImageInfo& info, std::optional<VMImage>& existing_source_image,
const QDir& image_dir, const FetchType& fetch_type,
const PrepareAction& prepare, const ProgressMonitor& monitor);
QString extract_image_from(const std::string& instance_name, const VMImage& source_image,
const ProgressMonitor& monitor);
const ProgressMonitor& monitor, const Path& dest_dir);
VMImage fetch_kernel_and_initrd(const VMImageInfo& info, const VMImage& source_image, const QDir& image_dir,
const ProgressMonitor& monitor);
std::optional<QFuture<VMImage>> get_image_future(const std::string& id);
VMImage finalize_image_records(const Query& query, const VMImage& prepared_image, const std::string& id);
VMImage finalize_image_records(const Query& query, const VMImage& prepared_image, const std::string& id,
const Path& dest_dir);
VMImageInfo get_kernel_query_info(const std::string& name);
void persist_image_records();
void persist_instance_records();

URLDownloader* const url_downloader;
const QDir cache_dir;
const QDir data_dir;
const QDir instances_dir;
const QDir images_dir;
const days days_to_expire;
std::mutex fetch_mutex;
Expand Down
3 changes: 2 additions & 1 deletion src/platform/backends/lxd/lxd_vm_image_vault.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ mp::LXDVMImageVault::LXDVMImageVault(std::vector<VMImageHost*> image_hosts, URLD

mp::VMImage mp::LXDVMImageVault::fetch_image(const FetchType& fetch_type, const Query& query,
const PrepareAction& prepare, const ProgressMonitor& monitor,
const bool unlock, const std::optional<std::string>& checksum)
const bool unlock, const std::optional<std::string>& checksum,
const mp::Path&)
{
// Look for an already existing instance and get its image info
try
Expand Down
4 changes: 2 additions & 2 deletions src/platform/backends/lxd/lxd_vm_image_vault.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class LXDVMImageVault final : public BaseVMImageVault
const QUrl& base_url, const QString& cache_dir_path, const multipass::days& days_to_expire);

VMImage fetch_image(const FetchType& fetch_type, const Query& query, const PrepareAction& prepare,
const ProgressMonitor& monitor, const bool unlock,
const std::optional<std::string>& checksum) override;
const ProgressMonitor& monitor, const bool unlock, const std::optional<std::string>& checksum,
const Path&) override;
void remove(const std::string& name) override;
bool has_record_for(const std::string& name) override;
void prune_expired_images() override;
Expand Down
11 changes: 8 additions & 3 deletions src/platform/backends/qemu/qemu_virtual_machine_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ constexpr auto category = "qemu factory";
} // namespace

mp::QemuVirtualMachineFactory::QemuVirtualMachineFactory(const mp::Path& data_dir)
: BaseVirtualMachineFactory(
MP_UTILS.make_dir(QDir(data_dir, get_backend_directory_name()).filePath("vault"), "instances")),
qemu_platform{MP_QEMU_PLATFORM_FACTORY.make_qemu_platform(data_dir)}
: BaseVirtualMachineFactory(QString{}), qemu_platform{MP_QEMU_PLATFORM_FACTORY.make_qemu_platform(data_dir)}
{
instances_dir = MP_UTILS.make_dir(QDir(data_dir, get_backend_directory_name()).filePath("vault"), "instances");
}

mp::VirtualMachine::UPtr mp::QemuVirtualMachineFactory::create_virtual_machine(const VirtualMachineDescription& desc,
Expand Down Expand Up @@ -124,3 +123,9 @@ auto mp::QemuVirtualMachineFactory::networks() const -> std::vector<NetworkInter
{
return qemu_platform->networks();
}

mp::Path mp::QemuVirtualMachineFactory::make_qemu_platform_and_resolve_instances_dir(const mp::Path& data_dir)
{
qemu_platform = MP_QEMU_PLATFORM_FACTORY.make_qemu_platform(data_dir);
return MP_UTILS.make_dir(QDir(data_dir, get_backend_directory_name()).filePath("vault"), "instances");
}
2 changes: 2 additions & 0 deletions src/platform/backends/qemu/qemu_virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class QemuVirtualMachineFactory final : public BaseVirtualMachineFactory
std::vector<NetworkInterfaceInfo> networks() const override;

private:
Path make_qemu_platform_and_resolve_instances_dir(const Path& data_dir);

QemuPlatform::UPtr qemu_platform;
};
} // namespace multipass
Expand Down
4 changes: 2 additions & 2 deletions src/platform/backends/shared/base_virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class BaseVirtualMachineFactory : public VirtualMachineFactory

QString get_instance_directory_name(const std::string& name) const override
{
return multipass::utils::backend_directory_path(instances_dir, QString::fromStdString(name));
return MP_UTILS.make_dir(multipass::utils::backend_directory_path(instances_dir, QString::fromStdString(name)));
}

void prepare_networking(std::vector<NetworkInterface>& /*extra_interfaces*/) override
Expand Down Expand Up @@ -84,7 +84,7 @@ class BaseVirtualMachineFactory : public VirtualMachineFactory
virtual void prepare_interface(NetworkInterface& net, std::vector<NetworkInterfaceInfo>& host_nets,
const std::string& bridge_type);

const Path instances_dir;
Path instances_dir;
};
} // namespace multipass

Expand Down
8 changes: 5 additions & 3 deletions tests/blueprint_test_lambdas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@
#include "common.h"
#include "stub_virtual_machine.h"
#include "stub_vm_image_vault.h"
#include "temp_dir.h"

namespace mp = multipass;
namespace mpt = multipass::test;

std::function<mp::VMImage(const mp::FetchType&, const mp::Query&, const mp::VMImageVault::PrepareAction&,
const mp::ProgressMonitor&, const bool, const std::optional<std::string>)>
const mp::ProgressMonitor&, const bool, const std::optional<std::string>, const mp::Path&)>
mpt::fetch_image_lambda(const std::string& release, const std::string& remote, const bool must_have_checksum)
{
return [&release, &remote, must_have_checksum](
const mp::FetchType& fetch_type, const mp::Query& query, const mp::VMImageVault::PrepareAction& prepare,
const mp::ProgressMonitor& monitor, const bool unlock, const std::optional<std::string>& checksum) {
const mp::ProgressMonitor& monitor, const bool unlock, const std::optional<std::string>& checksum,
const mp::Path& download_dir) {
EXPECT_EQ(query.release, release);
if (remote.empty())
{
Expand All @@ -55,7 +57,7 @@ mpt::fetch_image_lambda(const std::string& release, const std::string& remote, c
EXPECT_NE(checksum, std::nullopt);
}

return mpt::StubVMImageVault().fetch_image(fetch_type, query, prepare, monitor, unlock, checksum);
return mpt::StubVMImageVault().fetch_image(fetch_type, query, prepare, monitor, unlock, checksum, download_dir);
};
}

Expand Down
2 changes: 1 addition & 1 deletion tests/blueprint_test_lambdas.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace test
{

std::function<VMImage(const FetchType&, const Query&, const VMImageVault::PrepareAction&, const ProgressMonitor&,
const bool, const std::optional<std::string>)>
const bool, const std::optional<std::string>, const multipass::Path&)>
fetch_image_lambda(const std::string& release, const std::string& remote, const bool must_have_checksum = false);

std::function<VirtualMachine::UPtr(const VirtualMachineDescription&, VMStatusMonitor&)>
Expand Down
Loading

0 comments on commit 7af15d3

Please sign in to comment.