borgcube.core package¶
borgcube.core.hookspec module¶
-
borgcube.core.hookspec.
borgcube_startup
(process)[source]¶ Called after application is configured and all plugins were discovered.
process identifies the process and may be None. Otherwise it can be one of:
- “borgcubed”
- “proxy”
- “manage” (this may include running the web frontend)
-
borgcube.core.hookspec.
borgcube_job_blocked
(job, blocking_jobs)[source]¶ Called to sort out whether job is blocked by any blocking_jobs.
blocking_jobs is a list of jobs that are aimed at the same repository as job and whose state is not in Job.State.STABLE.
Remove any false positives from blocking_jobs that might be there because of special snowflake semantics with your jobs.
If any blocking_jobs remain, job is considered blocked.
-
borgcube.core.hookspec.
borgcube_job_pre_state_update
(job, current_state, target_state)[source]¶ Called before the state of job is updated from current_state (BackupJob.State) to target_state (ditto).
-
borgcube.core.hookspec.
borgcube_job_post_state_update
(job, prior_state, current_state)[source]¶ Called after the state of job was updated from prior_state (BackupJob.State) to current_state.
job is already saved, but the database transaction has not yet completed.
-
borgcube.core.hookspec.
borgcube_job_post_force_state
(job, forced_state)[source]¶ Called after the state of job was forced to forced_state (BackupJob.State).
-
borgcube.core.hookspec.
borgcube_job_failure_cause
(job, kind, kwargs)[source]¶ Called after the failure cause (defined by kind (str) and it’s kwargs) is set for job.
-
borgcube.core.hookspec.
borgcube_job_created
(job)[source]¶ Called when a job was created, but before it will be executed.
borgcube.core.models module¶
-
class
borgcube.core.models.
NumberTree
[source]¶ Bases:
BTrees.LOBTree.LOBTree
-
insert
(key, value) → 0 or 1[source]¶ Add an item if the key is not already used. Return 1 if the item was added, or 0 otherwise.
-
reversed
()¶ Yield values in descending (high to low) key order..
-
-
class
borgcube.core.models.
Evolvable
[source]¶ Bases:
persistent.Persistent
,borgcube.core.models.StringObjectID
,borgcube.core.models.Updateable
Main class for persistent data in BorgCube.
This provides a means for online data migration (“evolution”). For this both objects and classes are versioned through the
version
attribute. When an object is written to the database the currentversion
is stored along with it (via__getstate__
), while retrieving an object may evolve it to the current version of the class.This is best illustrated with a simple example:
class Dog(Evolvable): def __init__(self): pass
Fair enough. We acquire some dogs, but notice we forgot a few things, which we want to add:
class Dog(Evolvable): def __init__(self, good_boy, food_bowl): self.good_boy = good_boy self.food_bowl = food_bowl
New code will expect these attributes to be available, so it would fail with older dogs. We fix this through evolution:
class Dog(Evolvable): version = 2 @evolve(from_version=1, to_version=2) def added_important_things(self): self.good_boy = True self.food_bowl = FoodBowl.find_free_bowl_or_create_one() def __init__(self, good_boy, food_bowl): self.good_boy = good_boy self.food_bowl = food_bowl
If now an old dog (version=1) is loaded, the system will notice that and run
added_important_things
, which will perform the changes needed to match version=2 dogs.Note that this is subject to the regular transaction rules, so when, after loading old objects, no commit happens, the in-database data isn’t updated – the evolution would happen again next time they are loaded.
You can also provide shortcuts (or leaps), if there is a better upgrade path between certain versions, like so:
class Dog(Evolvable): version = 7 @evolve(from_version=2, to_version=7): def direct_upgrade_2to7(self): ... @evolve(from_version=2, to_version=3): def upgrade_2to3(self): ...
Note that evolution isn’t a SAT-solver, but works in a short-circuit way; in each step the largest leap is selected. Hidden paths are not considered.
-
version
= 1¶
-
-
class
borgcube.core.models.
DataRoot
[source]¶ Bases:
borgcube.core.models.Evolvable
The DataRoot has the following attributes:
Variables: - repositories – a
PersistentList
ofRepository
instances. - archives – an
OOBTree
mapping hex archive IDs toArchive
instances. - clients – an
OOBTree
mapping host names toClient
instances. - jobs – an
OOBTree
mapping TODO toJob
instances. - jobs_by_state – an
OOBTree
mapping job states to trees ofJob
instances. - schedules – a
PersistentList
ofSchedule
instances. - ext – a
PersistentDict
of extension data (seeplugin_data
, do not use directly).
-
version
= 6¶
-
plugin_data
(factory)[source]¶ Return an instance generated (at some point in time) by factory.
This should be used for storing plugin data, eg.:
class AwesomePluginData(Evolvable): name = 'awesome-plugin' def __init__(self): self.some_data = OOBTree() ... def show_some_data(request): # You might want to just put this in a separate helper (below) plugdat = data_root().plugin_data(AwesomePluginData) return TemplateResponse(...) # A sample helper def plugin_root(): return data_root().plugin_data(AwesomePluginData)
A good name would be the entrypoint name of your plugin, or it’s root module/package name.
The name attribute on factory is not mandatory. If it is not present the qualified class name is used instead (eg.
awesomeplugin.data.AwesomePluginData
)
- repositories – a
-
class
borgcube.core.models.
Repository
(name, url, description='', repository_id='', remote_borg='borg')[source]¶ Bases:
borgcube.core.models.Evolvable
-
version
= 2¶
-
location
¶
-
class
Form
(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None)[source]¶ Bases:
django.forms.forms.Form
description
=django.forms.CharField
url
=django.forms.CharField
repository_id
=django.forms.CharField
-
-
class
borgcube.core.models.
Archive
(id, repository, name, client=None, job=None, comment='', nfiles=0, original_size=0, compressed_size=0, deduplicated_size=0, duration=datetime.timedelta(0), timestamp=None, timestamp_end=None)[source]¶ Bases:
borgcube.core.models.Evolvable
-
version
= 2¶
-
ts
¶
-
-
class
borgcube.core.models.
RshClientConnection
(remote, rsh='ssh', rsh_options=None, ssh_identity_file=None, remote_borg='borg', remote_cache_dir=None)[source]¶ Bases:
borgcube.core.models.Evolvable
-
remote
= ''¶
-
rsh
= 'ssh'¶
-
rsh_options
= None¶
-
ssh_identity_file
= None¶
-
remote_borg
= 'borg'¶
-
remote_cache_dir
= None¶
-
class
Form
(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None)[source]¶ Bases:
django.forms.forms.Form
remote
=django.forms.CharField
rsh_options
=django.forms.CharField
ssh_identity_file
=django.forms.CharField
remote_borg
=django.forms.CharField
remote_cache_dir
=django.forms.CharField
-
prefix
= 'connection'¶
-
-
-
class
borgcube.core.models.
Client
(hostname, description='', connection=None)[source]¶ Bases:
borgcube.core.models.Evolvable
-
version
= 2¶
-
class
Form
(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None)[source]¶ Bases:
django.forms.forms.Form
hostname
=django.forms.CharField
description
=django.forms.CharField
-
-
class
borgcube.core.models.
Job
(repository=None)[source]¶ Bases:
borgcube.core.models.Evolvable
Core job model.
A job is some kind of task that is run by borgcubed. Normally these are concerned with a repository, but if that’s not the case - the field is nullable.
Steps to implement a Job class:
- Derive from this
- Define additional states, if necessary, by deriving the State class in your model from
Job.State
- borgcubed needs to know how to run the job, therefore set executor to your JobExecutor subclass.
- Relevant hooks:
borgcube_job_blocked
,borgcubed_job_exit
.
-
short_name
= 'job'¶
-
executor
¶ alias of
JobExecutor
-
class
State
[source]¶ Bases:
object
-
job_created
= 'job_created'¶
-
done
= 'done'¶
-
failed
= 'failed'¶
-
cancelled
= 'cancelled'¶
-
STABLE
= {'cancelled', 'done', 'failed', 'job_created'}¶
-
-
duration
¶
-
failed
¶
-
done
¶
-
stable
¶
-
class
borgcube.core.models.
TriggerID
(trigger, enabled=True, access=(), comment='')[source]¶ Bases:
borgcube.core.models.Evolvable
Defined access contexts are:
- anonymous-web
- local-cli
-
class
borgcube.core.models.
Schedule
(name, recurrence, recurrence_enabled=True, description='')[source]¶ Bases:
borgcube.core.models.Evolvable
-
version
= 4¶
-
class
Form
(data, *args, **kwargs)[source]¶ Bases:
django.forms.forms.Form
description
=django.forms.CharField
recurrence_enabled
=django.forms.BooleanField
recurrence_start
=django.forms.DateTimeField
recurrence
=recurrence.forms.RecurrenceField
-
-
class
borgcube.core.models.
ScheduledAction
(schedule)[source]¶ Bases:
borgcube.core.models.Evolvable
,borgcube.core.models.DottedPath
Implement this to add schedulable actions to the scheduler.
Make sure that your implementation is imported, since these are implicitly discovered subclasses.
-
name
= ''¶
-
class
Form
(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None)[source]¶ Bases:
django.forms.forms.Form
The form that should be presented for adding/modifying this action.
This can be a ModelForm or modify the DB; the transaction is managed for you, and no additional transaction management should be needed.
The usual form rules apply, however, note that .cleaned_data must be JSON serializable if .is_valid() returns true. This data will be used for instanciating the action class (py_args).
.save() will be called with no arguments regardless of type, if it exists.
-