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