Skip to content

Commit

Permalink
FD python plugin baseclass and sample plugins
Browse files Browse the repository at this point in the history
Signed-off-by: Marco van Wieringen <marco.van.wieringen@bareos.com>
  • Loading branch information
Maik Aussendorf authored and Marco van Wieringen committed Apr 14, 2014
1 parent ee96b58 commit c96b8a9
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/plugins/filed/BareosFdPluginBaseclass.py
@@ -0,0 +1,136 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Baseclass for Bareos python plugins
# Functions taken and adapted from bareos-fd.py
# (c) Bareos GmbH & Co. KG, Maik Aussendorf
# AGPL v.3

from bareosfd import *
from bareos_fd_consts import *
from os import O_WRONLY, O_CREAT

class BareosFdPluginBaseclass:
''' Bareos python plugin base class '''
def __init__(self, context, plugindef):
DebugMessage(context, 100, "Constructor called in module " + __name__ + "\n");
events = [];
events.append(bEventType['bEventJobEnd']);
events.append(bEventType['bEventEndBackupJob']);
events.append(bEventType['bEventEndFileSet']);
events.append(bEventType['bEventHandleBackupFile']);
RegisterEvents(context, events);
# get some static Bareos values
self.fdname = GetValue(context, bVariable['bVarFDName']);
self.jobId = GetValue(context, bVariable['bVarJobId']);
self.client = GetValue(context, bVariable['bVarClient']);
self.level = GetValue(context, bVariable['bVarLevel']);
self.jobName = GetValue(context, bVariable['bVarJobName']);
self.workingdir = GetValue(context, bVariable['bVarWorkingDir']);
DebugMessage(context, 100, "FDName = " + self.fdname + " - BareosFdPluginBaseclass\n");
DebugMessage(context, 100, "WorkingDir = " + self.workingdir + " jobId: " + str(self.jobId) + "\n");

def parse_plugin_definition(self,context, plugindef):
DebugMessage(context, 100, "plugin def parser called with " + plugindef + "\n");
# Parse plugin options into a dict
self.options = dict();
plugin_options = plugindef.split(":");
for current_option in plugin_options:
key,sep,val = current_option.partition("=");
DebugMessage(context, 100, "key:val: " + key + ':' + val + "\n");
if val == '':
continue;
else:
self.options[key] = val;
# you should overload this method with your own and do option checking here, return bRCs['bRC_Error'], if options are not ok
# or better call super.parse_plugin_definition in your own class and make sanity check on self.options afterwards
return bRCs['bRC_OK'];


def plugin_io(self, context, IOP):
DebugMessage(context, 100, "plugin_io called with " + str(IOP) + "\n");

FNAME = IOP.fname;
if IOP.func == bIOPS['IO_OPEN']:
try:
if IOP.flags & (O_CREAT | O_WRONLY):
self.file = open(FNAME, 'wb');
else:
self.file = open(FNAME, 'rb');
except:
IOP.status = -1;
return bRCs['bRC_Error'];

return bRCs['bRC_OK'];

elif IOP.func == bIOPS['IO_CLOSE']:
self.file.close();
return bRCs['bRC_OK'];

elif IOP.func == bIOPS['IO_SEEK']:
return bRCs['bRC_OK'];

elif IOP.func == bIOPS['IO_READ']:
IOP.buf = bytearray(IOP.count);
IOP.status = self.file.readinto(IOP.buf);
IOP.io_errno = 0
return bRCs['bRC_OK'];

elif IOP.func == bIOPS['IO_WRITE']:
IOP.status = self.file.write(IOP.buf);
IOP.io_errno = 0
return bRCs['bRC_OK'];


def handle_plugin_event(self, context, event):
if event == bEventType['bEventJobEnd']:
DebugMessage(context, 100, "handle_plugin_event called with bEventJobEnd\n");

elif event == bEventType['bEventEndBackupJob']:
DebugMessage(context, 100, "handle_plugin_event called with bEventEndBackupJob\n");

