Bacula plug-in writing initial knowledge

Source: Internet
Author: User
Tags bool error code win32 win32 error bacula

The Bacula plugin has the following functions Newplugin (Bpcontext *ctx)
Freeplugin (Bpcontext *ctx)
Getpluginvalue (Bpcontext *ctx, pvariable var, void *value)
Setpluginvalue (Bpcontext *ctx, pvariable var, void *value)
Handlepluginevent (Bpcontext *ctx, bevent *event, void *value)
Startbackupfile (Bpcontext *ctx, struct save_pkt *sp)
Endbackupfile (Bpcontext *ctx)
Startrestorefile (Bpcontext *ctx, const char *cmd)
CreateFile (Bpcontext *ctx, struct restore_pkt *rp)
SetFileAttributes (Bpcontext *ctx, struct restore_pkt *rp)
Endrestorefile (Bpcontext *ctx)
Pluginio (Bpcontext *ctx, struct io_pkt *io)

BOOL Checkfile (Bpcontext *ctx, char *fname)

Similarly, it has several entry points

BRC registerbaculaevents (Bpcontext *ctx, ...)
BRC Getbaculavalue (Bpcontext *ctx, bvariable var, void *value)
BRC Setbaculavalue (Bpcontext *ctx, bvariable var, void *value)
BRC jobmessage (Bpcontext *ctx, const char *file, int line, int type, utime_t mtime, const char *FMT, ...)
BRC DebugMessage (Bpcontext *ctx, const char *file, int line, int. level, const char *FMT, ...)
void Baculamalloc (Bpcontext *ctx, const char *file, int line, size_t size)
void Baculafree (Bpcontext *ctx, const char *file, int line, void *mem)

These are all defined in the BPLUGINFO.C.

Plug-ins are implemented in a dynamic shared object program or DLL (Win32), and there is a configuration in bacula-fd.conf that will load the-fd.so or-fd.dll (Win32) in the directory you configured when the FD starts.

In general, plug-ins can be called in 3 ways: first, when a particular event is detected in the Bacula, it will take turns to pass the event to the plugin that has already been loaded, which is similar to the script run, and the events are similar. Once the plugin gets control, it interacts with the Bacula by acquiring and setting the Bacula variable. In this way, he is very similar to the script. There are few Bacula variables defined at the moment, but they are executed when needed and very extensible.

You can register the plugin to receive events that are not normally received, such as checking each file for backup and restore. But it hasn't been realized yet.

The second plugin is useful and has been implemented in our current version, which is called the command plugin. Like other plug-ins, he will be ruled as important events as described above, except that this type of plugin can accept command-line-

Plugin = <command-string>

This command will define a file set directory, and "file=" function very much like (PS: This section of the feeling is not translated), when the Bacula backup encountered this instruction, it will be the command inside the commands passed to the plugin. This allows the plugin to back up any files or folders on the system. You can also create a virtual folder in the directory containing the recovered data, and there is no need to correspond to the actual folder above the system ——— PS: I don't understand.

The third is the choice of plug-ins, which are useful for implementing custom filtering of data. For example, you can implement a compression algorithm in a very simple way. Bacula will invoke the plugin for each file that is selected in Fileset (according to Wild/regex/exclude/include rules). As with all plugins, it will be notified of events as above, and in addition, the plugin can be placed in a selection group like this:

Fileset {
Name = Testfs
Include {
Options {
Compression = GZIP1
Signature = MD5
Wild = "*.txt"
Plugin = <command-string>
}
File =/
}
}

Loading Plugins

When FD loads the plugins, it will call the OS ask two entry points (Oadplugin and Unloadplugin) and then invoke the two entry points of Loadplugin

Bacula through this call to pass information to the plugin, but also in this way to get information from the plug-in to use plug-ins. The Bacula will then invoke the specific function defined by the Loadplugin interface.

Unloadplugin is called when Bacula exits plugin (that is, Bacula does not need to use plugin).

These two functions are

BRC Loadplugin (binfo *lbinfo, Bfuncs *lbfuncs, PInfo **pinfo, Pfuncs **pfuncs) and BRC Unloadplugin ()

