mirror of
https://github.com/openSUSE/snapper.git
synced 2026-02-06 09:46:06 +01:00
367 lines
10 KiB
C++
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
|