Skip to content

Commit c1eb975

Browse files
committed
Added sample for directory usage
1 parent 8bfa7b4 commit c1eb975

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

samples/blob/directory_usage.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import uuid
2+
3+
from tests.settings_real import (
4+
STORAGE_ACCOUNT_NAME,
5+
STORAGE_ACCOUNT_KEY,
6+
HIERARCHICAL_NAMESPACE_ACCOUNT_NAME,
7+
HIERARCHICAL_NAMESPACE_ACCOUNT_KEY,
8+
ACTIVE_DIRECTORY_APPLICATION_ID
9+
)
10+
from azure.storage.blob import (
11+
BlockBlobService
12+
)
13+
14+
# toggle this constant to see different behaviors
15+
# when HNS is enabled:
16+
# - get/set access control operations are supported
17+
# - rename/delete operations are atomic
18+
IS_HNS_ENABLED = False
19+
20+
21+
def run():
22+
# swap in your test accounts
23+
if IS_HNS_ENABLED:
24+
blob_service = BlockBlobService(HIERARCHICAL_NAMESPACE_ACCOUNT_NAME, HIERARCHICAL_NAMESPACE_ACCOUNT_KEY)
25+
else:
26+
blob_service = BlockBlobService(STORAGE_ACCOUNT_NAME, STORAGE_ACCOUNT_KEY, protocol="http")
27+
28+
# set up a test container
29+
container_name = "testcontainer"
30+
blob_service.create_container(container_name)
31+
32+
try:
33+
demonstrate_directory_usage(blob_service, container_name)
34+
finally:
35+
# clean up the test container
36+
blob_service.delete_container(container_name)
37+
38+
39+
def demonstrate_directory_usage(blob_service, container_name):
40+
directory_name = "dir"
41+
42+
# usage 1: create a directory with metadata inside the container
43+
props = blob_service.create_directory(container_name, directory_path=directory_name, metadata={"test": "value"})
44+
45+
# show the etag and lmt of the newly created directory
46+
print("Etag: {}".format(props.etag))
47+
print("Lmt: {}".format(props.last_modified))
48+
49+
# populate the created directory with some blobs
50+
_create_blobs(blob_service, container_name, directory_name, num_of_blobs=200)
51+
52+
# these APIs only work against an account where HNS is enabled
53+
if IS_HNS_ENABLED:
54+
# usage 2: set the access control properties on the directory
55+
test_owner = ACTIVE_DIRECTORY_APPLICATION_ID
56+
test_group = ACTIVE_DIRECTORY_APPLICATION_ID
57+
test_permissions = 'rwxrw-rw-'
58+
blob_service.set_path_access_control(container_name, directory_name, owner=test_owner, group=test_group,
59+
permissions=test_permissions)
60+
61+
# usage 3: fetch the access control information on the directory
62+
access_control_props = blob_service.get_path_access_control(
63+
container_name, directory_name, user_principle_names=True)
64+
65+
# print out values
66+
print("Owner: {}".format(access_control_props.owner))
67+
print("Permissions: {}".format(access_control_props.permissions))
68+
print("Group: {}".format(access_control_props.group))
69+
print("Acl: {}".format(access_control_props.acl))
70+
71+
# usage 4: rename directory, see method for more details
72+
new_directory_name = "dir2"
73+
rename_directory(blob_service, container_name, new_directory_name, directory_name)
74+
75+
# usage 5: delete the directory, see method for more details
76+
delete_directory(blob_service, container_name, new_directory_name)
77+
78+
79+
def rename_directory(blob_service, container_name, new_directory_name, old_directory_name):
80+
marker = blob_service.rename_path(container_name, new_directory_name, old_directory_name)
81+
82+
# if HNS is enabled, the rename operation is atomic and no marker is returned
83+
# if HNS is not enabled, and there are too more files/subdirectories in the directories to be renamed
84+
# in a single call, the service returns a marker, so that we can follow it and finish renaming
85+
# the rest of the files/subdirectories
86+
count = 1
87+
while marker is not None:
88+
marker = blob_service.rename_path(container_name, new_directory_name, old_directory_name, marker=marker)
89+
count += 1
90+
91+
print("Took {} call(s) to finish renaming.".format(count))
92+
93+
94+
def delete_directory(blob_service, container_name, directory_name):
95+
deleted, marker = blob_service.delete_directory(container_name, directory_name, recursive=True)
96+
97+
# if HNS is enabled, the delete operation is atomic and no marker is returned
98+
# if HNS is not enabled, and there are too more files/subdirectories in the directories to be deleted
99+
# in a single call, the service returns a marker, so that we can follow it and finish deleting
100+
# the rest of the files/subdirectories
101+
count = 1
102+
while marker is not None:
103+
deleted, marker = blob_service.delete_directory(container_name, directory_name,
104+
marker=marker, recursive=True)
105+
count += 1
106+
107+
print("Took {} calls(s) to finish deleting.".format(count))
108+
109+
110+
def _create_blobs(blob_service, container_name, directory_name, num_of_blobs):
111+
import concurrent.futures
112+
import itertools
113+
# Use a thread pool because it is too slow otherwise
114+
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
115+
def create_blob():
116+
# generate a random name
117+
blob_name = "{}/{}".format(directory_name, str(uuid.uuid4()).replace('-', ''))
118+
119+
# create a blob under the directory
120+
# blob_service.create_blob_from_bytes(container_name, blob_name, b"test")
121+
blob_service.create_directory(container_name, blob_name)
122+
123+
futures = {executor.submit(create_blob) for _ in itertools.repeat(None, num_of_blobs)}
124+
concurrent.futures.wait(futures)
125+
print("Created {} blobs under the directory: {}".format(num_of_blobs, directory_name))
126+
127+
128+
if __name__ == '__main__':
129+
run()

0 commit comments

Comments
 (0)