Although they are defined in C, they can be written in any language, preferably C or C + +


The BRC and parameters are defined in Src/filed/fd-plugins.h, plus src/lib/plugins.h, which basically defines all plug-in interfaces. In this header file, it contains the following files:

#include <sys/types.h>
#include "Config.h"
#include "Bc_types.h"
#include "Lib/plugins.h"
#include <sys/stat.h>

In addition to the BC Types.h and con fig.h plugin definition is used for the smallest amount of code

Bc_types.h is to ensure that the data type definition and Bacula core code are consistent.

The return code is defined as follows:

typedef enum {
BRC_OK = 0,/* OK */
Brc_stop = 1,/* Stop calling other plugins */
Brc_error = 2,/* Some kind of Error */
Brc_more = 3,/* More files to backup */
Brc_term = 4,/* Unload Me * *
Brc_seen = 5,/* Return code from Checkfiles */
Brc_core = 6,/* Let Bacula Core handles the This file */
Brc_skip = 7,/* Skip The proposed file */
} BRC;

We want to make the Bacula libbac.a into a shared object so that the plugin can use more bacula things. But for the this first cut, we try to make it less dependent on Bacula


Loadplugin

Loadplugin is called immediately after the Bacula's FD service starts and loads the plugin for the first time. This entry point is called only once during the execution of the FD. The first two parameters are the information that Bacula passes to the plug-in, and the latter two are information that the plug-in itself needs to pass to Bacula. The prototype is as follows:

BRC Loadplugin (binfo * Lbinfo,bfuncs * lbfuncs,pinfo * * Pinfo,pfuncs * Pfuncs)

The parameters are as follows:

Lbinfo

In general, this is information about Bacula, currently, only the value of the interface version of the Bacula plug-in is defined in the binfo struct, now defined as 1,size is the size of the structure of the byte, the following is the definition of binfo

typedef struct S_BACULAINFO {
uint32_t size;
uint32_t version;
} binfo;


Lbfuncs

The BFUNCS structure defines the callback function entry point inside the Bacula, and the plugin can use register events, get Bacula values, set Bacula values, and send messages to the Job OU Tput or debug output, defined as follows:

typedef struct S_BACULAFUNCS {
uint32_t size;
uint32_t version;
BRC (*registerbaculaevents) (Bpcontext *ctx, ...);
BRC (*getbaculavalue) (Bpcontext *ctx, bvariable var, void *value);
BRC (*setbaculavalue) (Bpcontext *ctx, bvariable var, void *value);
BRC (*jobmessage) (Bpcontext *ctx, const char *file, int line,
int type, utime_t mtime, const char *fmt, ...);
BRC (*debugmessage) (Bpcontext *ctx, const char *file, int line,
int level, const char *FMT, ...);
void * (*baculamalloc) (Bpcontext *ctx, const char *file, int line,
size_t size);
void (*baculafree) (Bpcontext *ctx, const char *file, int line, void *mem);
} Bfuncs;

PInfo

When Loadplugin is called, the plugin must initialize an information structure about the plug-in and return a pointer to the struct to Bacula

typedef struct S_PLUGININFO {
uint32_t size;
uint32_t version;
const char *plugin_magic;
const char *plugin_license;
const char *plugin_author;
const char *plugin_date;
const char *plugin_version;
const char *plugin_description;
} PInfo;

Version is the current version of the plug-in interface, which is currently 1, and the plugin will not work (not implemented) when the interface version is different from the current Bacula version.

Plugin_magic is a pointer to the text string "Fdplugindata", which is a sanity check, when the value is not specified, the plugin will not run

Plugin_license points to a pointer to a text string that describes the plug-in license, Bacula only accepts a compatible license (not implemented) "

Plugin_author A pointer to the text name

Plugin_version pointer to a text string containing the plug-in version

Plugin_description pointer to the string that the plugin describes

The pinfo struct must be defined in a static store (because Bacula does not replicate it and may refer to its value at any time after the plug-in is loaded). All of these values have to be (not implemented), and the text string is in ASCII or UTF-8 format.


