Permalink
Cannot retrieve contributors at this time
Fetching contributors…

Embedding full NDMP support in BAREOS. | |
No filed plugin but a proper implementation with support in | |
the director to act as a NDMP DMA (Data Management Application) | |
and for NDMP tape agent support in the storage daemon for saving | |
data using the NDMP protocol. | |
This code is based on the NDMJOB NDMP reference implementation | |
of Traakan, Inc., Los Altos, CA which has a BSD style license | |
(2 clause one). | |
http://www.traakan.com/ndmjob/index.html | |
We imported the latest actively supported version of this | |
reference NDMP code from the Amanda project. Instead of | |
basing it on glib what Amanda has done we reverted some changes | |
back to the way the latest spinnaker sources of the NDMJOB code | |
deliver things with per OS specific code. | |
The robot and tape simulator are rewritten versions from NDMJOB | |
with support for registering callbacks in the calling code. This | |
way we can implement virtual tape and robot functionality in the | |
storage daemon for handling NDMP backups. | |
There is also some code added for registering authentication | |
callbacks in the calling code. This way we can perform clear | |
text and md5 based authentication against the internal config | |
data we keep in BAREOS native resources. | |
The core fileindex handling code is rewritten to use callback | |
functions for doing the real work. This way we can hook in | |
internal functions into the core file indexing process which | |
happens after a backup and before a restore to fill the | |
files which have been backuped or restored. | |
Some missing initialization, commission and decommission is | |
added although it is empty it is better to have a consistent | |
coding path/style for everything. Added extra destroy method | |
as for some agents a decommission means make it ready for a next | |
run and we want something that does a tear down and cleanup | |
of anything dynamically allocated during a NDMP run. | |
We also added support for telling the initialization upfront | |
what NDMP services it should support. (e.g. DATA MANAGEMENT | |
APPLICATION (DMA), DATA AGENT, TAPE AGENT or ROBOT AGENT) | |
so when we accept a connection in the storage daemon via | |
ndmp_tape we only allow the client to use our NDMP TAPE AGENT | |
and not the ROBOT, DMA and DATA AGENT. See ndm_session structure | |
members ..._agent_enabled. | |
We also rewrote some of the internal structures. Normally | |
a NDMP session is described by a so called ndm_session struct | |
which is a whopping 1442392 bytes (almost 1.4 Mb) in size. | |
The coders decided they would allocate each array up front | |
and as such the total structure is huge. This is not very | |
handy when using it as a base for a shared library as we want | |
to support all agents but possibly not at the same time | |
(even most likely not at the same time.) | |
So the new ndm_session struct has pointers to the individual | |
members and storage is only allocated when things are needed | |
we also only allocate buffers at the time we need them not | |
upfront. For things like directory names or other pathnames | |
we just strdup the actual string and free it on decommission | |
of the data, this saves a lot when PATH_MAX = 1024 bytes and | |
you stuff a directory path of lets say 30 bytes. | |
The DMA and DATA AGENT also keep track of an list of environment | |
variables and a name list structure. In the original code the | |
environment variable list can have a maximum of 1024 entries | |
and 10240 entries for the name list and that is allocated as | |
one big array of either 1024 or 10240 entries. This is | |
madness we rewrote the list code to use a normal linked | |
list so we only need the space to store the actual number | |
of nodes of each list. There is a enumerate function which | |
returns a memory chunk with all entries concatenated which | |
is used for the rpc calls. We keep track of this enumerate | |
buffer in the list descriptor and when the list is torn down | |
it is freed. (We cannot free it earlier as it is needed | |
as buffer for the returning rpc call.) This lingering of | |
a buffer should be no problem as it should be moderate in | |
size now and not the whopping 1024 or 10240 entries anymore. | |
The media table is also rewritten to a linked list and not | |
a fixed list of 40 entries as it was in the old code. | |
This has significant size advantages to give an idea: | |
ndm_control_agent, original size 523000 bytes, new size 928 bytes | |
ndm_data_agent, original size 553232 bytes, new size 304 bytes | |
ndm_tape_agent, original size 263388 bytes, new size 228 bytes | |
ndm_plumbing, original size 102592 bytes, new size 20 bytes | |
As we initialize some things now later we needed to add some | |
extra checks and things may core dump due to dereferencing | |
a null pointer. We decided to take that as a risk and fix | |
those problems which we encounter them. Adding extra checks | |
all over the place checking if things are not initialized is | |
also gross overkill and as NDMP is a nice state machine we | |
probably can get away by putting checks in strategic places. | |
The test routines are put into an extra define named | |
NDMOS_OPTION_NO_TEST_AGENTS so one can disable them for a | |
production shared library. | |
Extra support for getaddrinfo() is added to the library | |
which supercedes the old and by POSIX deprecated gethostbyname() | |
interface. Also the implementation of poll() is completed and | |
we now also check the return info from poll() and set the | |
channel ready flag if we detect something on a channel. This | |
way the poll() handler should be on par with the select() | |
based poller. | |
The ndmjob program code is also included and you can build | |
the ndmjob binary using the new shared library. Currently | |
it is mostly for testing the new code in the shared library. | |
The ndmjob program code is rewritten to also use linked list | |
whereever possible without the need to completely rewrite the | |
code. | |
The NDMJOB header files are made C++ aware so we can compile | |
the shared lib a pure C-code (which it essentially also is) | |
and use it from BAREOS. | |
The config engine of the director and storage daemon have been | |
made aware of the NDMP protocol. Currently there is support for | |
creating NDMP protocol based Backup and Restore Jobs. The storage | |
resource is extended with a protocol and authentication type field | |
which can be used by the NDMP DMA coded in ndmp_dma.c. A Client | |
also has those two fields. When a storage daemon used in the NDMP | |
backup/restore is in real life an BAREOS storage daemon an extra | |
field named paired storage is part of the storage resource and is | |
used by the DMA to contact the storage daemon via the native protocol | |
to be able to simulate a NDMP save or restore via the normal | |
BAREOS infrastructure. Via the native protocol we reserve | |
things like drives etc so the virtual NDMP tape client can | |
save its data, the native link is also used for things like | |
getting the next volume to load etc. | |
The job start code for backup and restore is modified to check | |
for the job protocol and dispatch to the native routines when | |
it is a native backup or to the NDMP routines when it is any NDMP job. | |
The NDMP tape agent lives in ndmp_tape.c in the storage | |
daemon it creates an extra listening thread which handles NDMP | |
connections. Its based on the BAREOS bnet_server_thread code but | |
put somewhat on a diet as for NDMP we don't need all the bells | |
and whistles from the bsock class so we implemented a light weight | |
ndmp connection structure. This structure is passed as handle to | |
the connection handler and could be seen as local hook data and | |
can be extended along the way to keep some state information on | |
the NDMP session related to internal BAREOS resources. | |
A ndmp backup configuration looks somethings like this: | |
Configuration in bareos-dir.conf: | |
Replace <ndmp_data_server> with the hostname of the storage device | |
you are backing up e.g. the DATA AGENT in NDMP terms. | |
# | |
# Use the DUMP protocol (e.g. UNIX DUMP comparable to tar/cpio) | |
# Generates FileHandle Information which can be used for single file | |
# restore. | |
# | |
JobDefs { | |
Name = "DefaultNDMPJob" | |
Type = Backup | |
Protocol = NDMP | |
Level = Incremental | |
Client = <ndmp_data_server>-ndmp | |
Backup Format = dump | |
FileSet = "NDMP Fileset" | |
Schedule = "WeeklyCycle" | |
Storage = NDMPFile | |
Messages = Standard | |
Pool = NDMPFile | |
Priority = 10 | |
Write Bootstrap = "/var/opt/bareos/run/bareos/%c.bsr" | |
} | |
# | |
# A special restore Job which has the protocol set right etc. | |
# | |
JobDefs { | |
Name = "DefaultNDMPRestoreJob" | |
Client = <ndmp_data_server>-ndmp | |
Type = Restore | |
Protocol = NDMP | |
Backup Format = dump | |
FileSet = "NDMP Fileset" | |
Storage = NDMPFile | |
Pool = Default | |
Messages = Standard | |
Where = / | |
} | |
# | |
# A NDMP Backup Job using the JobDef above. | |
# | |
Job { | |
Name = "BackupNDMPDump" | |
JobDefs = "DefaultNDMPJob" | |
} | |
# | |
# Use the NETAPP SMTAPE protocol e.g. same protocol is used as replication protocol | |
# between two NETAPP storage boxes. Doesn't allow single file restore all or nothing | |
# restore of whole NETAPP volume. | |
# | |
Job { | |
Name = "BackupNDMPSMTape" | |
JobDefs = "DefaultNDMPJob" | |
Backup Format = smtape | |
Client = <ndmp_data_server>-ndmp | |
FileSet = "NDMP SMtape Fileset" | |
} | |
# | |
# A NDMP restore Job using the JobDef above. | |
# | |
Job { | |
Name = "NDMPRestoreDump" | |
JobDefs = "DefaultNDMPRestoreJob" | |
} | |
# | |
# A NDMP restore Job using the JobDef above but for restoring a SMTAPE type of NDMP backup. | |
# | |
Job { | |
Name = "NDMPRestoreSMTape" | |
JobDefs = "DefaultNDMPRestoreJob" | |
Backup Format = smtape | |
FileSet = "NDMP SMtape Restore Fileset" | |
} | |
Fileset { | |
Name = "NDMP Fileset" | |
Include { | |
Options { | |
meta = "USER=root" | |
} | |
File = /export/home/... | |
} | |
} | |
# | |
# A NDMP Backup using SMPTAPE of a NetAPP storage box. | |
# | |
Fileset { | |
Name = "NDMP SMtape Fileset" | |
Include { | |
Options { | |
meta = "SMTAPE_DELETE_SNAPSHOT=Y" | |
} | |
File = /vol/vol1 | |
} | |
} | |
# | |
# A NDMP Restore using SMPTAPE of a NetAPP storage box. | |
# | |
Fileset { | |
Name = "NDMP SMtape Restore Fileset" | |
Include { | |
Options { | |
meta = "SMTAPE_BREAK_MIRROR=Y" | |
} | |
File = /vol/vol1 | |
} | |
} | |
# | |
# A NDMP Client. | |
# | |
Client { | |
Name = <ndmp_data_server>-ndmp | |
Address = ... | |
Port = 10000 | |
Protocol = NDMPv4 # Need to specify protocol before password as protocol determines password encoding used. | |
Auth Type = Clear # Clear == Clear Text, MD5 == Challenge protocol | |
Username = "ndmp" # username of the NDMP user on the DATA AGENT e.g. storage box being backuped. | |
Password = "test" # password of the NDMP user on the DATA AGENT e.g. storage box being backuped. | |
} | |
# | |
# Your normal Bareos SD definition should be already in your config. | |
# | |
Storage { | |
Name = File | |
Address = ... # N.B. Use a fully qualified name here | |
SDPort = 9103 | |
Password = ... | |
Device = FileStorage | |
Media Type = File | |
} | |
# | |
# Same storage daemon but via NDMP protocol. | |
# We link via the PairedStorage config option the Bareos SD instance definition to a NDMP TAPE AGENT. | |
# | |
Storage { | |
Name = NDMPFile | |
Address = ... # N.B. Use a fully qualified name here | |
Port = 10000 | |
Protocol = NDMPv4 # Need to specify protocol before password as protocol determines password encoding used. | |
Auth Type = Clear # Clear == Clear Text, MD5 == Challenge protocol | |
Username = ndmp # username of the NDMP user on the TAPE AGENT e.g. the Bareos SD but accessed via the NDMP protocol. | |
Password = test # password of the NDMP user on the TAPE AGENT e.g. the Bareos SD but accessed via the NDMP protocol. | |
Device = FileStorage | |
Media Type = File | |
PairedStorage = File | |
} | |
# | |
# Your normal File based backup pool normally already defined. | |
# | |
Pool { | |
Name = File | |
Pool Type = Backup | |
Recycle = yes | |
AutoPrune = yes | |
Storage = File | |
Volume Retention = 365 days # one year | |
Maximum Volume Bytes = 50G # Limit Volume size to something reasonable | |
Maximum Volumes = 100 # Limit number of Volumes in Pool | |
} | |
# | |
# Separate Pool for NDMP data so upgrading of Jobs works and selects the right storage. | |
# | |
Pool { | |
Name = NDMPFile | |
Pool Type = Backup | |
Recycle = yes | |
AutoPrune = yes | |
Storage = NDMPFile | |
Volume Retention = 365 days # one year | |
Maximum Volume Bytes = 50G # Limit Volume size to something reasonable | |
Maximum Volumes = 100 # Limit number of Volumes in Pool | |
} | |
Configuration in bareos-sd.conf: | |
# | |
# Normal SD config block, should enable the NDMP protocol here otherwise it won't listen | |
# on port 10000. | |
# | |
Storage { | |
Name = .... | |
... | |
NDMP Enable = yes | |
} | |
# | |
# This entry gives the DMA in the Director access to the bareos SD via the NDMP protocol. | |
# This option is used via the NDMP protocol to open the right TAPE AGENT connection to your | |
# Bareos SD via the NDMP protocol. The initialization of the SD is done via the native protocol | |
# and is handled via the PairedStorage keyword. | |
# | |
Ndmp { | |
Name = ...-ndmp-dma # Can be any name but normally you should use the name of the Director here. | |
Username = ndmp # Same username as you specified in the NDMPFile storage definition. | |
Password = test # Same password as you specified in the NDMPFile storage definition. | |
AuthType = Clear # Clear == Clear Text, MD5 == Challenge protocol | |
} |