Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
61 changes: 61 additions & 0 deletions include/multipass/base_availability_zone.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (C) 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_BASE_AVAILABILITY_ZONE_H
#define MULTIPASS_BASE_AVAILABILITY_ZONE_H

#include "availability_zone.h"

#include <filesystem>
#include <mutex>
#include <string>
#include <vector>

namespace multipass
{
class BaseAvailabilityZone : public AvailabilityZone
{
public:
BaseAvailabilityZone(const std::string& name, const std::filesystem::path& az_directory);

const std::string& get_name() const override;
const std::string& get_subnet() const override;
bool is_available() const override;
void set_available(bool new_available) override;
void add_vm(VirtualMachine& vm) override;
void remove_vm(VirtualMachine& vm) override;

private:
void serialize() const;

// we store all the data in one struct so that it can be created from one function call in the initializer list
struct data
{
const std::string name{};
const std::filesystem::path file_path{};
const std::string subnet{};
bool available{};
std::vector<std::reference_wrapper<VirtualMachine>> vms{};
// we don't have designated initializers, so mutex remains last so it doesn't need to be manually initialized
mutable std::recursive_mutex mutex{};
} m;

static data read_from_file(const std::string& name, const std::filesystem::path& file_path);
};
} // namespace multipass

#endif // MULTIPASS_BASE_AVAILABILITY_ZONE_H
78 changes: 78 additions & 0 deletions include/multipass/base_availability_zone_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 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_BASE_AVAILABILITY_ZONE_MANAGER_H
#define MULTIPASS_BASE_AVAILABILITY_ZONE_MANAGER_H

#include "availability_zone_manager.h"

#include <multipass/constants.h>

#include <array>
#include <filesystem>
#include <mutex>
#include <shared_mutex>

namespace multipass
{
class BaseAvailabilityZoneManager final : public AvailabilityZoneManager
{
public:
explicit BaseAvailabilityZoneManager(const std::filesystem::path& data_dir);

AvailabilityZone& get_zone(const std::string& name) override;
std::vector<std::reference_wrapper<const AvailabilityZone>> get_zones() override;
std::string get_automatic_zone_name() override;
std::string get_default_zone_name() const override;

private:
void serialize() const;

class ZoneCollection
{
public:
static constexpr size_t size = default_zone_names.size();
using ZoneArray = std::array<AvailabilityZone::UPtr, size>;
static_assert(size > 0);

const ZoneArray zones{};

ZoneCollection(ZoneArray&& zones, std::string last_used);
[[nodiscard]] std::string next_available();
[[nodiscard]] std::string last_used() const;

private:
ZoneArray::const_iterator automatic_zone;
mutable std::shared_mutex mutex{};
};

// we store all the data in one struct so that it can be created from one function call in the initializer list
struct data
{
const std::filesystem::path file_path{};
ZoneCollection zone_collection;
// we don't have designated initializers, so mutex remains last so it doesn't need to be manually initialized
mutable std::recursive_mutex mutex{};
} m;

[[nodiscard]] const ZoneCollection::ZoneArray& zones() const;

static data read_from_file(const std::filesystem::path& file_path, const std::filesystem::path& zones_directory);
};
} // namespace multipass

#endif // MULTIPASS_BASE_AVAILABILITY_ZONE_MANAGER_H
2 changes: 2 additions & 0 deletions include/multipass/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ constexpr auto petenv_default = "primary";
constexpr auto timeout_exit_code = 5;

constexpr auto authenticated_certs_dir = "authenticated-certs";

constexpr auto default_zone_names = {"zone1", "zone2", "zone3"};
} // namespace multipass

#endif // MULTIPASS_CONSTANTS_H
2 changes: 2 additions & 0 deletions include/multipass/json_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <QJsonObject>
#include <QString>

#include <filesystem>
#include <optional>
#include <string>
#include <vector>
Expand All @@ -41,6 +42,7 @@ class JsonUtils : public Singleton<JsonUtils>
explicit JsonUtils(const Singleton<JsonUtils>::PrivatePass&) noexcept;

