1
0
mirror of https://github.com/openSUSE/snapper.git synced 2026-02-06 09:46:06 +01:00
Files
snapper/client/proxy/proxy.h

367 lines
10 KiB
C++

/*
* Copyright (c) [2016-2025] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* 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, contact Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail, you may
* find current contact information at www.novell.com.
*/
#ifndef SNAPPER_PROXY_H
#define SNAPPER_PROXY_H
#include <memory>
#include <vector>
#include <list>
#include <map>
#include <snapper/Snapshot.h>
#include <snapper/Snapper.h>
#include <snapper/File.h>
namespace snapper
{
/**
* The proxy classes here allow clients, so far only the snapper command line
* interface, to work with and without DBus in a transparent way by providing
* the same interface in both cases.
*
* The main idea for providing the same interface is to have an abstract
* class, e.g. ProxySnapper, and two concrete implementation ProxySnapperDbus
* and ProxySnapperLib. This is done for ProxySnapshots, ProxySnapper and
* ProxySnappers.
*
* For ProxySnapshot the implementation is more complicated since
* ProxySnapshots provides an interface to list<ProxySnapshot> and thus
* polymorphism does not work. Instead ProxySnapshot has an implementation
* pointer (pimpl idiom) which ensures polymorphism. Another possibility would
* be to provide an interface to list<ProxySnapshot*> in ProxySnapshots but
* that is less intuitive to use.
*
* All objects are stored in containers or smart pointers to avoid manual
* cleanup.
*
* The interface copycats the classes Snapshot, Snapshots and Snapper of
* libsnapper. For consistency one may add a Snappers class to libsnapper.
*
* Limitations: The classes are tailored for the snapper command line
* interface. Other use-cases are not supported.
*/
// TODO Maybe unique error handling, e.g. catch dbus exceptions and
// throw snapper or new exceptions. Partly done, see errors.h.
class ProxyConfig
{
public:
ProxyConfig(const map<string, string>& values) : values(values) {}
const map<string, string>& getAllValues() const { return values; }
string getSubvolume() const;
// Return whether the key was found. If the key was not found then value is unchanged.
bool getValue(const string& key, string& value) const;
bool is_yes(const char* key) const;
private:
map<string, string> values;
};
class ProxySnapshot
{
public:
SnapshotType getType() const { return impl->getType(); }
unsigned int getNum() const { return impl->getNum(); }
time_t getDate() const { return impl->getDate(); }
uid_t getUid() const { return impl->getUid(); }
bool isReadOnly() const { return impl->isReadOnly(); }
void setReadOnly(bool read_only, Plugins::Report& report) { impl->setReadOnly(read_only, report); }
unsigned int getPreNum() const { return impl->getPreNum(); }
const string& getDescription() const { return impl->getDescription(); }
const string& getCleanup() const { return impl->getCleanup(); }
const map<string, string>& getUserdata() const { return impl->getUserdata(); }
SMD getSmd() const;
bool isCurrent() const { return impl->isCurrent(); }
uint64_t getUsedSpace() const { return impl->getUsedSpace(); }
void mountFilesystemSnapshot(bool user_request) const
{ impl->mountFilesystemSnapshot(user_request); }
void umountFilesystemSnapshot(bool user_request) const
{ impl->umountFilesystemSnapshot(user_request); }
public:
class Impl
{
public:
virtual ~Impl() {}
virtual SnapshotType getType() const = 0;
virtual unsigned int getNum() const = 0;
virtual time_t getDate() const = 0;
virtual uid_t getUid() const = 0;
virtual bool isReadOnly() const = 0;
virtual void setReadOnly(bool read_only, Plugins::Report& report) = 0;
virtual unsigned int getPreNum() const = 0;
virtual const string& getDescription() const = 0;
virtual const string& getCleanup() const = 0;
virtual const map<string, string>& getUserdata() const = 0;
virtual bool isCurrent() const = 0;
virtual uint64_t getUsedSpace() const = 0;
virtual string mountFilesystemSnapshot(bool user_request) const = 0;
virtual void umountFilesystemSnapshot(bool user_request) const = 0;
};
ProxySnapshot(Impl* impl) : impl(impl) {}
Impl& get_impl() { return *impl; }
const Impl& get_impl() const { return *impl; }
private:
std::unique_ptr<Impl> impl;
};
class ProxySnapshots
{
public:
virtual ~ProxySnapshots() {}
typedef list<ProxySnapshot>::iterator iterator;
typedef list<ProxySnapshot>::const_iterator const_iterator;
iterator begin() { return proxy_snapshots.begin(); }
const_iterator begin() const { return proxy_snapshots.begin(); }
iterator end() { return proxy_snapshots.end(); }
const_iterator end() const { return proxy_snapshots.end(); }
const_iterator getCurrent() const { return proxy_snapshots.begin(); }
virtual iterator getDefault() = 0;
virtual const_iterator getDefault() const = 0;
virtual iterator getActive() = 0;
virtual const_iterator getActive() const = 0;
iterator find(unsigned int i);
const_iterator find(unsigned int i) const;
iterator findNum(const string& str);
const_iterator findNum(const string& str) const;
std::pair<iterator, iterator> findNums(const string& str, const string& delim = "..");
const_iterator findPre(const_iterator post) const;
iterator findPost(iterator pre);
const_iterator findPost(const_iterator pre) const;
void emplace_back(ProxySnapshot::Impl* value) { proxy_snapshots.emplace_back(value); }
void erase(iterator it) { proxy_snapshots.erase(it); }
protected:
list<ProxySnapshot> proxy_snapshots;
};
class ProxyComparison;
class ProxySnapper
{
public:
virtual ~ProxySnapper() {}
virtual const string& configName() const = 0;
virtual ProxyConfig getConfig() const = 0;
virtual void setConfig(const ProxyConfig& proxy_config) = 0;
virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd, Plugins::Report& report) = 0;
virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
const SCD& scd, Plugins::Report& report) = 0;
virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd, Plugins::Report& report) = 0;
virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd, Plugins::Report& report) = 0;
virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
const SCD& scd, Plugins::Report& report) = 0;
virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd, Plugins::Report& report) = 0;
virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose, Plugins::Report& report) = 0;
virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
bool mount) = 0;
virtual void syncFilesystem() const = 0;
virtual ProxySnapshots& getSnapshots() = 0;
virtual const ProxySnapshots& getSnapshots() const = 0;
virtual void setupQuota() = 0;
virtual void prepareQuota() const = 0;
virtual QuotaData queryQuotaData() const = 0;
virtual FreeSpaceData queryFreeSpaceData() const = 0;
virtual void calculateUsedSpace() const = 0;
virtual void lock_config() const = 0;
virtual void unlock_config() const = 0;
};
class ProxySnappers
{
public:
static ProxySnappers createDbus();
static ProxySnappers createLib(const string& target_root);
void createConfig(const string& config_name, const string& subvolume, const string& fstype,
const string& template_name, Plugins::Report& report)
{ return impl->createConfig(config_name, subvolume, fstype, template_name, report); }
void deleteConfig(const string& config_name, Plugins::Report& report)
{ return impl->deleteConfig(config_name, report); }
ProxySnapper* getSnapper(const string& config_name)
{ return impl->getSnapper(config_name); }
map<string, ProxyConfig> getConfigs() const
{ return impl->getConfigs(); }
/**
* This function needs a few works: The Snapper class does not have a Plugin::Report
* object. The individual functions of the Snapper class have. For for proxy-lib this
* call is a no-op. For proxy-dbus the server is queried which has a per client
* Plugin::Report object.
*/
Plugins::Report get_plugins_report() const
{ return impl->get_plugins_report(); }
vector<string> debug() const
{ return impl->debug(); }
public:
class Impl
{
public:
virtual ~Impl() {}
virtual void createConfig(const string& config_name, const string& subvolume,
const string& fstype, const string& template_name, Plugins::Report& report) = 0;
virtual void deleteConfig(const string& config_name, Plugins::Report& report) = 0;
virtual ProxySnapper* getSnapper(const string& config_name) = 0;
virtual map<string, ProxyConfig> getConfigs() const = 0;
virtual Plugins::Report get_plugins_report() const = 0;
virtual vector<string> debug() const = 0;
};
ProxySnappers(Impl* impl) : impl(impl) {}
Impl& get_impl() { return *impl; }
const Impl& get_impl() const { return *impl; }
private:
std::unique_ptr<Impl> impl;
};
class ProxyComparison
{
public:
const Files& getFiles() const { return impl->getFiles(); }
public:
class Impl
{
public:
virtual ~Impl() {}
virtual const Files& getFiles() const = 0;
};
ProxyComparison(Impl* impl) : impl(impl) {}
Impl& get_impl() { return *impl; }
const Impl& get_impl() const { return *impl; }
private:
std::unique_ptr<Impl> impl;
};
}
#endif