Pfuncs

After the loadplugin is called, the plug-in must initialize an entry point structure about the plug-in and return a pointer to the struct to Bacula. This structure contains pointers to each entry point that the plugin must give Bacula. When Bacula runs the plug-in normally, it will invoke the defined entry point at a specific time. All the entry points have to be defined.

Pfuncs struct must be defined in a static storage area (as above)

typedef struct S_PLUGINFUNCS {
uint32_t byte size of size;//struct
uint32_t version;//plug-in interface version
BRC (*newplugin) (Bpcontext *ctx);//
BRC (*freeplugin) (Bpcontext *ctx);
BRC (*getpluginvalue) (Bpcontext *ctx, pvariable var, void *value);
BRC (*setpluginvalue) (Bpcontext *ctx, pvariable var, void *value);
BRC (*handlepluginevent) (Bpcontext *ctx, bevent *event, void *value);
BRC (*startbackupfile) (Bpcontext *ctx, struct save_pkt *sp);
BRC (*endbackupfile) (Bpcontext *ctx);
BRC (*startrestorefile) (Bpcontext *ctx, const char *cmd);
BRC (*endrestorefile) (Bpcontext *ctx);
BRC (*pluginio) (Bpcontext *ctx, struct io_pkt *io);
BRC (*createfile) (Bpcontext *ctx, struct restore_pkt *rp);
BRC (*setfileattributes) (Bpcontext *ctx, struct restore_pkt *rp);
BRC (*checkfile) (Bpcontext *ctx, char *fname);
} Pfuncs;



Entry point function

When Bacula calls Loadplugin, the pointers to these subroutines will be passed to Bacula in the PFUNCS structure.

Newplugin (Bpcontext *ctx)

Create a new plug-in instance when the Bacula will be called, generally at the start of the job call, when the 10 jobs run simultaneously, the plugin will have 10 instance. Bpcontext structure experience is passed to the plugin. If a plug-in needs to have a private working store associated with a specific instance of the plug-in, it should create and store a pointer to its private work store from the heap (malloc memory) at pcontext. Note: More than Bacula is a multi-process program, you cannot allow any variable data to be stored in your plugin unless it is indeed intended for global use by the entire plugin. In addition, you must realize that all other threads except the first and last Call plug-ins (Loadplugin and Unloadplugin) will be called by the corresponding to a Bacula Job. Bpcontext will remain the same, so you can save special data on your private job inside

typedef struct S_BPCONTEXT {
void *pcontext; /* Plugin Private context */
void *bcontext; /* Bacula Private context */
} Bpcontext;

This context pointer is passed as the first argument to all the entry points within the Bacula invocation plug-in. Needless to say, plug-ins should not change the Bcontext variable, which is an instance of Bacula's private context pointer to this plugin (work).


Freeplugin (Bpcontext *ctx)

This interface is called when instance is no longer needed, and the plug-in needs to release all the memory allocated by this instance, which unloadplugin different, and the other instance will continue to run, If the other jobs start, Newplugin will be called again.


Getpluginvalue (Bpcontext *ctx, pvariable var, void *value)

Bacula will call this function to get the plug-in variable, not yet called

Setpluginvalue (Bpcontext *ctx, pvariable var, void *value)

Set the variables in the plugin, not currently called

Handlepluginevent (Bpcontext *ctx, bevent *event, void *value)

Call this function when Bacula encounters the following: In fact, the function is that when the Bacula runtime plug-in gets control and knows what's going on in the job. It can be likened to runscript functions, calling external programs and scripts, and very similar to the Bacula Python interface. When the plug-in is called, Bacula passes the pointer of the bevent struct to the plugin, which looks like this:

typedef struct S_BEVENT {
uint32_t EventType;
} bevent;

Defines the event that is caused by a event,bacula that passes a pointer value associated with the event for each one. If there is no value associated with this event, Bacula passes a null pointer, so the plug-in must always check the variable pointer carefully before releasing the dependency.


The current events list is as follows:

