1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.snapshot;
19
20 import java.io.IOException;
21 import java.security.PrivilegedExceptionAction;
22 import java.util.Collections;
23
24 import com.google.common.collect.ListMultimap;
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.fs.FSDataInputStream;
29 import org.apache.hadoop.fs.FSDataOutputStream;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.fs.permission.FsPermission;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.TableName;
35 import org.apache.hadoop.hbase.classification.InterfaceAudience;
36 import org.apache.hadoop.hbase.client.Admin;
37 import org.apache.hadoop.hbase.client.Connection;
38 import org.apache.hadoop.hbase.client.ConnectionFactory;
39 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
40 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
41 import org.apache.hadoop.hbase.security.User;
42 import org.apache.hadoop.hbase.security.access.AccessControlLists;
43 import org.apache.hadoop.hbase.security.access.TablePermission;
44 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
45 import org.apache.hadoop.hbase.util.FSUtils;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 @InterfaceAudience.Private
84 public final class SnapshotDescriptionUtils {
85
86
87
88
89 public static class CompletedSnaphotDirectoriesFilter extends FSUtils.BlackListDirFilter {
90
91
92
93
94 public CompletedSnaphotDirectoriesFilter(FileSystem fs) {
95 super(fs, Collections.singletonList(SNAPSHOT_TMP_DIR_NAME));
96 }
97 }
98
99 private static final Log LOG = LogFactory.getLog(SnapshotDescriptionUtils.class);
100
101
102
103
104 public static final int SNAPSHOT_LAYOUT_VERSION = SnapshotManifestV2.DESCRIPTOR_VERSION;
105
106
107
108
109
110 public static final String SNAPSHOTINFO_FILE = ".snapshotinfo";
111
112
113 public static final String SNAPSHOT_TMP_DIR_NAME = ".tmp";
114
115
116 public static final String SNAPSHOT_IN_PROGRESS = ".inprogress";
117
118
119 public static final long NO_SNAPSHOT_START_TIME_SPECIFIED = 0;
120
121
122 public static final String MASTER_SNAPSHOT_TIMEOUT_MILLIS = "hbase.snapshot.master.timeout.millis";
123
124
125 public static final long DEFAULT_MAX_WAIT_TIME = 60000 * 5 ;
126
127
128
129
130
131
132 @Deprecated
133 public static final int SNAPSHOT_TIMEOUT_MILLIS_DEFAULT = 60000 * 5;
134
135
136
137
138
139
140 @Deprecated
141 public static final String SNAPSHOT_TIMEOUT_MILLIS_KEY = "hbase.snapshot.master.timeoutMillis";
142
143 private SnapshotDescriptionUtils() {
144
145 }
146
147
148
149
150
151
152
153 public static long getMaxMasterTimeout(Configuration conf, SnapshotDescription.Type type,
154 long defaultMaxWaitTime) {
155 String confKey;
156 switch (type) {
157 case DISABLED:
158 default:
159 confKey = MASTER_SNAPSHOT_TIMEOUT_MILLIS;
160 }
161 return Math.max(conf.getLong(confKey, defaultMaxWaitTime),
162 conf.getLong(SNAPSHOT_TIMEOUT_MILLIS_KEY, defaultMaxWaitTime));
163 }
164
165
166
167
168
169
170
171 public static Path getSnapshotRootDir(final Path rootDir) {
172 return new Path(rootDir, HConstants.SNAPSHOT_DIR_NAME);
173 }
174
175
176
177
178
179
180
181
182 public static Path getCompletedSnapshotDir(final SnapshotDescription snapshot, final Path rootDir) {
183 return getCompletedSnapshotDir(snapshot.getName(), rootDir);
184 }
185
186
187
188
189
190
191
192
193 public static Path getCompletedSnapshotDir(final String snapshotName, final Path rootDir) {
194 return getCompletedSnapshotDir(getSnapshotsDir(rootDir), snapshotName);
195 }
196
197
198
199
200
201
202
203 public static Path getWorkingSnapshotDir(final Path rootDir) {
204 return new Path(getSnapshotsDir(rootDir), SNAPSHOT_TMP_DIR_NAME);
205 }
206
207
208
209
210
211
212
213 public static Path getWorkingSnapshotDir(SnapshotDescription snapshot, final Path rootDir) {
214 return getCompletedSnapshotDir(getWorkingSnapshotDir(rootDir), snapshot.getName());
215 }
216
217
218
219
220
221
222
223 public static Path getWorkingSnapshotDir(String snapshotName, final Path rootDir) {
224 return getCompletedSnapshotDir(getWorkingSnapshotDir(rootDir), snapshotName);
225 }
226
227
228
229
230
231
232
233 private static final Path getCompletedSnapshotDir(final Path snapshotsDir, String snapshotName) {
234 return new Path(snapshotsDir, snapshotName);
235 }
236
237
238
239
240
241 public static final Path getSnapshotsDir(Path rootDir) {
242 return new Path(rootDir, HConstants.SNAPSHOT_DIR_NAME);
243 }
244
245
246
247
248
249
250
251
252
253
254
255 public static SnapshotDescription validate(SnapshotDescription snapshot, Configuration conf)
256 throws IllegalArgumentException, IOException {
257 if (!snapshot.hasTable()) {
258 throw new IllegalArgumentException(
259 "Descriptor doesn't apply to a table, so we can't build it.");
260 }
261
262
263 long time = snapshot.getCreationTime();
264 if (time == SnapshotDescriptionUtils.NO_SNAPSHOT_START_TIME_SPECIFIED) {
265 time = EnvironmentEdgeManager.currentTime();
266 LOG.debug("Creation time not specified, setting to:" + time + " (current time:"
267 + EnvironmentEdgeManager.currentTime() + ").");
268 SnapshotDescription.Builder builder = snapshot.toBuilder();
269 builder.setCreationTime(time);
270 snapshot = builder.build();
271 }
272
273
274 if(isSecurityAvailable(conf)){
275 snapshot = writeAclToSnapshotDescription(snapshot, conf);
276 }
277
278 return snapshot;
279 }
280
281
282
283
284
285
286
287
288
289 public static void writeSnapshotInfo(SnapshotDescription snapshot, Path workingDir, FileSystem fs)
290 throws IOException {
291 FsPermission perms = FSUtils.getFilePermissions(fs, fs.getConf(),
292 HConstants.DATA_FILE_UMASK_KEY);
293 Path snapshotInfo = new Path(workingDir, SnapshotDescriptionUtils.SNAPSHOTINFO_FILE);
294 try {
295 FSDataOutputStream out = FSUtils.create(fs, snapshotInfo, perms, true);
296 try {
297 snapshot.writeTo(out);
298 } finally {
299 out.close();
300 }
301 } catch (IOException e) {
302
303 if (!fs.delete(snapshotInfo, false)) {
304 String msg = "Couldn't delete snapshot info file: " + snapshotInfo;
305 LOG.error(msg);
306 throw new IOException(msg);
307 }
308 }
309 }
310
311
312
313
314 public static void createInProgressTag(Path workingDir, FileSystem fs) throws IOException {
315 FsPermission perms = FSUtils.getFilePermissions(fs, fs.getConf(),
316 HConstants.DATA_FILE_UMASK_KEY);
317 Path snapshot_in_progress = new Path(workingDir, SnapshotDescriptionUtils.SNAPSHOT_IN_PROGRESS);
318 FSUtils.create(fs, snapshot_in_progress, perms, true);
319 }
320
321
322
323
324
325
326
327
328
329 public static SnapshotDescription readSnapshotInfo(FileSystem fs, Path snapshotDir)
330 throws CorruptedSnapshotException {
331 Path snapshotInfo = new Path(snapshotDir, SNAPSHOTINFO_FILE);
332 try {
333 FSDataInputStream in = null;
334 try {
335 in = fs.open(snapshotInfo);
336 SnapshotDescription desc = SnapshotDescription.parseFrom(in);
337 return desc;
338 } finally {
339 if (in != null) in.close();
340 }
341 } catch (IOException e) {
342 throw new CorruptedSnapshotException("Couldn't read snapshot info from:" + snapshotInfo, e);
343 }
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357 public static void completeSnapshot(SnapshotDescription snapshot, Path rootdir, Path workingDir,
358 FileSystem fs) throws SnapshotCreationException, IOException {
359 Path finishedDir = getCompletedSnapshotDir(snapshot, rootdir);
360 LOG.debug("Snapshot is done, just moving the snapshot from " + workingDir + " to "
361 + finishedDir);
362 if (!fs.rename(workingDir, finishedDir)) {
363 throw new SnapshotCreationException("Failed to move working directory(" + workingDir
364 + ") to completed directory(" + finishedDir + ").", snapshot);
365 }
366 }
367
368
369
370
371
372
373
374
375 public static boolean isSnapshotOwner(final SnapshotDescription snapshot, final User user) {
376 if (user == null) return false;
377 if (!snapshot.hasOwner()) return false;
378 return snapshot.getOwner().equals(user.getShortName());
379 }
380
381 public static boolean isSecurityAvailable(Configuration conf) throws IOException {
382 Connection conn = ConnectionFactory.createConnection(conf);
383 try {
384 Admin admin = conn.getAdmin();
385 try {
386 return admin.tableExists(AccessControlLists.ACL_TABLE_NAME);
387 } finally {
388 admin.close();
389 }
390 } finally {
391 conn.close();
392 }
393 }
394
395 private static SnapshotDescription writeAclToSnapshotDescription(
396 final SnapshotDescription snapshot, final Configuration conf) throws IOException {
397 ListMultimap<String, TablePermission> perms =
398 User.runAsLoginUser(new PrivilegedExceptionAction<ListMultimap<String, TablePermission>>() {
399 @Override
400 public ListMultimap<String, TablePermission> run() throws Exception {
401 return AccessControlLists.getTablePermissions(conf,
402 TableName.valueOf(snapshot.getTable()));
403 }
404 });
405 return snapshot.toBuilder().setUsersAndPermissions(ProtobufUtil.toUserTablePermissions(perms))
406 .build();
407 }
408 }