Mercurial > hg > orthanc-object-storage
annotate Aws/AwsS3StoragePlugin.cpp @ 183:7a5d3e97b454 1.3.2
closing branch 1.3.2
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 25 Jun 2024 12:12:44 +0200 |
parents | 58a03fce4897 |
children | 16e419fe80c5 |
rev | line source |
---|---|
1 | 1 /** |
2 * Cloud storage plugins for Orthanc | |
37
f55b2afdf53d
upgrade to year 2021
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
33
diff
changeset
|
3 * Copyright (C) 2020-2021 Osimis S.A., Belgium |
1 | 4 * |
5 * This program is free software: you can redistribute it and/or | |
6 * modify it under the terms of the GNU Affero General Public License | |
7 * as published by the Free Software Foundation, either version 3 of | |
8 * the License, or (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, but | |
11 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Affero General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Affero General Public License | |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 **/ | |
18 | |
19 #include "AwsS3StoragePlugin.h" | |
20 | |
21 #include <aws/core/Aws.h> | |
22 #include <aws/s3/S3Client.h> | |
23 #include <aws/s3/model/PutObjectRequest.h> | |
24 #include <aws/s3/model/GetObjectRequest.h> | |
25 #include <aws/s3/model/ListObjectsRequest.h> | |
26 #include <aws/s3/model/DeleteObjectRequest.h> | |
27 #include <aws/core/auth/AWSCredentialsProvider.h> | |
28 #include <aws/core/utils/memory/stl/AWSStringStream.h> | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
29 #include <aws/crt/Api.h> |
1 | 30 |
31 #include <boost/lexical_cast.hpp> | |
32 #include <iostream> | |
33 #include <fstream> | |
34 | |
35 const char* ALLOCATION_TAG = "OrthancS3"; | |
15 | 36 static const char* const PLUGIN_SECTION = "AwsS3Storage"; |
1 | 37 |
15 | 38 class AwsS3StoragePlugin : public BaseStoragePlugin |
1 | 39 { |
40 public: | |
41 | |
42 Aws::S3::S3Client client_; | |
43 std::string bucketName_; | |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
44 bool storageContainsUnknownFiles_; |
1 | 45 |
46 public: | |
47 | |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
48 AwsS3StoragePlugin(const Aws::S3::S3Client& client, const std::string& bucketName, bool enableLegacyStorageStructure, bool storageContainsUnknownFiles); |
1 | 49 |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
50 virtual ~AwsS3StoragePlugin(); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
51 |
1 | 52 virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); |
53 virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); | |
54 virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); | |
15 | 55 virtual const char* GetConfigurationSectionName() {return PLUGIN_SECTION;}; |
1 | 56 }; |
57 | |
58 | |
59 class Writer : public IStoragePlugin::IWriter | |
60 { | |
61 std::string path_; | |
62 Aws::S3::S3Client client_; | |
63 std::string bucketName_; | |
64 | |
65 public: | |
66 Writer(const Aws::S3::S3Client& client, const std::string& bucketName, const std::string& path) | |
67 : path_(path), | |
68 client_(client), | |
69 bucketName_(bucketName) | |
70 { | |
71 } | |
72 | |
73 virtual ~Writer() | |
74 { | |
75 } | |
76 | |
77 virtual void Write(const char* data, size_t size) | |
78 { | |
79 Aws::S3::Model::PutObjectRequest putObjectRequest; | |
80 | |
81 putObjectRequest.SetBucket(bucketName_.c_str()); | |
82 putObjectRequest.SetKey(path_.c_str()); | |
83 | |
84 std::shared_ptr<Aws::StringStream> stream = Aws::MakeShared<Aws::StringStream>(ALLOCATION_TAG, std::ios_base::in | std::ios_base::binary); | |
85 | |
86 stream->rdbuf()->pubsetbuf(const_cast<char*>(data), size); | |
87 stream->rdbuf()->pubseekpos(size); | |
88 stream->seekg(0); | |
89 | |
90 putObjectRequest.SetBody(stream); | |
91 | |
92 auto result = client_.PutObject(putObjectRequest); | |
93 | |
94 if (!result.IsSuccess()) | |
95 { | |
62 | 96 throw StoragePluginException(std::string("error while writing file ") + path_ + ": response code = " + boost::lexical_cast<std::string>((int)result.GetError().GetResponseCode()) + " " + result.GetError().GetExceptionName().c_str() + " " + result.GetError().GetMessage().c_str()); |
1 | 97 } |
98 } | |
99 }; | |
100 | |
101 | |
102 class Reader : public IStoragePlugin::IReader | |
103 { | |
104 Aws::S3::S3Client client_; | |
105 std::string bucketName_; | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
106 std::list<std::string> paths_; |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
107 std::string uuid_; |
1 | 108 |
109 public: | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
110 Reader(const Aws::S3::S3Client& client, const std::string& bucketName, const std::list<std::string>& paths, const char* uuid) |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
111 : client_(client), |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
112 bucketName_(bucketName), |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
113 paths_(paths), |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
114 uuid_(uuid) |
1 | 115 { |
116 } | |
117 | |
118 virtual ~Reader() | |
119 { | |
120 | |
121 } | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
122 |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
123 size_t _GetSize(const std::string& path) |
1 | 124 { |
125 Aws::S3::Model::ListObjectsRequest listObjectRequest; | |
126 listObjectRequest.SetBucket(bucketName_.c_str()); | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
127 listObjectRequest.SetPrefix(path.c_str()); |
1 | 128 |
129 auto result = client_.ListObjects(listObjectRequest); | |
130 | |
131 if (result.IsSuccess()) | |
132 { | |
133 Aws::Vector<Aws::S3::Model::Object> objectList = | |
134 result.GetResult().GetContents(); | |
135 | |
136 if (objectList.size() == 1) | |
137 { | |
138 return objectList[0].GetSize(); | |
139 } | |
32 | 140 else if (objectList.size() > 1) |
141 { | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
142 throw StoragePluginException(std::string("error while reading file ") + path + ": multiple objet with same name !"); |
32 | 143 } |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
144 throw StoragePluginException(std::string("error while reading file ") + path + ": object not found !"); |
1 | 145 } |
146 else | |
147 { | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
148 throw StoragePluginException(std::string("error while reading file ") + path + ": " + result.GetError().GetExceptionName().c_str() + " " + result.GetError().GetMessage().c_str()); |
1 | 149 } |
150 } | |
41 | 151 |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
152 virtual size_t GetSize() |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
153 { |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
154 std::string firstExceptionMessage; |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
155 |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
156 for (auto& path: paths_) |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
157 { |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
158 try |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
159 { |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
160 return _GetSize(path); |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
161 } |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
162 catch (StoragePluginException& ex) |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
163 { |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
164 if (firstExceptionMessage.empty()) |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
165 { |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
166 firstExceptionMessage = ex.what(); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
167 } |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
168 //ignore to retry |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
169 } |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
170 } |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
171 throw StoragePluginException(firstExceptionMessage); |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
172 } |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
173 |
41 | 174 virtual void ReadWhole(char* data, size_t size) |
175 { | |
176 _Read(data, size, 0, false); | |
177 } | |
178 | |
179 virtual void ReadRange(char* data, size_t size, size_t fromOffset) | |
180 { | |
181 _Read(data, size, fromOffset, true); | |
182 } | |
183 | |
184 void _Read(char* data, size_t size, size_t fromOffset, bool useRange) | |
1 | 185 { |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
186 std::string firstExceptionMessage; |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
187 |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
188 for (auto& path: paths_) |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
189 { |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
190 try |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
191 { |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
192 return __Read(path, data, size, fromOffset, useRange); |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
193 } |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
194 catch (StoragePluginException& ex) |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
195 { |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
196 if (firstExceptionMessage.empty()) |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
197 { |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
198 firstExceptionMessage = ex.what(); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
199 } |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
200 //ignore to retry |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
201 } |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
202 } |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
203 throw StoragePluginException(firstExceptionMessage); |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
204 } |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
205 |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
206 void __Read(const std::string& path, char* data, size_t size, size_t fromOffset, bool useRange) |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
207 { |
1 | 208 Aws::S3::Model::GetObjectRequest getObjectRequest; |
209 getObjectRequest.SetBucket(bucketName_.c_str()); | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
210 getObjectRequest.SetKey(path.c_str()); |
1 | 211 |
41 | 212 if (useRange) |
213 { | |
214 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests | |
215 std::string range = std::string("bytes=") + boost::lexical_cast<std::string>(fromOffset) + "-" + boost::lexical_cast<std::string>(fromOffset + size -1); | |
216 getObjectRequest.SetRange(range.c_str()); | |
217 } | |
218 | |
1 | 219 getObjectRequest.SetResponseStreamFactory( |
220 [data, size]() | |
221 { | |
222 std::unique_ptr<Aws::StringStream> | |
223 istream(Aws::New<Aws::StringStream>(ALLOCATION_TAG)); | |
224 | |
225 istream->rdbuf()->pubsetbuf(static_cast<char*>(data), | |
226 size); | |
227 | |
228 return istream.release(); | |
229 }); | |
230 | |
231 // Get the object | |
232 auto result = client_.GetObject(getObjectRequest); | |
233 if (result.IsSuccess()) | |
234 { | |
235 } | |
236 else | |
237 { | |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
238 throw StoragePluginException(std::string("error while reading file ") + path + ": response code = " + boost::lexical_cast<std::string>((int)result.GetError().GetResponseCode()) + " " + result.GetError().GetExceptionName().c_str() + " " + result.GetError().GetMessage().c_str()); |
1 | 239 } |
240 } | |
241 | |
242 }; | |
243 | |
244 | |
245 | |
41 | 246 |
247 | |
1 | 248 const char* AwsS3StoragePluginFactory::GetStoragePluginName() |
249 { | |
250 return "AWS S3 Storage"; | |
251 } | |
252 | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
253 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
254 static std::unique_ptr<Aws::Crt::ApiHandle> api_; |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
255 static std::unique_ptr<Aws::SDKOptions> sdkOptions_; |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
256 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
257 |
1 | 258 IStoragePlugin* AwsS3StoragePluginFactory::CreateStoragePlugin(const OrthancPlugins::OrthancConfiguration& orthancConfig) |
259 { | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
260 if (sdkOptions_.get() != NULL) |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
261 { |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
262 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, "Cannot initialize twice"); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
263 } |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
264 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
265 api_.reset(new Aws::Crt::ApiHandle); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
266 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
267 sdkOptions_.reset(new Aws::SDKOptions); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
268 sdkOptions_->cryptoOptions.initAndCleanupOpenSSL = false; // Done by the Orthanc framework |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
269 sdkOptions_->httpOptions.initAndCleanupCurl = false; // Done by the Orthanc framework |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
270 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
271 Aws::InitAPI(*sdkOptions_); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
272 |
15 | 273 bool enableLegacyStorageStructure; |
274 | |
1 | 275 if (!orthancConfig.IsSection(PLUGIN_SECTION)) |
276 { | |
277 OrthancPlugins::LogWarning(std::string(GetStoragePluginName()) + " plugin, section missing. Plugin is not enabled."); | |
278 return nullptr; | |
279 } | |
280 | |
281 OrthancPlugins::OrthancConfiguration pluginSection; | |
282 orthancConfig.GetSection(pluginSection, PLUGIN_SECTION); | |
283 | |
15 | 284 if (!BaseStoragePlugin::ReadCommonConfiguration(enableLegacyStorageStructure, pluginSection)) |
285 { | |
286 return nullptr; | |
287 } | |
288 | |
1 | 289 std::string bucketName; |
290 std::string region; | |
291 std::string accessKey; | |
292 std::string secretKey; | |
293 | |
294 if (!pluginSection.LookupStringValue(bucketName, "BucketName")) | |
295 { | |
296 OrthancPlugins::LogError("AwsS3Storage/BucketName configuration missing. Unable to initialize plugin"); | |
297 return nullptr; | |
298 } | |
299 | |
300 if (!pluginSection.LookupStringValue(region, "Region")) | |
301 { | |
302 OrthancPlugins::LogError("AwsS3Storage/Region configuration missing. Unable to initialize plugin"); | |
303 return nullptr; | |
304 } | |
305 | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
306 const std::string endpoint = pluginSection.GetStringValue("Endpoint", ""); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
307 const unsigned int connectTimeout = pluginSection.GetUnsignedIntegerValue("ConnectTimeout", 30); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
308 const unsigned int requestTimeout = pluginSection.GetUnsignedIntegerValue("RequestTimeout", 1200); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
309 const bool virtualAddressing = pluginSection.GetBooleanValue("VirtualAddressing", true); |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
310 const bool storageContainsUnknownFiles = pluginSection.GetBooleanValue("EnableLegacyUnknownFiles", false); |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
311 const std::string caFile = orthancConfig.GetStringValue("HttpsCACertificates", ""); |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
15
diff
changeset
|
312 |
1 | 313 try |
314 { | |
315 Aws::SDKOptions options; | |
316 Aws::InitAPI(options); | |
317 | |
318 Aws::Client::ClientConfiguration configuration; | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
319 |
1 | 320 configuration.region = region.c_str(); |
6
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
321 configuration.scheme = Aws::Http::Scheme::HTTPS; |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
322 configuration.connectTimeoutMs = connectTimeout * 1000; |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
323 configuration.requestTimeoutMs = requestTimeout * 1000; |
27
e1f52b851827
Added "VirtualAddressing" configuration option in the AWS S3 plugin (for compatibility with minio)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
15
diff
changeset
|
324 configuration.httpRequestTimeoutMs = requestTimeout * 1000; |
6
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
325 |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
326 if (!endpoint.empty()) |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
327 { |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
328 configuration.endpointOverride = endpoint.c_str(); |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
329 } |
393fcf337462
AWS: added 3 configurations: Endpoint, ConnectionTimeout, RequestTimeout
Alain Mazy
parents:
1
diff
changeset
|
330 |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
331 if (!caFile.empty()) |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
332 { |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
333 configuration.caFile = caFile; |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
334 } |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
335 |
53
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
336 if (pluginSection.LookupStringValue(accessKey, "AccessKey") && pluginSection.LookupStringValue(secretKey, "SecretKey")) |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
337 { |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
338 OrthancPlugins::LogInfo("AWS S3 Storage: using credentials from the configuration file"); |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
339 Aws::Auth::AWSCredentials credentials(accessKey.c_str(), secretKey.c_str()); |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
340 |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
341 Aws::S3::S3Client client(credentials, configuration, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, virtualAddressing); |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
342 |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
343 OrthancPlugins::LogInfo("AWS S3 storage initialized"); |
1 | 344 |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
345 return new AwsS3StoragePlugin(client, bucketName, enableLegacyStorageStructure, storageContainsUnknownFiles); |
53
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
346 } |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
347 else |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
348 { |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
349 // when using default credentials, credentials are not checked at startup but only the first time you try to access the bucket ! |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
350 OrthancPlugins::LogInfo("AWS S3 Storage: using default credentials provider"); |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
351 Aws::S3::S3Client client(configuration, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, virtualAddressing); |
1 | 352 |
53
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
353 OrthancPlugins::LogInfo("AWS S3 storage initialized"); |
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
354 |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
355 return new AwsS3StoragePlugin(client, bucketName, enableLegacyStorageStructure, storageContainsUnknownFiles); |
53
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
356 } |
1 | 357 } |
358 catch (const std::exception& e) | |
359 { | |
53
1c3e34f5c5c6
AWS S3: if no access & secret keys are provided, now getting the credentials from the default credentials manager
Alain Mazy <am@osimis.io>
parents:
41
diff
changeset
|
360 OrthancPlugins::LogError(std::string("AWS S3 Storage plugin: failed to initialize plugin: ") + e.what()); |
1 | 361 return nullptr; |
362 } | |
363 | |
364 } | |
365 | |
57
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
366 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
367 AwsS3StoragePlugin::~AwsS3StoragePlugin() |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
368 { |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
369 assert(sdkOptions_.get() != NULL); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
370 Aws::ShutdownAPI(*sdkOptions_); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
371 api_.reset(); |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
372 } |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
373 |
ba1be668e475
fix initialization of the aws static library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
53
diff
changeset
|
374 |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
375 AwsS3StoragePlugin::AwsS3StoragePlugin(const Aws::S3::S3Client& client, const std::string& bucketName, bool enableLegacyStorageStructure, bool storageContainsUnknownFiles) |
15 | 376 : BaseStoragePlugin(enableLegacyStorageStructure), |
377 client_(client), | |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
378 bucketName_(bucketName), |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
379 storageContainsUnknownFiles_(storageContainsUnknownFiles) |
1 | 380 { |
381 } | |
382 | |
383 IStoragePlugin::IWriter* AwsS3StoragePlugin::GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) | |
384 { | |
385 return new Writer(client_, bucketName_, GetPath(uuid, type, encryptionEnabled)); | |
386 } | |
387 | |
388 IStoragePlugin::IReader* AwsS3StoragePlugin::GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) | |
389 { | |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
390 std::list<std::string> paths; |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
391 paths.push_back(GetPath(uuid, type, encryptionEnabled, false)); |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
392 if (storageContainsUnknownFiles_) |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
393 { |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
394 paths.push_back(GetPath(uuid, type, encryptionEnabled, true)); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
395 } |
64
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
396 |
c4f56973a279
Fix reading/deleting DCM header files that were saved with plugin v 1.2.0 and Orthanc 1.9.3 which had a .unk extension
Alain Mazy <am@osimis.io>
parents:
62
diff
changeset
|
397 return new Reader(client_, bucketName_, paths, uuid); |
1 | 398 } |
399 | |
400 void AwsS3StoragePlugin::DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) | |
401 { | |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
402 std::string firstExceptionMessage; |
1 | 403 |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
404 std::list<std::string> paths; |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
405 paths.push_back(GetPath(uuid, type, encryptionEnabled, false)); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
406 if (storageContainsUnknownFiles_) |
1 | 407 { |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
408 paths.push_back(GetPath(uuid, type, encryptionEnabled, true)); |
1 | 409 } |
410 | |
68
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
411 // DeleteObject succeeds even if the file does not exist -> we need to try to delete every path |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
412 for (auto& path: paths) |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
413 { |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
414 Aws::S3::Model::DeleteObjectRequest deleteObjectRequest; |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
415 deleteObjectRequest.SetBucket(bucketName_.c_str()); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
416 deleteObjectRequest.SetKey(path.c_str()); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
417 |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
418 auto result = client_.DeleteObject(deleteObjectRequest); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
419 |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
420 if (!result.IsSuccess() && firstExceptionMessage.empty()) |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
421 { |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
422 firstExceptionMessage = std::string("error while deleting file ") + path + ": response code = " + boost::lexical_cast<std::string>((int)result.GetError().GetResponseCode()) + " " + result.GetError().GetExceptionName().c_str() + " " + result.GetError().GetMessage().c_str(); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
423 } |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
424 } |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
425 |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
426 if (!firstExceptionMessage.empty()) |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
427 { |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
428 throw StoragePluginException(firstExceptionMessage); |
58a03fce4897
new option for AWS: EnableLegacyUnknownFiles
Alain Mazy <am@osimis.io>
parents:
64
diff
changeset
|
429 } |
1 | 430 } |