elif event == bEventType['bEventEndFileSet']:
DebugMessage(context, 100, "handle_plugin_event called with bEventEndFileSet\n");

else:
DebugMessage(context, 100, "handle_plugin_event called with event" + str(event) + "\n");

return bRCs['bRC_OK'];


def start_backup_file(self,context, savepkt):
DebugMessage(context, 100, "start_backup called\n");
# Base method, we do not add anything, overload this method with your implementation to add files to backup fileset
return bRCs['bRC_Skip'];


def end_backup_file(self, context):
DebugMessage(context, 100, "end_backup_file() entry point in Python called\n")
return bRCs['bRC_OK'];

def start_restore_file(self, context, cmd):
DebugMessage(context, 100, "start_restore_file() entry point in Python called with" + str(cmd) + "\n")
return bRCs['bRC_OK'];

def end_restore_file(self,context):
DebugMessage(context, 100, "end_restore_file() entry point in Python called\n")
return bRCs['bRC_OK'];

def restore_object_data(self, context, ROP):
DebugMessage(context, 100, "restore_object_data called with " + str(ROP) + "\n");
return bRCs['bRC_OK'];

def create_file(self,context, restorepkt):
DebugMessage(context, 100, "create_file() entry point in Python called with" + str(restorepkt) + "\n")
restorepkt.create_status = bCFs['CF_EXTRACT'];
return bRCs['bRC_OK'];

def check_file(self,context, fname):
DebugMessage(context, 100, "check_file() entry point in Python called with" + str(fname) + "\n")
return bRCs['bRC_OK'];

def handle_backup_file(self,context, savepkt):
DebugMessage(context, 100, "handle_backup_file called with " + str(savepkt) + "\n");
return bRCs['bRC_OK'];

# vim: ts=4 tabstop=4 expandtab shiftwidth=4 softtabstop=4
77 changes: 77 additions & 0 deletions src/plugins/filed/BareosFdPluginLocalFileset.py
@@ -0,0 +1,77 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Bareos python plugins class that adds files from a local list to the backup fileset
# (c) Bareos GmbH & Co. KG
# AGPL v.3
# Author: Maik Aussendorf

from bareosfd import *
from bareos_fd_consts import *
import os
from BareosFdPluginBaseclass import *
import BareosFdWrapper


class BareosFdPluginLocalFileset (BareosFdPluginBaseclass):
'''
Simple Bareos-FD-Plugin-Class that parses a file and backups all files listed there
Filename is taken from plugin argument 'filename'
'''

def parse_plugin_definition(self,context, plugindef):
'''
Parses the plugin argmuents and reads files from file given by argument 'filename'
'''
BareosFdPluginBaseclass.parse_plugin_definition(self, context, plugindef);
if (not 'filename' in self.options):
DebugMessage(context, 100, "Option \'filename\' not defined.\n");
return bRCs['bRC_Error'];
DebugMessage(context, 100, "Using " + self.options['filename'] + " to search for local files\n");
if os.path.exists (self.options['filename']):
try:
config_file = open (self.options['filename'],'rb');
except:
DebugMessage(context, 100, "Could not open file " + self.options['filename'] + "\n");
return bRCs['bRC_Error'];
else:
DebugMessage(context, 100, "File " + self.options['filename'] + " does not exist\n");
return bRCs['bRC_Error'];
self.files_to_backup = config_file.read().splitlines();
return bRCs['bRC_OK'];


def start_backup_file(self,context, savepkt):
'''
Defines the file to backup and creates the savepkt. In this example only files (no directories)
are allowed
'''
DebugMessage(context, 100, "start_backup called\n");
if not self.files_to_backup:
DebugMessage(context, 100, "No files to backup\n");
return bRCs['bRC_Skip'];

file_to_backup = self.files_to_backup.pop();
DebugMessage(context, 100, "file: " + file_to_backup + "\n");

statp = StatPacket();
savepkt.statp = statp;
savepkt.fname = file_to_backup;
savepkt.type = bFileType['FT_REG'];

