forked from aws/aws-sdk-net
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ImageUtilities.bcl.cs
232 lines (210 loc) · 8.95 KB
/
ImageUtilities.bcl.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*******************************************************************************
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
* this file except in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and
* limitations under the License.
* *****************************************************************************
* __ _ _ ___
* ( )( \/\/ )/ __)
* /__\ \ / \__ \
* (_)(_) \/\/ (___/
*
* AWS SDK for .NET
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using Amazon.EC2.Model;
using Amazon.Runtime.Internal.Util;
using ThirdParty.Json.LitJson;
using Amazon.Runtime;
#pragma warning disable 1591
namespace Amazon.EC2.Util
{
/// <summary>
/// This class has utility methods for finding common Amazon machine images.
/// </summary>
public static partial class ImageUtilities
{
/// <summary>
/// Returns the ImageDescriptor instance for a known key.
/// </summary>
/// <param name="key">The version-independent key identifying the descriptor</param>
/// <returns>Matching descriptor containing the name filter to search on</returns>
public static ImageDescriptor DescriptorFromKey(string key)
{
return DescriptorFromKey(key, null);
}
/// <summary>
/// Returns the ImageDescriptor instance for a known key.
/// </summary>
/// <param name="key">
/// The version-independent key identifying the descriptor
/// </param>
/// <param name="ec2Client">
/// <para>
/// Optional. Configured client object from which proxy settings, if needed, can be
/// determined. If no client is supplied the application configuration will be
/// inspected for proxy details.
/// </para>
/// <para>
/// If a proxy is configured (either on the client or in the configuration file) it
/// will be used when downloading the metadata file containing the key to filter
/// mappings.
/// </para>
/// </param>
/// <returns>Matching descriptor containing the name filter to search on</returns>
public static ImageDescriptor DescriptorFromKey(string key, IAmazonEC2 ec2Client)
{
LoadDefinitionsFromWeb(ConfigFromClient(ec2Client));
return FindDescriptorWithKey(key);
}
private static void LoadDefinitionsFromWeb(AmazonEC2Config ec2Config)
{
lock (LOCK_OBJECT)
{
if (ImageDefinitionsLoaded)
return;
}
const string httpPrefix = "http://";
const string httpsPrefix = "https://";
IWebProxy webProxy = null;
IWebProxy httpProxy = null;
IWebProxy httpsProxy = null;
if (ec2Config != null) {
webProxy = ec2Config.GetWebProxy();
httpProxy = ec2Config.GetHttpProxy();
httpsProxy = ec2Config.GetHttpsProxy();
}
int retries = 0;
while (retries < MAX_DOWNLOAD_RETRIES)
{
try
{
HttpWebResponse response = null;
foreach (var location in DownloadLocations)
{
var useProxy = webProxy;
if (useProxy == null)
{
if (location.StartsWith(httpPrefix))
{
useProxy = httpProxy;
}
else if (location.StartsWith(httpsPrefix))
{
useProxy = httpsProxy;
}
}
try
{
response = DownloadControlFile(location, useProxy);
if (response != null)
break;
}
catch (Exception e)
{
Logger.InfoFormat("Failed to download stockamis.json from {0}, exception {1}", location, e);
}
}
if (response == null)
throw new AmazonClientException("Failed to download ImageUtilities metadata file stockamis.json from known locations.");
using (response)
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
lock (LOCK_OBJECT)
{
ParseAMIDefinitions(reader);
ImageDefinitionsLoaded = true;
return;
}
}
}
}
catch (AmazonClientException e)
{
retries++;
if (retries == MAX_DOWNLOAD_RETRIES)
{
Logger.Error(e, "Error downloading AMI definition file, ImageDescriptors were not initialized.");
break;
}
}
int delay = (int)(Math.Pow(4, retries) * 100);
delay = Math.Min(delay, 30 * 1000);
Thread.Sleep(delay);
}
}
private static HttpWebResponse DownloadControlFile(string location, IWebProxy proxy)
{
var request = WebRequest.Create(location) as HttpWebRequest;
if (proxy != null)
request.Proxy = proxy;
return request.GetResponse() as HttpWebResponse;
}
/// <summary>
/// Find the Amazon machine image identified by the version-independent key name.
/// </summary>
/// <param name="ec2Client">The EC2 client used to search for the image.</param>
/// <param name="imageKey">The keyname used to identify the image.</param>
/// <returns>The Amazon machine image.</returns>
public static Image FindImage(IAmazonEC2 ec2Client, string imageKey)
{
ImageDescriptor descriptor = DescriptorFromKey(imageKey);
if (descriptor != null)
return FindImage(ec2Client, descriptor);
else
throw new ArgumentException("Image key '{0}' is not recognized.", imageKey);
}
/// <summary>
/// Find the Amazon machine image identified by the ImageDescriptor.
/// </summary>
/// <param name="ec2Client">The EC2 client used to search for the image.</param>
/// <param name="descriptor">The descriptor used to identify the image.</param>
/// <returns>The Amazon machine image.</returns>
public static Image FindImage(IAmazonEC2 ec2Client, ImageDescriptor descriptor)
{
AmazonEC2Config config = CreateConfigFromClient(ec2Client, descriptor);
LoadDefinitionsFromWeb(config);
int retryCount = 1;
Image image = null;
do
{
var result = ec2Client.DescribeImages(CreateDescribeImagesRequest(descriptor));
if (result.Images.Any())
image = result.Images.OrderByDescending(x => x.Name).First();
else
{
// backing control file may be outdated, reload and try once more
if (retryCount == 1)
{
Logger.InfoFormat("FindImage - DescribeImages call for image descriptor '{0}' (name prefix '{1}') yielded no results, assuming outdated control file and reloading",
descriptor.DefinitionKey,
descriptor.NamePrefix);
lock (LOCK_OBJECT)
{
ImageDefinitionsLoaded = false;
}
LoadDefinitionsFromWeb(config);
}
retryCount++;
}
} while (image == null && retryCount <= 2);
if (image == null)
Logger.InfoFormat("FindImage - failed to find valid AMI image for descriptor '{0}' (name prefix '{1}')",
descriptor.DefinitionKey,
descriptor.NamePrefix);
return image;
}
}
}