|
19 | 19 |
|
20 | 20 | import java.io.IOException; |
21 | 21 | import java.util.ArrayList; |
| 22 | +import java.util.BitSet; |
22 | 23 | import java.util.HashMap; |
23 | 24 | import java.util.List; |
24 | 25 | import java.util.Map; |
25 | 26 | import java.util.Objects; |
26 | 27 | import java.util.stream.Collectors; |
27 | 28 |
|
| 29 | +import com.google.protobuf.ByteString; |
28 | 30 | import org.apache.hadoop.fs.FileEncryptionInfo; |
29 | 31 | import org.apache.hadoop.hdds.protocol.proto.HddsProtos; |
30 | 32 | import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyInfo; |
|
34 | 36 |
|
35 | 37 | import com.google.common.base.Preconditions; |
36 | 38 |
|
| 39 | +import static org.apache.hadoop.ozone.OzoneAcl.ZERO_BITSET; |
| 40 | + |
37 | 41 | /** |
38 | 42 | * Args for key block. The block instance for the key requested in putKey. |
39 | 43 | * This is returned from OM to client, and client use class to talk to |
@@ -235,6 +239,119 @@ public List<OzoneAclInfo> getAcls() { |
235 | 239 | return acls; |
236 | 240 | } |
237 | 241 |
|
| 242 | + /** |
| 243 | + * Add an ozoneAcl to list of existing Acl set. |
| 244 | + * @param ozoneAcl |
| 245 | + * @return true - if successfully added, false if not added or acl is |
| 246 | + * already existing in the acl list. |
| 247 | + */ |
| 248 | + public boolean addAcl(OzoneAclInfo ozoneAcl) { |
| 249 | + // Case 1: When we are adding more rights to existing user/group. |
| 250 | + boolean addToExistingAcl = false; |
| 251 | + for(OzoneAclInfo existingAcl: getAcls()) { |
| 252 | + if(existingAcl.getName().equals(ozoneAcl.getName()) && |
| 253 | + existingAcl.getType().equals(ozoneAcl.getType())) { |
| 254 | + |
| 255 | + // We need to do "or" before comparision because think of a case like |
| 256 | + // existing acl is 777 and newly added acl is 444, we have already |
| 257 | + // that acl set. In this case if we do direct check they will not |
| 258 | + // be equal, but if we do or and then check, we shall know it |
| 259 | + // has acl's already set or not. |
| 260 | + BitSet newAclBits = BitSet.valueOf( |
| 261 | + existingAcl.getRights().toByteArray()); |
| 262 | + |
| 263 | + newAclBits.or(BitSet.valueOf(ozoneAcl.getRights().toByteArray())); |
| 264 | + |
| 265 | + if (newAclBits.equals(BitSet.valueOf( |
| 266 | + existingAcl.getRights().toByteArray()))) { |
| 267 | + return false; |
| 268 | + } else { |
| 269 | + OzoneAclInfo newAcl = OzoneAclInfo.newBuilder() |
| 270 | + .setType(ozoneAcl.getType()) |
| 271 | + .setName(ozoneAcl.getName()) |
| 272 | + .setAclScope(ozoneAcl.getAclScope()) |
| 273 | + .setRights(ByteString.copyFrom(newAclBits.toByteArray())) |
| 274 | + .build(); |
| 275 | + getAcls().remove(existingAcl); |
| 276 | + getAcls().add(newAcl); |
| 277 | + addToExistingAcl = true; |
| 278 | + break; |
| 279 | + } |
| 280 | + } |
| 281 | + } |
| 282 | + |
| 283 | + // Case 2: When a completely new acl is added. |
| 284 | + if(!addToExistingAcl) { |
| 285 | + getAcls().add(ozoneAcl); |
| 286 | + } |
| 287 | + return true; |
| 288 | + } |
| 289 | + |
| 290 | + /** |
| 291 | + * Remove acl from existing acl list. |
| 292 | + * @param ozoneAcl |
| 293 | + * @return true - if successfully removed, false if not able to remove due |
| 294 | + * to that acl is not in the existing acl list. |
| 295 | + */ |
| 296 | + public boolean removeAcl(OzoneAclInfo ozoneAcl) { |
| 297 | + boolean removed = false; |
| 298 | + |
| 299 | + // When we are removing subset of rights from existing acl. |
| 300 | + for(OzoneAclInfo existingAcl: getAcls()) { |
| 301 | + if (existingAcl.getName().equals(ozoneAcl.getName()) && |
| 302 | + existingAcl.getType().equals(ozoneAcl.getType())) { |
| 303 | + |
| 304 | + BitSet bits = BitSet.valueOf(ozoneAcl.getRights().toByteArray()); |
| 305 | + BitSet existingAclBits = |
| 306 | + BitSet.valueOf(existingAcl.getRights().toByteArray()); |
| 307 | + bits.and(existingAclBits); |
| 308 | + |
| 309 | + // This happens when the acl bitset asked to remove is not set for |
| 310 | + // matched name and type. |
| 311 | + // Like a case we have 444 permission, 333 is asked to removed. |
| 312 | + if (bits.equals(ZERO_BITSET)) { |
| 313 | + return false; |
| 314 | + } |
| 315 | + |
| 316 | + // We have some matching. Remove them. |
| 317 | + bits.xor(existingAclBits); |
| 318 | + |
| 319 | + // If existing acl has same bitset as passed acl bitset, remove that |
| 320 | + // acl from the list |
| 321 | + if (bits.equals(ZERO_BITSET)) { |
| 322 | + getAcls().remove(existingAcl); |
| 323 | + } else { |
| 324 | + // Remove old acl and add new acl. |
| 325 | + OzoneAclInfo newAcl = OzoneAclInfo.newBuilder() |
| 326 | + .setType(ozoneAcl.getType()) |
| 327 | + .setName(ozoneAcl.getName()) |
| 328 | + .setAclScope(ozoneAcl.getAclScope()) |
| 329 | + .setRights(ByteString.copyFrom(bits.toByteArray())) |
| 330 | + .build(); |
| 331 | + getAcls().remove(existingAcl); |
| 332 | + getAcls().add(newAcl); |
| 333 | + } |
| 334 | + removed = true; |
| 335 | + break; |
| 336 | + } |
| 337 | + } |
| 338 | + |
| 339 | + return removed; |
| 340 | + } |
| 341 | + |
| 342 | + /** |
| 343 | + * Reset the existing acl list. |
| 344 | + * @param ozoneAcls |
| 345 | + * @return true - if successfully able to reset. |
| 346 | + */ |
| 347 | + public boolean setAcls(List<OzoneAclInfo> ozoneAcls) { |
| 348 | + this.acls.clear(); |
| 349 | + this.acls = ozoneAcls; |
| 350 | + return true; |
| 351 | + } |
| 352 | + |
| 353 | + |
| 354 | + |
238 | 355 | /** |
239 | 356 | * Builder of OmKeyInfo. |
240 | 357 | */ |
@@ -320,7 +437,8 @@ public Builder setFileEncryptionInfo(FileEncryptionInfo feInfo) { |
320 | 437 | } |
321 | 438 |
|
322 | 439 | public Builder setAcls(List<OzoneAclInfo> listOfAcls) { |
323 | | - this.acls = listOfAcls; |
| 440 | + this.acls = new ArrayList<>(); |
| 441 | + this.acls.addAll(listOfAcls); |
324 | 442 | return this; |
325 | 443 | } |
326 | 444 |
|
@@ -359,22 +477,22 @@ public KeyInfo getProtobuf() { |
359 | 477 | } |
360 | 478 |
|
361 | 479 | public static OmKeyInfo getFromProtobuf(KeyInfo keyInfo) { |
362 | | - return new OmKeyInfo( |
363 | | - keyInfo.getVolumeName(), |
364 | | - keyInfo.getBucketName(), |
365 | | - keyInfo.getKeyName(), |
366 | | - keyInfo.getKeyLocationListList().stream() |
| 480 | + return new OmKeyInfo.Builder() |
| 481 | + .setVolumeName(keyInfo.getVolumeName()) |
| 482 | + .setBucketName(keyInfo.getBucketName()) |
| 483 | + .setKeyName(keyInfo.getKeyName()) |
| 484 | + .setOmKeyLocationInfos(keyInfo.getKeyLocationListList().stream() |
367 | 485 | .map(OmKeyLocationInfoGroup::getFromProtobuf) |
368 | | - .collect(Collectors.toList()), |
369 | | - keyInfo.getDataSize(), |
370 | | - keyInfo.getCreationTime(), |
371 | | - keyInfo.getModificationTime(), |
372 | | - keyInfo.getType(), |
373 | | - keyInfo.getFactor(), |
374 | | - KeyValueUtil.getFromProtobuf(keyInfo.getMetadataList()), |
375 | | - keyInfo.hasFileEncryptionInfo() ? OMPBHelper.convert(keyInfo |
376 | | - .getFileEncryptionInfo()): null, |
377 | | - keyInfo.getAclsList()); |
| 486 | + .collect(Collectors.toList())) |
| 487 | + .setDataSize(keyInfo.getDataSize()) |
| 488 | + .setCreationTime(keyInfo.getCreationTime()) |
| 489 | + .setModificationTime(keyInfo.getModificationTime()) |
| 490 | + .setReplicationType(keyInfo.getType()) |
| 491 | + .setReplicationFactor(keyInfo.getFactor()) |
| 492 | + .addAllMetadata(KeyValueUtil.getFromProtobuf(keyInfo.getMetadataList())) |
| 493 | + .setFileEncryptionInfo(keyInfo.hasFileEncryptionInfo() ? |
| 494 | + OMPBHelper.convert(keyInfo.getFileEncryptionInfo()): null) |
| 495 | + .setAcls(keyInfo.getAclsList()).build(); |
378 | 496 | } |
379 | 497 |
|
380 | 498 | @Override |
|
0 commit comments