1""" 2.. versionadded:: 2015.8.0 3 4Utilities for accessing storage container blobs on Azure 5""" 6 7 8import logging 9 10from salt.exceptions import SaltSystemExit 11 12HAS_LIBS = False 13try: 14 import azure 15 16 HAS_LIBS = True 17except ImportError: 18 pass 19 20 21log = logging.getLogger(__name__) 22 23 24def get_storage_conn(storage_account=None, storage_key=None, opts=None): 25 """ 26 .. versionadded:: 2015.8.0 27 28 Return a storage_conn object for the storage account 29 """ 30 if opts is None: 31 opts = {} 32 33 if not storage_account: 34 storage_account = opts.get("storage_account", None) 35 if not storage_key: 36 storage_key = opts.get("storage_key", None) 37 38 return azure.storage.BlobService(storage_account, storage_key) 39 40 41def list_blobs(storage_conn=None, **kwargs): 42 """ 43 .. versionadded:: 2015.8.0 44 45 List blobs associated with the container 46 """ 47 if not storage_conn: 48 storage_conn = get_storage_conn(opts=kwargs) 49 50 if "container" not in kwargs: 51 raise SaltSystemExit( 52 code=42, msg='An storage container name must be specified as "container"' 53 ) 54 55 data = storage_conn.list_blobs( 56 container_name=kwargs["container"], 57 prefix=kwargs.get("prefix", None), 58 marker=kwargs.get("marker", None), 59 maxresults=kwargs.get("maxresults", None), 60 include=kwargs.get("include", None), 61 delimiter=kwargs.get("delimiter", None), 62 ) 63 64 ret = {} 65 for item in data.blobs: 66 ret[item.name] = object_to_dict(item) 67 return ret 68 69 70def put_blob(storage_conn=None, **kwargs): 71 """ 72 .. versionadded:: 2015.8.0 73 74 Upload a blob 75 """ 76 if not storage_conn: 77 storage_conn = get_storage_conn(opts=kwargs) 78 79 if "container" not in kwargs: 80 raise SaltSystemExit( 81 code=42, msg='The blob container name must be specified as "container"' 82 ) 83 84 if "name" not in kwargs: 85 raise SaltSystemExit(code=42, msg='The blob name must be specified as "name"') 86 87 if "blob_path" not in kwargs and "blob_content" not in kwargs: 88 raise SaltSystemExit( 89 code=42, 90 msg=( 91 'Either a path to a file needs to be passed in as "blob_path" ' 92 'or the contents of a blob as "blob_content."' 93 ), 94 ) 95 96 blob_kwargs = { 97 "container_name": kwargs["container"], 98 "blob_name": kwargs["name"], 99 "cache_control": kwargs.get("cache_control", None), 100 "content_language": kwargs.get("content_language", None), 101 "content_md5": kwargs.get("content_md5", None), 102 "x_ms_blob_content_type": kwargs.get("blob_content_type", None), 103 "x_ms_blob_content_encoding": kwargs.get("blob_content_encoding", None), 104 "x_ms_blob_content_language": kwargs.get("blob_content_language", None), 105 "x_ms_blob_content_md5": kwargs.get("blob_content_md5", None), 106 "x_ms_blob_cache_control": kwargs.get("blob_cache_control", None), 107 "x_ms_meta_name_values": kwargs.get("meta_name_values", None), 108 "x_ms_lease_id": kwargs.get("lease_id", None), 109 } 110 if "blob_path" in kwargs: 111 data = storage_conn.put_block_blob_from_path( 112 file_path=kwargs["blob_path"], **blob_kwargs 113 ) 114 elif "blob_content" in kwargs: 115 data = storage_conn.put_block_blob_from_bytes( 116 blob=kwargs["blob_content"], **blob_kwargs 117 ) 118 119 return data 120 121 122def get_blob(storage_conn=None, **kwargs): 123 """ 124 .. versionadded:: 2015.8.0 125 126 Download a blob 127 """ 128 if not storage_conn: 129 storage_conn = get_storage_conn(opts=kwargs) 130 131 if "container" not in kwargs: 132 raise SaltSystemExit( 133 code=42, msg='The blob container name must be specified as "container"' 134 ) 135 136 if "name" not in kwargs: 137 raise SaltSystemExit(code=42, msg='The blob name must be specified as "name"') 138 139 if "local_path" not in kwargs and "return_content" not in kwargs: 140 raise SaltSystemExit( 141 code=42, 142 msg=( 143 'Either a local path needs to be passed in as "local_path", ' 144 'or "return_content" to return the blob contents directly' 145 ), 146 ) 147 148 blob_kwargs = { 149 "container_name": kwargs["container"], 150 "blob_name": kwargs["name"], 151 "snapshot": kwargs.get("snapshot", None), 152 "x_ms_lease_id": kwargs.get("lease_id", None), 153 "progress_callback": kwargs.get("progress_callback", None), 154 "max_connections": kwargs.get("max_connections", 1), 155 "max_retries": kwargs.get("max_retries", 5), 156 "retry_wait": kwargs.get("retry_wait", 1), 157 } 158 159 if "local_path" in kwargs: 160 data = storage_conn.get_blob_to_path( 161 file_path=kwargs["local_path"], 162 open_mode=kwargs.get("open_mode", "wb"), 163 **blob_kwargs 164 ) 165 elif "return_content" in kwargs: 166 data = storage_conn.get_blob_to_bytes(**blob_kwargs) 167 168 return data 169 170 171def object_to_dict(obj): 172 """ 173 .. versionadded:: 2015.8.0 174 175 Convert an object to a dictionary 176 """ 177 if isinstance(obj, list) or isinstance(obj, tuple): 178 ret = [] 179 for item in obj: 180 ret.append(object_to_dict(item)) 181 elif hasattr(obj, "__dict__"): 182 ret = {} 183 for item in obj.__dict__: 184 if item.startswith("_"): 185 continue 186 ret[item] = object_to_dict(obj.__dict__[item]) 187 else: 188 ret = obj 189 return ret 190