JobMessage(context, bJobMessageType['M_INFO'], "Starting backup of " + file_to_backup + "\n");
return bRCs['bRC_OK'];

def end_backup_file(self, context):
'''
Here we return 'bRC_More' as long as our list files_to_backup is not empty and
bRC_OK when we are done
'''
DebugMessage(context, 100, "end_backup_file() entry point in Python called\n")
if self.files_to_backup:
return bRCs['bRC_More'];
else:
return bRCs['bRC_OK'];


# vim: ts=4 tabstop=4 expandtab shiftwidth=4 softtabstop=4
41 changes: 41 additions & 0 deletions src/plugins/filed/BareosFdWrapper.py
@@ -0,0 +1,41 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# The BareosFdWrapper module. Here is a global object bareos_fd_plugin_object and wrapper functions, which
# are directly called out of the bareos-fd. They are intended to pass the call to a method of an
# object of type BareosFdPluginBaseclass (or derived)

# use this as global plugin object among your python-fd-plugin modules
bareos_fd_plugin_object=None

def parse_plugin_definition(context, plugindef):
return bareos_fd_plugin_object.parse_plugin_definition(context, plugindef);

def handle_plugin_event(context, event):
return bareos_fd_plugin_object.handle_plugin_event(context, event);

def start_backup_file(context, savepkt):
return bareos_fd_plugin_object.start_backup_file(context, savepkt);

def end_backup_file(context):
return bareos_fd_plugin_object.end_backup_file(context);

def start_restore_file(context, cmd):
return bareos_fd_plugin_object.start_restore_file(context,cmd);

def end_restore_file(context):
return bareos_fd_plugin_object.end_restore_file(context);

def restore_object_data(context, ROP):
return bareos_fd_plugin_object.restore_object_data(context, ROP);

def plugin_io(context, IOP):
return bareos_fd_plugin_object.plugin_io(context, IOP);

def create_file(context, restorepkt):
return bareos_fd_plugin_object.create_file(context, restorepkt)

def check_file(context, fname):
return bareos_fd_plugin_object.check_file(context, fname)

def handle_backup_file(context, savepkt):
return bareos_fd_plugin_object.handle_backup_file(context, savepkt)
26 changes: 26 additions & 0 deletions src/plugins/filed/bareos-fd-local-fileset.py
@@ -0,0 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Bareos-fd-local-fileset a simple example for a python Bareos FD Plugin using BareosFdPluginLocalFileset
# The plugin argument 'filename' is used to read all files listed in that file and add it to the fileset

# Provided by the Bareos FD Python plugin interface
from bareosfd import *
from bareos_fd_consts import *

# This module contains the wrapper functions called by the Bareos-FD, the functions call the corresponding
# methods from your plugin class
from BareosFdWrapper import *

# This module contains the used plugin class
from BareosFdPluginLocalFileset import *

def load_bareos_plugin(context, plugindef):
'''
This function is called by the Bareos-FD to load the plugin
We use it to instantiate the plugin class
'''
# BareosFdWrapper.bareos_fd_plugin_object is the module attribute that holds the plugin class object
BareosFdWrapper.bareos_fd_plugin_object = BareosFdPluginLocalFileset (context, plugindef);
return bRCs['bRC_OK'];

# the rest is done in the Plugin module
19 changes: 19 additions & 0 deletions src/plugins/filed/bareos-fd-mock-test.py
@@ -0,0 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Bareos-fd-mock-test a simple example for a python Bareos FD Plugin using the baseclass
# and doing nothing
# You may take this as a skeleton for your plugin

from bareosfd import *
from bareos_fd_consts import *
from os import O_WRONLY, O_CREAT

from BareosFdPluginBaseclass import *
from BareosFdWrapper import *

def load_bareos_plugin(context, plugindef):
DebugMessage(context, 100, "------ Plugin loader called with " + plugindef + "\n");
BareosFdWrapper.plugin_object = BareosFdPluginBaseclass (context, plugindef);
return bRCs['bRC_OK'];

# the rest is done in the Plugin module

0 comments on commit c96b8a9

Please sign in to comment.