1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2013-2013 Planets Communications B.V.
5    Copyright (C) 2013-2016 Bareos GmbH & Co. KG
6 
7    This program is Free Software; you can redistribute it and/or
8    modify it under the terms of version three of the GNU Affero General Public
9    License as published by the Free Software Foundation, which is
10    listed in the file LICENSE.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15    Affero General Public License for more details.
16 
17    You should have received a copy of the GNU Affero General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20    02110-1301, USA.
21 */
22 /*
23  * Marco van Wieringen, November 2013
24  */
25 /**
26  * @file
27  * SCSI Tape Alert Storage daemon Plugin
28  */
29 #include "include/bareos.h"
30 #include "stored/stored.h"
31 #include "lib/scsi_tapealert.h"
32 
33 using namespace storagedaemon;
34 
35 #define PLUGIN_LICENSE "Bareos AGPLv3"
36 #define PLUGIN_AUTHOR "Marco van Wieringen"
37 #define PLUGIN_DATE "November 2013"
38 #define PLUGIN_VERSION "1"
39 #define PLUGIN_DESCRIPTION "SCSI Tape Alert Storage Daemon Plugin"
40 #define PLUGIN_USAGE "(No usage yet)"
41 
42 /**
43  * Forward referenced functions
44  */
45 static bRC newPlugin(bpContext* ctx);
46 static bRC freePlugin(bpContext* ctx);
47 static bRC getPluginValue(bpContext* ctx, psdVariable var, void* value);
48 static bRC setPluginValue(bpContext* ctx, psdVariable var, void* value);
49 static bRC handlePluginEvent(bpContext* ctx, bsdEvent* event, void* value);
50 static bRC handle_tapealert_readout(void* value);
51 
52 /**
53  * Pointers to Bareos functions
54  */
55 static bsdFuncs* bfuncs = NULL;
56 static bsdInfo* binfo = NULL;
57 
58 static genpInfo pluginInfo = {sizeof(pluginInfo), SD_PLUGIN_INTERFACE_VERSION,
59                               SD_PLUGIN_MAGIC,    PLUGIN_LICENSE,
60                               PLUGIN_AUTHOR,      PLUGIN_DATE,
61                               PLUGIN_VERSION,     PLUGIN_DESCRIPTION,
62                               PLUGIN_USAGE};
63 
64 static psdFuncs pluginFuncs = {sizeof(pluginFuncs), SD_PLUGIN_INTERFACE_VERSION,
65 
66                                /*
67                                 * Entry points into plugin
68                                 */
69                                newPlugin,  /* new plugin instance */
70                                freePlugin, /* free plugin instance */
71                                getPluginValue, setPluginValue,
72                                handlePluginEvent};
73 
74 static int const debuglevel = 200;
75 
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
79 
80 /**
81  * loadPlugin() and unloadPlugin() are entry points that are
82  *  exported, so Bareos can directly call these two entry points
83  *  they are common to all Bareos plugins.
84  *
85  * External entry point called by Bareos to "load the plugin
86  */
loadPlugin(bsdInfo * lbinfo,bsdFuncs * lbfuncs,genpInfo ** pinfo,psdFuncs ** pfuncs)87 bRC loadPlugin(bsdInfo* lbinfo,
88                bsdFuncs* lbfuncs,
89                genpInfo** pinfo,
90                psdFuncs** pfuncs)
91 {
92   bfuncs = lbfuncs; /* set Bareos funct pointers */
93   binfo = lbinfo;
94   Dmsg2(debuglevel, "scsitapealert-sd: Loaded: size=%d version=%d\n",
95         bfuncs->size, bfuncs->version);
96   *pinfo = &pluginInfo;   /* return pointer to our info */
97   *pfuncs = &pluginFuncs; /* return pointer to our functions */
98 
99   return bRC_OK;
100 }
101 
102 /**
103  * External entry point to unload the plugin
104  */
unloadPlugin()105 bRC unloadPlugin() { return bRC_OK; }
106 
107 #ifdef __cplusplus
108 }
109 #endif
110 
111 /**
112  * The following entry points are accessed through the function
113  * pointers we supplied to Bareos. Each plugin type (dir, fd, sd)
114  * has its own set of entry points that the plugin must define.
115  *
116  * Create a new instance of the plugin i.e. allocate our private storage
117  */
newPlugin(bpContext * ctx)118 static bRC newPlugin(bpContext* ctx)
119 {
120   int JobId = 0;
121 
122   bfuncs->getBareosValue(ctx, bsdVarJobId, (void*)&JobId);
123   Dmsg1(debuglevel, "scsitapealert-sd: newPlugin JobId=%d\n", JobId);
124 
125   /*
126    * Only register plugin events we are interested in.
127    */
128   bfuncs->registerBareosEvents(
129       ctx, 6, bsdEventVolumeLoad, bsdEventLabelVerified, bsdEventReadError,
130       bsdEventWriteError, bsdEventVolumeUnload, bsdEventDeviceRelease);
131 
132   return bRC_OK;
133 }
134 
135 /**
136  * Free a plugin instance, i.e. release our private storage
137  */
freePlugin(bpContext * ctx)138 static bRC freePlugin(bpContext* ctx)
139 {
140   int JobId = 0;
141 
142   bfuncs->getBareosValue(ctx, bsdVarJobId, (void*)&JobId);
143   Dmsg1(debuglevel, "scsitapealert-sd: freePlugin JobId=%d\n", JobId);
144 
145   return bRC_OK;
146 }
147 
148 /**
149  * Return some plugin value (none defined)
150  */
getPluginValue(bpContext * ctx,psdVariable var,void * value)151 static bRC getPluginValue(bpContext* ctx, psdVariable var, void* value)
152 {
153   Dmsg1(debuglevel, "scsitapealert-sd: getPluginValue var=%d\n", var);
154 
155   return bRC_OK;
156 }
157 
158 /**
159  * Set a plugin value (none defined)
160  */
setPluginValue(bpContext * ctx,psdVariable var,void * value)161 static bRC setPluginValue(bpContext* ctx, psdVariable var, void* value)
162 {
163   Dmsg1(debuglevel, "scsitapealert-sd: setPluginValue var=%d\n", var);
164 
165   return bRC_OK;
166 }
167 
168 /**
169  * Handle an event that was generated in Bareos
170  */
handlePluginEvent(bpContext * ctx,bsdEvent * event,void * value)171 static bRC handlePluginEvent(bpContext* ctx, bsdEvent* event, void* value)
172 {
173   switch (event->eventType) {
174     case bsdEventLabelVerified:
175     case bsdEventReadError:
176     case bsdEventWriteError:
177     case bsdEventVolumeUnload:
178       return handle_tapealert_readout(value);
179     default:
180       Dmsg1(debuglevel, "scsitapealert-sd: Unknown event %d\n",
181             event->eventType);
182       return bRC_Error;
183   }
184 
185   return bRC_OK;
186 }
187 
188 static pthread_mutex_t tapealert_operation_mutex = PTHREAD_MUTEX_INITIALIZER;
189 
handle_tapealert_readout(void * value)190 static bRC handle_tapealert_readout(void* value)
191 {
192   DeviceControlRecord* dcr;
193   Device* dev;
194   DeviceResource* device;
195   uint64_t flags;
196 
197   /*
198    * Unpack the arguments passed in.
199    */
200   dcr = (DeviceControlRecord*)value;
201   if (!dcr) { return bRC_Error; }
202   dev = dcr->dev;
203   if (!dev) { return bRC_Error; }
204   device = dev->device;
205   if (!device) { return bRC_Error; }
206 
207   /*
208    * See if drive tapealert is enabled.
209    */
210   if (!device->drive_tapealert_enabled) {
211     Dmsg1(debuglevel,
212           "scsitapealert-sd: tapealert is not enabled on device %s\n",
213           dev->dev_name);
214     return bRC_OK;
215   }
216 
217   Dmsg1(debuglevel, "scsitapealert-sd: checking for tapealerts on device %s\n",
218         dev->dev_name);
219   P(tapealert_operation_mutex);
220   GetTapealertFlags(dev->fd(), dev->dev_name, &flags);
221   V(tapealert_operation_mutex);
222 
223   Dmsg1(debuglevel,
224         "scsitapealert-sd: checking for tapealerts on device %s DONE\n",
225         dev->dev_name);
226   Dmsg1(debuglevel, "scsitapealert-sd: flags: %ld \n", flags);
227 
228   if (flags) {
229     Dmsg1(
230         debuglevel,
231         "scsitapealert-sd: tapealerts on device %s, calling UpdateTapeAlerts\n",
232         dev->dev_name);
233     bfuncs->UpdateTapeAlert(dcr, flags);
234   }
235 
236   return bRC_OK;
237 }
238