Mercurial > hg > orthanc-object-storage
annotate Azure/AzureBlobStoragePlugin.cpp @ 171:98371e70c460
integration 1.2.0: back to mainline
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 25 Jun 2024 12:07:52 +0200 |
parents | 6dd8bb916573 |
children |
rev | line source |
---|---|
1 | 1 /** |
2 * Cloud storage plugins for Orthanc | |
145
3c7e0374f28e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
111
diff
changeset
|
3 * Copyright (C) 2020-2023 Osimis S.A., Belgium |
3c7e0374f28e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
111
diff
changeset
|
4 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
3c7e0374f28e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
111
diff
changeset
|
5 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
1 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
56
b922ae86bbe1
full static linking against AWS SDK
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
48
diff
changeset
|
21 |
1 | 22 #include "AzureBlobStoragePlugin.h" |
23 | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
24 #include <azure/storage/blobs.hpp> |
1 | 25 #include <boost/lexical_cast.hpp> |
12
a203d0a4fd8f
Azure: now removing spaces and CR at the end of the connectionString since it prevented the plugin to initialize.
Alain Mazy
parents:
11
diff
changeset
|
26 #include <boost/algorithm/string.hpp> |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
27 // #include "cpprest/rawptrstream.h" |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
28 // #include "cpprest/details/basic_types.h" |
1 | 29 |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
30 #include <Logging.h> |
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
31 |
1 | 32 // Create aliases to make the code easier to read. |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
33 namespace as = Azure::Storage::Blobs; |
1 | 34 |
78 | 35 class AzureBlobStoragePlugin : public BaseStorage |
1 | 36 { |
37 public: | |
38 | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
39 as::BlobContainerClient blobClient_; |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
40 bool storageContainsUnknownFiles_; |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
41 |
1 | 42 public: |
43 | |
79 | 44 AzureBlobStoragePlugin(const std::string& nameForLogs, |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
45 const as::BlobContainerClient& blobClient, |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
46 bool enableLegacyStorageStructure, |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
47 bool storageContainsUnknownFiles |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
48 ); |
1 | 49 |
153 | 50 virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; |
51 virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; | |
52 virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; | |
53 virtual bool HasFileExists() ORTHANC_OVERRIDE {return false;}; | |
1 | 54 }; |
55 | |
56 | |
78 | 57 class Writer : public IStorage::IWriter |
1 | 58 { |
59 std::string path_; | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
60 as::BlobContainerClient client_; |
1 | 61 |
62 public: | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
63 Writer(const std::string& path, const as::BlobContainerClient& client) |
1 | 64 : path_(path), |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
65 client_(client) |
1 | 66 { |
67 } | |
68 | |
69 virtual ~Writer() | |
70 { | |
71 } | |
72 | |
153 | 73 virtual void Write(const char* data, size_t size) ORTHANC_OVERRIDE |
1 | 74 { |
75 try | |
76 { | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
77 as::BlockBlobClient blobClient = client_.GetBlockBlobClient(path_); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
78 blobClient.UploadFrom(reinterpret_cast<const uint8_t*>(data), size); |
1 | 79 } |
80 catch (std::exception& ex) | |
81 { | |
82 throw StoragePluginException("AzureBlobStorage: error writing file " + std::string(path_) + ": " + ex.what()); | |
83 } | |
84 } | |
85 }; | |
86 | |
87 | |
78 | 88 class Reader : public IStorage::IReader |
1 | 89 { |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
90 std::string path_; |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
91 as::BlobContainerClient client_; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
92 int64_t size_; |
1 | 93 |
94 public: | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
95 Reader(const std::list<std::string>& paths, const as::BlobContainerClient& client) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
96 : client_(client) |
1 | 97 { |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
98 std::string firstExceptionMessage; |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
99 |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
100 for (auto& path: paths) |
1 | 101 { |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
102 try |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
103 { |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
104 as::BlockBlobClient blobClient = client_.GetBlockBlobClient(path); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
105 auto properties = blobClient.GetProperties().Value; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
106 size_ = properties.BlobSize; |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
107 path_ = path; |
71 | 108 return; |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
109 } |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
110 catch (std::exception& ex) |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
111 { |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
112 if (firstExceptionMessage.empty()) |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
113 { |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
114 firstExceptionMessage = "AzureBlobStorage: error opening file for reading " + std::string(path) + ": " + ex.what(); |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
115 } |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
116 //ignore to retry |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
117 } |
1 | 118 } |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
119 throw StoragePluginException(firstExceptionMessage); |
1 | 120 } |
121 | |
122 virtual ~Reader() | |
123 { | |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
124 } |
1 | 125 |
153 | 126 virtual size_t GetSize() ORTHANC_OVERRIDE |
1 | 127 { |
128 try | |
129 { | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
130 return static_cast<size_t>(size_); |
1 | 131 } |
132 catch (std::exception& ex) | |
133 { | |
134 throw StoragePluginException("AzureBlobStorage: error while reading file " + std::string(path_) + ": " + ex.what()); | |
135 } | |
136 } | |
137 | |
153 | 138 virtual void ReadWhole(char* data, size_t size) ORTHANC_OVERRIDE |
1 | 139 { |
140 try | |
141 { | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
142 as::BlockBlobClient blobClient = client_.GetBlockBlobClient(path_); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
143 blobClient.DownloadTo(reinterpret_cast<uint8_t*>(data), static_cast<int64_t>(size)); |
1 | 144 } |
145 catch (std::exception& ex) | |
146 { | |
147 throw StoragePluginException("AzureBlobStorage: error while reading file " + std::string(path_) + ": " + ex.what()); | |
148 } | |
149 } | |
150 | |
153 | 151 virtual void ReadRange(char* data, size_t size, size_t fromOffset) ORTHANC_OVERRIDE |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
152 { |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
153 try |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
154 { |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
155 as::BlockBlobClient blobClient = client_.GetBlockBlobClient(path_); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
156 as::DownloadBlobToOptions options; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
157 options.Range = Azure::Core::Http::HttpRange(); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
158 options.Range.Value().Length = static_cast<int64_t>(size); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
159 options.Range.Value().Offset = static_cast<int64_t>(fromOffset); |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
160 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
161 blobClient.DownloadTo(reinterpret_cast<uint8_t*>(data), static_cast<int64_t>(size), options); |
39
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
162 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
163 catch (std::exception& ex) |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
164 { |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
165 throw StoragePluginException("AzureBlobStorage: error while reading partial file " + std::string(path_) + ": " + ex.what()); |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
166 } |
50d0be413c42
implemented ReadRange (only in Azure plugin right now)
Alain Mazy <am@osimis.io>
parents:
37
diff
changeset
|
167 } |
1 | 168 }; |
169 | |
170 | |
171 | |
172 const char* AzureBlobStoragePluginFactory::GetStoragePluginName() | |
173 { | |
174 return "Azure Blob Storage"; | |
175 } | |
176 | |
94
1bc055199cd2
Added a description for all plugins
Alain Mazy <am@osimis.io>
parents:
92
diff
changeset
|
177 const char* AzureBlobStoragePluginFactory::GetStorageDescription() |
1bc055199cd2
Added a description for all plugins
Alain Mazy <am@osimis.io>
parents:
92
diff
changeset
|
178 { |
1bc055199cd2
Added a description for all plugins
Alain Mazy <am@osimis.io>
parents:
92
diff
changeset
|
179 return "Stores the Orthanc storage area in Azure Blob"; |
1bc055199cd2
Added a description for all plugins
Alain Mazy <am@osimis.io>
parents:
92
diff
changeset
|
180 } |
1bc055199cd2
Added a description for all plugins
Alain Mazy <am@osimis.io>
parents:
92
diff
changeset
|
181 |
1bc055199cd2
Added a description for all plugins
Alain Mazy <am@osimis.io>
parents:
92
diff
changeset
|
182 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
183 // bool IsSasTokenAccountLevel(utility::string_t sasToken) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
184 // { |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
185 // // Use cpprestsdk's utility::string_t here since the expected argument is the return value of |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
186 // // as::storage_credentials::sas_token(), which is type utility::string_t (which is a std::wstring on Windows and a std::string on Linux) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
187 // size_t newIdx = 0; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
188 // size_t prevIdx = 0; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
189 // while ((newIdx = sasToken.find('&', prevIdx)) != utility::string_t::npos) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
190 // { |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
191 // utility::string_t kvpair = sasToken.substr(prevIdx, newIdx - prevIdx); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
192 // prevIdx = newIdx + 1; // start next time from char after '&' |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
193 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
194 // size_t equalsIdx = kvpair.find('='); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
195 // utility::string_t key = kvpair.substr(0, equalsIdx); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
196 // #ifdef WIN32 |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
197 // const wchar_t* srt = L"srt"; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
198 // #else |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
199 // const char* srt = "srt"; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
200 // #endif |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
201 // if (key == srt) // only account SAS has this parameter |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
202 // return true; |
89 | 203 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
204 // } |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
205 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
206 // return false; |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
207 // } |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
208 |
79 | 209 IStorage* AzureBlobStoragePluginFactory::CreateStorage(const std::string& nameForLogs, const OrthancPlugins::OrthancConfiguration& orthancConfig) |
1 | 210 { |
211 std::string connectionString; | |
212 std::string containerName; | |
15 | 213 bool enableLegacyStorageStructure; |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
214 bool storageContainsUnknownFiles; |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
215 bool createContainerIfNotExists; |
1 | 216 |
81 | 217 if (orthancConfig.IsSection(GetConfigurationSectionName())) |
1 | 218 { |
219 OrthancPlugins::OrthancConfiguration pluginSection; | |
81 | 220 orthancConfig.GetSection(pluginSection, GetConfigurationSectionName()); |
1 | 221 |
78 | 222 if (!BaseStorage::ReadCommonConfiguration(enableLegacyStorageStructure, storageContainsUnknownFiles, pluginSection)) |
15 | 223 { |
224 return nullptr; | |
225 } | |
226 | |
1 | 227 if (!pluginSection.LookupStringValue(connectionString, "ConnectionString")) |
228 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
229 LOG(ERROR) << "AzureBlobStorage/ConnectionString configuration missing. Unable to initialize plugin"; |
1 | 230 return nullptr; |
231 } | |
232 | |
233 if (!pluginSection.LookupStringValue(containerName, "ContainerName")) | |
234 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
235 LOG(ERROR) << "AzureBlobStorage/ContainerName configuration missing. Unable to initialize plugin"; |
1 | 236 return nullptr; |
237 } | |
238 | |
12
a203d0a4fd8f
Azure: now removing spaces and CR at the end of the connectionString since it prevented the plugin to initialize.
Alain Mazy
parents:
11
diff
changeset
|
239 boost::trim(connectionString); // without that, if there's an EOL in the string, it fails with "provided uri is invalid" |
a203d0a4fd8f
Azure: now removing spaces and CR at the end of the connectionString since it prevented the plugin to initialize.
Alain Mazy
parents:
11
diff
changeset
|
240 boost::trim(containerName); |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
241 |
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
242 createContainerIfNotExists = pluginSection.GetBooleanValue("CreateContainerIfNotExists", true); |
1 | 243 } |
244 else if (orthancConfig.IsSection("BlobStorage")) // backward compatibility with the old plugin: | |
245 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
246 LOG(WARNING) << "AzureBlobStorage: you're using an old configuration format for the plugin."; |
1 | 247 |
248 OrthancPlugins::OrthancConfiguration pluginSection; | |
249 orthancConfig.GetSection(pluginSection, "BlobStorage"); | |
250 | |
251 std::string accountName; | |
252 std::string accountKey; | |
253 | |
254 if (!pluginSection.LookupStringValue(containerName, "ContainerName")) | |
255 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
256 LOG(ERROR) << "BlobStorage/AccountName configuration missing. Unable to initialize plugin"; |
1 | 257 return nullptr; |
258 } | |
259 | |
260 if (!pluginSection.LookupStringValue(accountName, "AccountName")) | |
261 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
262 LOG(ERROR) << "BlobStorage/AccountName configuration missing. Unable to initialize plugin"; |
1 | 263 return nullptr; |
264 } | |
265 | |
266 if (!pluginSection.LookupStringValue(accountKey, "AccountKey")) | |
267 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
268 LOG(ERROR) << "BlobStorage/ContainerName configuration missing. Unable to initialize plugin"; |
1 | 269 return nullptr; |
270 } | |
271 | |
272 std::ostringstream connectionStringBuilder; | |
273 connectionStringBuilder << "DefaultEndpointsProtocol=https;AccountName=" << accountName << ";AccountKey=" << accountKey; | |
274 connectionString = connectionStringBuilder.str(); | |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
275 |
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
276 createContainerIfNotExists = pluginSection.GetBooleanValue("CreateContainerIfNotExists", true); |
1 | 277 } |
278 else | |
279 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
280 LOG(WARNING) << GetStoragePluginName() << " plugin, section missing. Plugin is not enabled."; |
1 | 281 return nullptr; |
282 } | |
283 | |
284 try | |
285 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
286 LOG(INFO) << "Connecting to Azure storage ..."; |
11 | 287 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
288 as::BlobContainerClient client = as::BlobContainerClient::CreateFromConnectionString(connectionString, containerName); |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
289 LOG(INFO) << "Blob client created"; |
11 | 290 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
291 if (createContainerIfNotExists) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
292 { |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
293 // Note: in version up to 2.1.2, we had this code: |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
294 // // blobContainer.create_if_not_exists() throws an error if a service SAS (for a blob container) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
295 // // was used in the connectionString. |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
296 // // Only allow the use of this function when using storage account-level credentials, whether |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
297 // // through accountName/accountKey combo or account SAS. |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
298 // if ((storageAccount.credentials().is_account_key() || |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
299 // (storageAccount.credentials().is_sas() && IsSasTokenAccountLevel(storageAccount.credentials().sas_token()))) |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
300 // && createContainerIfNotExists) |
1 | 301 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
302 auto createResult = client.CreateIfNotExists(); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
303 if (createResult.Value.Created) |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
304 { |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
305 LOG(WARNING) << "Blob Storage Area container has been created. **** check in the Azure console that your container is private ****"; |
46
3b8fab63313d
Add "CreateContainerIfNotExists" config for Azure
Mark Poscablo <Mark.Poscablo@varian.com>
parents:
15
diff
changeset
|
306 } |
1 | 307 } |
308 | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
309 LOG(INFO) << "Blob storage initialized"; |
1 | 310 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
311 return new AzureBlobStoragePlugin(nameForLogs, client, enableLegacyStorageStructure, storageContainsUnknownFiles); |
1 | 312 } |
313 catch (const std::exception& e) | |
314 { | |
152
d62f52be1943
use Orthanc frameworking for logging
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
145
diff
changeset
|
315 LOG(ERROR) << "AzureBlobStorage plugin: failed to initialize plugin: " << e.what(); |
1 | 316 return nullptr; |
317 } | |
318 | |
319 } | |
320 | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
321 AzureBlobStoragePlugin::AzureBlobStoragePlugin(const std::string& nameForLogs, const as::BlobContainerClient& blobClient, bool enableLegacyStorageStructure, bool storageContainsUnknownFiles) |
79 | 322 : BaseStorage(nameForLogs, enableLegacyStorageStructure), |
15 | 323 blobClient_(blobClient), |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
324 storageContainsUnknownFiles_(storageContainsUnknownFiles) |
1 | 325 { |
326 | |
327 } | |
328 | |
78 | 329 IStorage::IWriter* AzureBlobStoragePlugin::GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) |
1 | 330 { |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
331 return new Writer(GetPath(uuid, type, encryptionEnabled), blobClient_); |
1 | 332 } |
333 | |
78 | 334 IStorage::IReader* AzureBlobStoragePlugin::GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) |
1 | 335 { |
70
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
336 std::list<std::string> paths; |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
337 paths.push_back(GetPath(uuid, type, encryptionEnabled, false)); |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
338 if (storageContainsUnknownFiles_) |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
339 { |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
340 paths.push_back(GetPath(uuid, type, encryptionEnabled, true)); |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
341 } |
16e419fe80c5
Google & Azure: Added the "EnableLegacyUnknownFiles" configuration option
Alain Mazy <am@osimis.io>
parents:
56
diff
changeset
|
342 |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
343 return new Reader(paths, blobClient_); |
1 | 344 } |
345 | |
346 void AzureBlobStoragePlugin::DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) | |
347 { | |
348 std::string path = GetPath(uuid, type, encryptionEnabled); | |
349 | |
350 try | |
351 { | |
99
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
352 as::BlockBlobClient blobClient = blobClient_.GetBlockBlobClient(path); |
f4e05641c108
rewrote using the latest azure C++ sdk
Alain Mazy <am@osimis.io>
parents:
94
diff
changeset
|
353 blobClient.Delete(); |
1 | 354 } |
355 catch (std::exception& ex) | |
356 { | |
357 throw StoragePluginException("AzureBlobStorage: error while deleting file " + std::string(path) + ": " + ex.what()); | |
358 } | |
359 } |