typedef enum {
Beventjobstart = 1,
Beventjobend = 2,
Beventstartbackupjob = 3,
Beventendbackupjob = 4,
Beventstartrestorejob = 5,
Beventendrestorejob = 6,
Beventstartverifyjob = 7,
Beventendverifyjob = 8,
Beventbackupcommand = 9,
Beventrestorecommand = 10,
Beventlevel = 11,
Beventsince = 12,
Beventcancelcommand = +,/* Executed by another thread */

/* Just before Beventvsspreparesnapshot */
Beventvssbackupaddcomponents = 14,


Beventvssrestoreloadcomponentmetadata = 15,
beventvssrestoresetcomponentsselected = 16,
Beventrestoreobject = 17,
Beventendfileset = 18,
Beventplugincommand = 19,
Beventvssbeforecloserestore = 21,


/* ADD drives to VSS snapshot
* Argument:char[27] Drivelist
* You need to add them without duplicates,
* See Fd_common.h add_drive () copy_drives () to get help
*/
Beventvsspreparesnapshot = 22,
Beventoptionplugin = 23,
Beventhandlebackupfile = Used with Options Plugin */


} Beventtype;


Beventjobstart Job starts with the call, including jobid=nnn Job=job-name

Beventjobend Job End

Beventstartbackupjob Backup Start

Beventendbackupjob Backup End

Beventstartrestorejob Restore Start

Beventendrestorejob Restore End

Beventstartverifyjob Verification Work started

Beventendverifyjob verification work is over

Beventbackupcommand is called before Beventstartbackupjob, passing the command (that is, after plugin=) to the plugin. Note: If you want to back up the file, it is important to 1th, copy the command string to your pcontext zone, so you will know, when performing a backup, how to back up and what the user wants to call it

Beventrestorecommand called before Beventstartrestorejob, the rest of the above

Beventlevel when level is called because the new job is set, it is a 32-bit integer that displays the job's level code

Beventsince when since time is called when a new job is set, is the last job runtime time_t time

Beventcancelcommand is called when a running job is canceled. This is sent by a different thread.

Beventvssbackupaddcomponents

Beventplugincommand in the current Fileset call, the event can only be passed to the command inside the specified plug-in, the parameter is Plugincommand

Beventhandlebackupfile when using a selective plug-in is called by every file in the file set, if the plug-in returns CF_OK, it will be used for backup and if Cf_skip is returned, the file will be ignored. Something else will use the Bacula core feature to back up files


Startbackupfile (Bpcontext *ctx, struct save_pkt *sp)

Only your plugin is a command plug-in and is called when the "Plugin =" command is encountered, and is called at backup time. Bacula provides a pointer to the SAVE_PKT struct, and you must fill in the "Properties" data for this file.

struct SAVE_PKT {
int32_t pkt_size; /* Size of this packet */
Char *fname; /* Full path and filename */
Char *link; /* Link Name if any */
struct stat STATP; /* System stat () packet for file */
int32_t type; /* FT_XX for this file */
uint32_t flags; /* Bacula Internal flags * *
BOOL Portable; /* Set if data format is portable */
Char *cmd; /* Command */
uint32_t Delta_seq; /* Delta Sequence Number */
Char *object_name; /* Object name to create */
Char *object; /* Restore Object data to save */
int32_t Object_len; /* Restore Object Length */
int32_t index; /* Restore Object Index */
int32_t Pkt_end; /* End Packet Sentinel */
};

The second argument is a pointer to the SAVE_PKT struct. The plugin is responsible for filling in all save_pkt fields. If you back up a real file, in general, you can fill out the STATP structure when a stat system call is made.

If you want to back up something as complex as a database, you have to create a virtual file that does not exist, but it can present what you have backed up. In this case, you have to make sure that the fname string you return is unique and does not conflict with the actual file above the system, and you have to create it yourself in STATP. Sample programs such as BPIPE-FD.C show how to set these fields. You must be careful not to store pointers to the stack area of pointer fields, such as fname and link (PS: This section is not fluent). Because when you return from the function, your stack entry will be destroyed. In this case the solution is malloc () and a pointer after malloc is returned. In order to have no memory leaks, you should store pointers to all allocated memory in the PCONTEXT structure so that you can release it at subsequent calls or termination.

