forked from Linq2Azure/API
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Subscription.cs
155 lines (128 loc) · 6.48 KB
/
Subscription.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
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Xml.Linq;
using Linq2Azure.CloudServices;
using Linq2Azure.SqlDatabases;
using Linq2Azure.TrafficManagement;
using System.Diagnostics;
namespace Linq2Azure
{
/// <summary>
/// This is the "root" type in the LinqToAzure API, from which all queries and operations are made.
/// </summary>
public class Subscription : IDisposable
{
public static readonly string CoreUri = "https://management.core.windows.net/";
public static readonly string DatabaseUri = "https://management.database.windows.net:8443/";
public IEnumerable<TraceListener> LogDestinations { get; set; }
public Guid ID { get; private set; }
public string Name { get; private set; }
public X509Certificate2 ManagementCertificate { get; private set; }
public LatentSequence<CloudService> CloudServices { get; private set; }
public LatentSequence<DatabaseServer> DatabaseServers { get; private set; }
public LatentSequence<TrafficManagerProfile> TrafficManagerProfiles { get; private set; }
HttpClient _coreHttpClient, _databaseHttpClient;
public Subscription(Guid id, string name, X509Certificate2 managementCertificate)
{
Contract.Requires(!string.IsNullOrWhiteSpace(name));
Contract.Requires(managementCertificate != null);
ID = id;
Name = name;
ManagementCertificate = managementCertificate;
Init();
}
public Subscription(string publishSettingsPath)
{
Contract.Requires(!string.IsNullOrWhiteSpace(publishSettingsPath));
var pp = XDocument.Load(publishSettingsPath).Root.Element("PublishProfile");
var sub = pp.Element("Subscription");
ID = Guid.Parse((string)sub.Attribute("Id"));
Name = (string)sub.Attribute("Name");
string managementCertificateAttempt = (string)pp.Attribute("ManagementCertificate");
if (managementCertificateAttempt == null)
{
managementCertificateAttempt = (string)sub.Attribute("ManagementCertificate");
}
if (managementCertificateAttempt == null)
{
throw new System.Configuration.ConfigurationException("Cannot find ManagementCertificate attribute neither in PublishProfile node, nor in Subscription in file " + publishSettingsPath);
}
ManagementCertificate = new X509Certificate2(Convert.FromBase64String(managementCertificateAttempt));
Init();
}
void Init()
{
_coreHttpClient = AzureRestClient.CreateHttpClient(this, "2012-03-01", () => LogDestinations);
_databaseHttpClient = AzureRestClient.CreateHttpClient(this, "1.0", () => LogDestinations);
CloudServices = new LatentSequence<CloudService>(GetCloudServicesAsync);
DatabaseServers = new LatentSequence<DatabaseServer>(GetDatabaseServersAsync);
TrafficManagerProfiles = new LatentSequence<TrafficManagerProfile>(GetTrafficManagerProfilesAsync);
}
public Task CreateCloudServiceAsync(CloudService service) { return service.CreateAsync(this); }
public Task CreateDatabaseServerAsync(DatabaseServer server, string adminPassword) { return server.CreateAsync(this, adminPassword); }
public Task CreateTrafficManagerProfileAsync(TrafficManagerProfile profile) { return profile.CreateAsync(this); }
async Task<CloudService[]> GetCloudServicesAsync()
{
var xe = await GetCoreRestClient("services/hostedServices").GetXmlAsync();
return xe.Elements(XmlNamespaces.WindowsAzure + "HostedService").Select(x => new CloudService(x, this)).ToArray();
}
async Task<DatabaseServer[]> GetDatabaseServersAsync()
{
var xe = await GetDatabaseRestClient("servers").GetXmlAsync();
return xe.Elements(XmlNamespaces.SqlAzure + "Server").Select(x => new DatabaseServer(x, this)).ToArray();
}
async Task<TrafficManagerProfile[]> GetTrafficManagerProfilesAsync()
{
var xe = await GetCoreRestClient("services/WATM/profiles").GetXmlAsync();
return xe.Elements(XmlNamespaces.WindowsAzure + "Profile").Select(x => new TrafficManagerProfile(x, this)).ToArray();
}
internal AzureRestClient GetCoreRestClient(string servicePath)
{
return new AzureRestClient(this, _coreHttpClient, CoreUri, servicePath);
}
internal AzureRestClient GetDatabaseRestClient(string servicePath)
{
return new AzureRestClient(this, _databaseHttpClient, DatabaseUri, servicePath);
}
/// <summary>
/// Implements http://msdn.microsoft.com/en-us/library/windowsazure/ee460783.aspx
/// </summary>
/// <param name="operationResponse">The response message from the operation for which we're awaiting completion.</param>
internal async Task WaitForOperationCompletionAsync(HttpResponseMessage operationResponse)
{
var requestId = operationResponse.Headers.Single(h => h.Key == "x-ms-request-id").Value.Single();
var delay = 1000;
while (true)
{
var result = await GetOperationResultAsync(requestId);
if (result == "Succeeded")
return;
if (result != "InProgress")
throw new InvalidOperationException("Unknown error: result=" + result);
await Task.Delay(delay);
if (delay < 5000) delay += 1000;
}
}
async Task<string> GetOperationResultAsync(string requestId)
{
var client = GetCoreRestClient("operations/" + requestId);
return ParseResult(await client.GetXmlAsync());
}
internal static string ParseResult(XElement result)
{
var error = result.Element(XmlNamespaces.WindowsAzure + "Error");
if (error != null) AzureRestClient.Throw(null, error);
return (string)result.Element(XmlNamespaces.WindowsAzure + "Status");
}
public void Dispose()
{
if (_coreHttpClient != null) _coreHttpClient.Dispose();
if (_databaseHttpClient != null) _databaseHttpClient.Dispose();
}
}
}