virtual void write_json(const QJsonObject& root, QString file_name) const; // transactional; creates parent dirs
virtual QJsonObject read_object_from_file(const std::filesystem::path& file_path) const;
virtual std::string json_to_string(const QJsonObject& root) const;
virtual QJsonValue update_cloud_init_instance_id(const QJsonValue& id,
const std::string& src_vm_name,
Expand Down
3 changes: 2 additions & 1 deletion include/multipass/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define MULTIPASS_PLATFORM_H

#include <multipass/alias_definition.h>
#include <multipass/availability_zone_manager.h>
#include <multipass/days.h>
#include <multipass/logging/logger.h>
#include <multipass/network_interface_info.h>
Expand Down Expand Up @@ -86,7 +87,7 @@ void sync_winterm_profiles();

std::string default_server_address();

VirtualMachineFactory::UPtr vm_backend(const Path& data_dir);
VirtualMachineFactory::UPtr vm_backend(const Path& data_dir, AvailabilityZoneManager& az_manager);
logging::Logger::UPtr make_logger(logging::Level level);
UpdatePrompt::UPtr make_update_prompt();
std::unique_ptr<Process> make_sshfs_server_process(const SSHFSServerConfig& config);
Expand Down
6 changes: 5 additions & 1 deletion include/multipass/virtual_machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

namespace multipass
{
class AvailabilityZone;
class MemorySize;
class VMMount;
struct VMSpecs;
Expand All @@ -55,7 +56,8 @@ class VirtualMachine : private DisabledCopyMove
delayed_shutdown,
suspending,
suspended,
unknown
unknown,
unavailable,
};

enum class ShutdownPolicy
Expand All @@ -73,6 +75,7 @@ class VirtualMachine : private DisabledCopyMove
virtual void start() = 0;
virtual void shutdown(ShutdownPolicy shutdown_policy = ShutdownPolicy::Powerdown) = 0;
virtual void suspend() = 0;
virtual void set_available(bool available) = 0;
virtual State current_state() = 0;
virtual int ssh_port() = 0;
virtual std::string ssh_hostname()
Expand Down Expand Up @@ -122,6 +125,7 @@ class VirtualMachine : private DisabledCopyMove
virtual int get_snapshot_count() const = 0;

QDir instance_directory() const;
virtual const AvailabilityZone& get_zone() const = 0;

VirtualMachine::State state;
const std::string vm_name;
Expand Down
1 change: 1 addition & 0 deletions include/multipass/virtual_machine_description.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class VirtualMachineDescription
MemorySize mem_size;
MemorySize disk_space;
std::string vm_name;
std::string zone;
std::string default_mac_address;
std::vector<NetworkInterface> extra_interfaces;
std::string ssh_username;
Expand Down
40 changes: 19 additions & 21 deletions include/multipass/vm_specs.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,29 @@ struct VMSpecs
bool deleted;
QJsonObject metadata;
int clone_count = 0; // tracks the number of cloned vm from this source vm (regardless of deletes)
std::string zone;
};

inline bool operator==(const VMSpecs& a, const VMSpecs& b)
{
return std::tie(a.num_cores,
a.mem_size,
a.disk_space,
a.default_mac_address,
a.extra_interfaces,
a.ssh_username,
a.state,
a.mounts,
a.deleted,
a.metadata,
a.clone_count) == std::tie(b.num_cores,
b.mem_size,
b.disk_space,
b.default_mac_address,
b.extra_interfaces,
b.ssh_username,
b.state,
b.mounts,
b.deleted,
b.metadata,
a.clone_count);
const auto properties_of = [](const VMSpecs& spec) {
return std::tuple{
spec.num_cores,
spec.mem_size,
spec.disk_space,
spec.default_mac_address,
spec.extra_interfaces,
spec.ssh_username,
spec.state,
spec.mounts,
spec.deleted,
spec.metadata,
spec.clone_count,
spec.zone,
};
};

return properties_of(a) == properties_of(b);
}

inline bool operator!=(const VMSpecs& a, const VMSpecs& b) // TODO drop in C++20
Expand Down
Loading
Loading