Once the backup is started, Bacula will call Pluginio to read the data for backup. Refer to BPIPE-FD.C, as follows

struct Plugin_ctx *p_ctx = (struct Plugin_ctx *) ctx->pcontext;
time_t now = time (NULL);
Sp->fname = p_ctx->fname;
Sp->statp.st_mode = 0700 | S_ifreg;
Sp->statp.st_ctime = Now;
Sp->statp.st_mtime = Now;
Sp->statp.st_atime = Now;
Sp->statp.st_size =-1;
Sp->statp.st_blksize = 4096;
Sp->statp.st_blocks = 1;
P_ctx->backup = true;
return BRC_OK;

Note: The filename that needs to be created is already created in the command previously passed to the plugin, and is malloc out of the plugin's p_ctx->fname.


In general, the order of processing "Plugin =" commands from Bacula to plug-ins is:

Generates a Beventbackupcommand event corresponding to the specified plug-in and assigns the command string to the plugin.

Send a Startpluginbackup call command to the plugin, which fills in the data needed in SAVE_PKT to save as the file attributes and to put on the V Olume and in the catalog.

Call the Save_file () subroutine inside the Bacula to save the specified file. The plug-in's Pluginio will then be called, and then the read data is started. If it is a virtual file operation, this open is only the plug-in internal behavior, there is no need to open a disk of real files. In the BPIPE-FD.C example, initializing a pipeline, the final plug-in sends a signal to bacula that it is read, and then Bacula calls the function "close" Pluginio.

Endbackupfile (Bpcontext *ctx)

If the backup is complete, return to BRC_OK. If the plugin wants to create some other file and back it up, it has to return to Brc_more (not yet implemented). This is a relatively good time to release the memory of malloc that you have returned to filenames. Don't know ...

Startrestorefile (Bpcontext *ctx, const char *cmd)

CreateFile (Bpcontext *ctx, struct restore_pkt *rp)

SetFileAttributes (Bpcontext *ctx, struct restore_pkt *rp)

Endrestorefile (Bpcontext *ctx)

Pluginio (Bpcontext *ctx, struct io_pkt *io)

Command plug-ins are used to input and output data when backing up and restoring. These are read,write,open,close,lseek-type interfaces that mimic Unix, and the parameters are in the packet. Also for the WIN32 system plug-in must return two additional values:

enum {
Io_open = 1,
Io_read = 2,
Io_write = 3,
Io_close = 4,
Io_seek = 5
};


struct IO_PKT {
int32_t pkt_size; /* Size of this packet */
int32_t func; /* Function Code */
int32_t count; /* Read/write count */
mode_t mode; /* Permissions for created files */
int32_t flags; /* Open Flags */
Char *buf; /* Read/write Buffer */
const char *fname; /* Open filename */
int32_t status; /* Return status */
int32_t Io_errno; /* errno Code */
int32_t Lerror; /* WIN32 Error code */
int32_t whence; /* lseek argument */
boffset_t offset; /* lseek argument */
BOOL Win32; /* WIN32 GetLastError returned */
int32_t Pkt_end; /* End Packet Sentinel */
};

BOOL Checkfile (Bpcontext *ctx, char *fname)

BRC registerbaculaevents (Bpcontext *ctx, ...)

BRC Getbaculavalue (Bpcontext *ctx, bvariable var, void *value)

BRC Setbaculavalue (Bpcontext *ctx, bvariable var, void *value)

BRC jobmessage (Bpcontext *ctx, const char *file, int line, int type, utime_t mtime, const char *FMT, ...)

BRC DebugMessage (Bpcontext *ctx, const char *file, int line, int. level, const char *FMT, ...)

void Baculamalloc (Bpcontext *ctx, const char *file, int line, size_t size)

void Baculafree (Bpcontext *ctx, const char *file, int line, void *mem)


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.