1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2011-2015 Planets Communications B.V.
5 Copyright (C) 2013-2020 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 const 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