1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2011-2015 Planets Communications B.V.
5    Copyright (C) 2013-2019 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 and included
10    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  * Routines that store the NDMP Media Info in the Bareos DB
24  * and retrieve them back
25  *
26  * Philipp Storz, November 2016
27  */
28 
29 #include "include/bareos.h"
30 #include "dird.h"
31 
32 #if HAVE_NDMP
33 #include "ndmp/ndmagents.h"
34 #endif /* HAVE_NDMP */
35 
36 namespace directordaemon {
37 
38 #if HAVE_NDMP
39 
40 /* clang-format off */
41 
42 /**
43  * Store ndmmedia information into database in MEDIA and JOBMEDIA information.
44  * we map the ndm_media fields into the MediaDbRecord and JobMediaDbRecord fields as follows
45  *
46  ***********************************************************************************************
47  *     NDM_MEDIA                        |        MediaDbRecord / JobMediaDbRecord              *
48  ***********************************************************************************************
49  char     label[NDMMEDIA_LABEL_MAX+1];  |  MediaDbRecord:      char VolumeName[MAX_NAME_LENGTH];
50  unsigned slot_addr;                    |  MediaDbRecord:      int32_t Slot;
51  -----------------------------------------------------------------------------------------------
52  unsigned file_mark_offset;             |  JobMediaDbRecord:   uint32_t StartBlock;
53  uint64_t n_bytes;                      |  JobMediaDbRecord:   uint64_t JobBytes;
54  ***********************************************************************************************
55 
56  Notes:
57    * Slot needs to be translated from bareos slotnr to NDMP slot number  and back
58    * uint64_t begin_offset,end_offset; do not need to be stored (scratchpad)
59  */
60 
61 /* clang-format on */
62 
63 
NdmmediaToBareosDbRecords(ndmmedia * media,MediaDbRecord * mr,JobMediaDbRecord * jm)64 void NdmmediaToBareosDbRecords(ndmmedia* media,
65                                MediaDbRecord* mr,
66                                JobMediaDbRecord* jm)
67 {
68   bstrncpy(mr->VolumeName, media->label, NDMMEDIA_LABEL_MAX);
69   mr->Slot = media->slot_addr;
70 
71   jm->StartBlock = media->file_mark_offset;
72   jm->JobBytes = media->n_bytes;
73 
74   /*
75    * We usually get here with the Volstatus used as it is set
76    * to be sure the medium will not be used by other jobs
77    *
78    * If eom was reached, mark medium Full,
79    * else make it append so that the remaining space
80    * will be used
81    */
82   if (media->media_eom) {
83     bstrncpy(mr->VolStatus, NT_("Full"), sizeof(mr->VolStatus));
84   } else {
85     bstrncpy(mr->VolStatus, NT_("Append"), sizeof(mr->VolStatus));
86   }
87 
88   Dmsg2(100, "Set Medium %s: to VolStatus %s", mr->VolumeName, mr->VolStatus);
89 
90   /*
91    * Update LastWritten Timestamp
92    */
93   mr->LastWritten = (utime_t)time(NULL);
94 
95   /*
96    * VolBytes
97    */
98   mr->VolBytes += media->n_bytes;
99 
100   /*
101    * also store file_marks
102    */
103   mr->VolFiles = media->file_mark_offset;
104 }
105 
NdmmediaFromBareosDbRecords(ndmmedia * media,MediaDbRecord * mr,JobMediaDbRecord * jm)106 void NdmmediaFromBareosDbRecords(ndmmedia* media,
107                                  MediaDbRecord* mr,
108                                  JobMediaDbRecord* jm)
109 {
110   bstrncpy(media->label, mr->VolumeName, NDMMEDIA_LABEL_MAX - 1);
111   media->valid_label = NDMP9_VALIDITY_VALID;
112 
113   media->slot_addr = mr->Slot;
114   media->valid_slot = NDMP9_VALIDITY_VALID;
115 
116   media->n_bytes = mr->VolBytes;
117   media->valid_n_bytes = NDMP9_VALIDITY_VALID;
118 
119   media->file_mark_offset = jm->StartBlock;
120   media->valid_filemark = NDMP9_VALIDITY_VALID;
121 
122   media->n_bytes = jm->JobBytes;
123   media->valid_n_bytes = NDMP9_VALIDITY_VALID;
124 }
125 
126 
StoreNdmmediaInfoInDatabase(ndmmedia * media,JobControlRecord * jcr)127 bool StoreNdmmediaInfoInDatabase(ndmmedia* media, JobControlRecord* jcr)
128 {
129   JobMediaDbRecord jm;
130   MediaDbRecord mr;
131 
132   /*
133    * get media record by name
134    */
135   bstrncpy(mr.VolumeName, media->label, NDMMEDIA_LABEL_MAX);
136   if (!jcr->db->GetMediaRecord(jcr, &mr)) {
137     Jmsg(jcr, M_FATAL, 0,
138          _("Catalog error getting Media record for Medium %s: %s"),
139          mr.VolumeName, jcr->db->strerror());
140     return false;
141   }
142 
143   /*
144    * map media info into db records
145    */
146   NdmmediaToBareosDbRecords(media, &mr, &jm);
147 
148 
149   /*
150    * store db records
151    */
152   jm.MediaId = mr.MediaId;
153   jm.JobId = jcr->JobId;
154   if (!jcr->db->CreateJobmediaRecord(jcr, &jm)) {
155     Jmsg(jcr, M_FATAL, 0, _("Catalog error creating JobMedia record. %s"),
156          jcr->db->strerror());
157     return false;
158   }
159 
160   if (!jcr->db->UpdateMediaRecord(jcr, &mr)) {
161     Jmsg(jcr, M_FATAL, 0,
162          _("Catalog error updating Media record for Medium %s: %s"),
163          mr.VolumeName, jcr->db->strerror());
164     return false;
165   }
166   return true;
167 }
168 
169 
170 /*
171  * get ndmmedia from database for certain job
172  */
GetNdmmediaInfoFromDatabase(ndm_media_table * media_tab,JobControlRecord * jcr)173 bool GetNdmmediaInfoFromDatabase(ndm_media_table* media_tab,
174                                  JobControlRecord* jcr)
175 {
176   int VolCount;
177   VolumeParameters* VolParams = NULL;
178   bool retval = false;
179 
180 
181   /*
182    * Find restore JobId
183    */
184   JobId_t restoreJobId;
185   char* p = jcr->JobIds;
186 
187   /*
188    *  TODO: what happens with multiple IDs?
189    */
190   if (!GetNextJobidFromList(&p, &restoreJobId)) {
191     Jmsg(jcr, M_FATAL, 0, _("Error getting next jobid from list\n"));
192   }
193   if (restoreJobId == 0) {
194     Jmsg(jcr, M_FATAL, 0, _("RestoreJobId is zero, cannot go on\n"));
195   }
196   /*
197    * Get Media for certain job
198    */
199   VolCount = jcr->db->GetJobVolumeParameters(jcr, restoreJobId, &VolParams);
200 
201   if (!VolCount) {
202     Jmsg(jcr, M_ERROR, 0,
203          _("Could not get Job Volume Parameters to "
204            "create ndmmedia list. ERR=%s\n"),
205          jcr->db->strerror());
206     goto bail_out;
207   }
208 
209   /*
210    * create a ndmmedium for each volume
211    */
212   for (int i = 0; i < VolCount; i++) {
213     ndmmedia* media = ndma_store_media(media_tab, i);
214 
215     bstrncpy(media->label, VolParams[i].VolumeName, NDMMEDIA_LABEL_MAX);
216     media->valid_label = NDMP9_VALIDITY_VALID;
217 
218     media->slot_addr = VolParams[i].Slot;
219     media->valid_slot = NDMP9_VALIDITY_VALID;
220 
221     media->n_bytes = VolParams[i].JobBytes;
222     media->valid_n_bytes = NDMP9_VALIDITY_VALID;
223 
224     // Vols[i].StartAddr = (((uint64_t)StartFile)<<32) | StartBlock;
225     // VolParams[i].StartAddr >>= 32;
226     media->file_mark_offset = VolParams[i].StartAddr;
227 
228     media->valid_filemark = NDMP9_VALIDITY_VALID;
229   }
230   retval = true;
231 
232 bail_out:
233   if (VolParams) { free(VolParams); }
234 
235   return retval;
236 }
237 
238 
239 #else
240 
241 #endif /* HAVE_NDMP */
242 
243 } /* namespace directordaemon */
244