建立儲存體帳戶
Create Storage Account
非同步作業會在 Microsoft Azure 中建立新的儲存體帳戶。
要求
Create Storage Account
要求可能會以下面方式指定。 取代 <subscription-id>
與您的訂用帳戶 id。
方法 | 要求 URI |
---|---|
POST | https://management.core.windows.net/<subscription-id>/services/storageservices |
您必須確定對管理服務發出的要求是安全的。 如需詳細資訊,請參閱 驗證服務管理要求。
URI 參數
無。
要求標頭
下表描述要求標頭。
要求標頭 | 說明 |
---|---|
Content-Type |
必要項。 此標頭設定為 application/xml 。 |
x-ms-version |
必要項。 指定用於這個要求的作業版本。 此標頭的值必須設定為 2011年-06-01 或更高版本。 如需有關版本設定標頭的詳細資訊,請參閱 服務管理版本控制。 |
要求本文
要求主體的格式如下:
<?xml version="1.0" encoding="utf-8"?> <CreateStorageServiceInput xmlns="https://schemas.microsoft.com/windowsazure"> <ServiceName>name-of-storage-account</ServiceName> <Description>description-of-storage-account</Description> <Label>base64-encoded-label</Label> <AffinityGroup>name-of-affinity-group</AffinityGroup> <Location>location-of-storage-account</Location> <GeoReplicationEnabled>geo-replication-indicator</GeoReplicationEnabled> <ExtendedProperties> <ExtendedProperty> <Name>property-name</Name> <Value>property-value</Value> </ExtendedProperty> </ExtendedProperties> <SecondaryReadEnabled>secondary-read-indicator</SecondaryReadEnabled> <AccountType>type-of-storage-account</AccountType> </CreateStorageServiceInput>
下表說明要求主體的元素。
元素名稱 | 說明 |
Service Name | 必要項。 儲存體帳戶在 Azure 中獨一無二的名稱。 儲存體帳戶名稱的長度必須介於 3 到 24 個字元之間,而且只能使用數字和小寫字母。 這個名稱是 DNS 首碼名稱,可用來存取儲存體帳戶中的 Blob、佇列和資料表。 例如:http://ServiceName.blob.core.windows.net/mycontainer/ |
Label | 必要項。 指定成 Base64 編碼字串格式的儲存體帳戶標籤。 標籤的長度最多可以有 100 個字元。 在您進行追蹤時,此標籤可用來識別儲存體帳戶。 |
說明 | 選擇項。 儲存體帳戶的描述。 描述的長度最多可以有 1024 個字元。 |
位置 | 若 AffinityGroup 未指定。 儲存體帳戶建立的位置。 您可以加入其中一個 位置 或 AffinityGroup 要求主體中,但不可兩者中的項目。 若要列出可用的位置,請使用 列出位置 作業。 |
AffinityGroup | 若 位置 未指定。 指定的訂閱中現有同質群組的名稱。 您可以加入其中一個 位置 或 AffinityGroup 要求主體中,但不可兩者中的項目。 若要列出可用的同質群組,請使用 列出同質群組 作業。 |
GeoReplicationEnabled | 選擇項。 指定建立的儲存體帳戶是否啟用地理複寫。 如果在要求主體中未包含此元素,預設值是 true 。 如果設定為 true , 、 儲存體帳戶中的資料會複寫跨多個地理位置以便啟用面臨重大服務中斷的恢復功能。GeoReplicationEnabled 項目才提供使用 2012年-03-01 版或更高版本和取代由 AccountType 元素與 2014年-06-01 版或更高版本。 |
名稱 | 選擇項。 代表擴充儲存體帳戶屬性的名稱。 每個擴充屬性都必須具有已定義的名稱和值。 您最多可以擁有 50 個擴充屬性名稱/值組。 Name 元素的長度上限為 64 個字元、只有英數字元和底線可用於 Name,而且名稱必須以字母當做開頭。 如果您嘗試使用其他字元、以非字母字元當做 Name 的開頭,或者輸入的名稱與相同儲存體帳戶所擁有之其他擴充屬性的名稱完全相同,就會產生狀態碼 400 (不正確的要求) 錯誤。 名稱 項目只是使用 2012年-03-01 版或更高版本。 |
值 | 選擇項。 代表擴充儲存體帳戶屬性的值。 每個擴充屬性都必須具有已定義的名稱和值。 您最多可以擁有 50 個擴充屬性名稱/值組,而且每個擴充屬性值的長度上限為 255 個字元。 值 項目只是使用 2012年-03-01 版或更高版本。 |
SecondaryReadEnabled | 選擇項。 指出儲存體帳戶已啟用次要讀取。 可能的值為: - true - false SecondaryReadEnabled 項目只有使用 2013年-11-01 版或更高且取代由 AccountType 元素與 2014年-06-01 版或更高版本。 |
AccountType | 指定帳戶是否支援本機備援儲存體、地理備援儲存體、區域備援儲存體或讀取權限地理備援儲存體。 可能的值為: - Standard_LRS - Standard_ZRS - Standard_GRS - Standard_RAGRS - Premium_LRS AccountType 項目只是使用 2014年-06-01 版或更高版本,並取代 SecondaryReadEnabled 和 GeoReplicationEnabled 元素。Premium_LRS 項目只是使用 2014年-10-01 版或更高版本。 Note: A Standard_ZRS 帳戶之後無法變更到另一個帳戶類型,以及其他帳戶類型不能變更為 Standard_ZRS 。 也是 Premium_LRS 帳戶。 |
回應
回應包括 HTTP 狀態碼、一組回應標頭和回應主體。
狀態碼
成功的作業會傳回狀態碼 200 (OK)。 如需狀態碼的相關資訊,請參閱 服務管理狀態和錯誤碼。
回應標頭
這項作業的回應包括下列標頭。 回應也可能包括其他標準 HTTP 標頭。 所有標準標頭符合 HTTP/1.1 通訊協定規格。
回應標頭 | 說明 |
---|---|
x-ms-request-id |
唯一識別對管理服務發出之要求的值。 您可以呼叫非同步作業, 取得作業狀態 以判斷作業已完成之標頭的值、 失敗,還是仍在進行中。 |
回應主體
無。
備註
您可以建立以程式設計方式使用的儲存體帳戶 建立儲存體帳戶 作業到訂閱中可用的上限。 如需限制與儲存體帳戶相關資訊,請參閱 Azure 訂用帳戶和服務限制、 配額及條件約束。
此作業會立即傳回並附有要求 ID,而儲存體帳戶的建立則是由 Azure 以非同步方式執行,因為佈建新的儲存體帳戶可能需時數分鐘。 若要查明儲存體帳戶建立作業完成時,您可以輪詢 取得作業狀態 作業要求識別碼。 這會傳回具有的 XML 主體 作業 項目包含 狀態 項目會具有值為 InProgress
, ,Failed
, ,或 Succeeded
, 、 儲存體帳戶建立狀態而定。 如果您輪詢直到狀態 Failed
或 Succeeded
, 、 作業 元素會包含在狀態碼 StatusCode 項目,而失敗的作業將會包含在其他錯誤資訊 錯誤 項目。
中的資訊 Azure 儲存體延展性和效能目標 也可以讓您在規劃您的儲存體需求。
範例
這個範例主控台程式會建立新的儲存體帳戶、 設定描述、 標籤、 位置和地理複寫狀態使用 建立儲存體帳戶 作業,然後使用 取得作業狀態 識別碼傳回要求的作業 建立儲存體帳戶 作業,直到呼叫成功、 失敗或輪詢已逾時為止。 最後,它會呼叫 取得儲存體帳戶屬性 以顯示新的儲存體帳戶的屬性。 設定的值 x-ms-version
標頭中的 Version
字串,您的訂閱識別碼在 SubscriptionId
, ,在您的管理憑證指紋 Thumbprint
, ,並且將 ServiceName 設定到要執行範例的唯一的儲存體帳戶名稱。
namespace Microsoft.WindowsAzure.ServiceManagementRESTAPI.Samples { using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Xml; using System.Xml.Linq; public class Program { // Set these constants with your values to run the sample. private const string Version = "2011-12-01"; private const string Thumbprint = "management-certificate-thumbprint"; private const string SubscriptionId = "subscription-identifier"; private const string ServiceName = "unique-storage-account-name"; // This is the common namespace for all Service Management REST API XML data. private static XNamespace wa = "https://schemas.microsoft.com/windowsazure"; /// <summary> /// The operation status values from PollGetOperationStatus. /// </summary> private enum OperationStatus { InProgress, Failed, Succeeded, TimedOut } /// <summary> /// Gets or sets the certificate that matches the Thumbprint value. /// </summary> private static X509Certificate2 Certificate { get; set; } static void Main(string[] args) { try { Certificate = GetStoreCertificate(Thumbprint); // Create the new storage account with the following values: string description = "Description for my example storage account"; string label = "My example storage account label"; string location = "North Central US"; bool? enableGeoReplication = true; string requestId = CreateStorageAccount( ServiceName, description, label, null, location, enableGeoReplication); Console.WriteLine( "Called Create Storage Account operation: requestId {0}", requestId); // Loop on Get Operation Status for result of storage creation OperationResult result = PollGetOperationStatus( requestId, pollIntervalSeconds: 20, timeoutSeconds: 180); switch (result.Status) { case OperationStatus.TimedOut: Console.WriteLine( "Poll of Get Operation Status timed out: " + "Operation {0} is still in progress after {1} seconds.", requestId, (int)result.RunningTime.TotalSeconds); break; case OperationStatus.Failed: Console.WriteLine( "Failed: Operation {0} failed after " + "{1} seconds with status {2} ({3}) - {4}: {5}", requestId, (int)result.RunningTime.TotalSeconds, (int)result.StatusCode, result.StatusCode, result.Code, result.Message); break; case OperationStatus.Succeeded: Console.WriteLine( "Succeeded: Operation {0} completed " + "after {1} seconds with status {2} ({3})", requestId, (int)result.RunningTime.TotalSeconds, (int)result.StatusCode, result.StatusCode); break; } // Display the property values for the new storage account. // Convert the Label property to a readable value for display. XElement updatedProperties = GetStorageAccountProperties(ServiceName); XElement labelElement = updatedProperties.Descendants(wa + "Label").First(); labelElement.Value = labelElement.Value.FromBase64(); Console.WriteLine( "New Storage Account Properties for {0}:{1}{2}", ServiceName, Environment.NewLine, updatedProperties.ToString(SaveOptions.OmitDuplicateNamespaces)); } catch (Exception ex) { Console.WriteLine("Exception caught in Main:"); Console.WriteLine(ex.Message); } Console.Write("Press any key to continue:"); Console.ReadKey(); } /// <summary> /// Calls the Get Storage Account Properties operation in the Service /// Management REST API for the specified subscription and storage account /// name and returns the StorageService XML element from the response. /// </summary> /// <param name="serviceName">The name of the storage account.</param> /// <returns>The StorageService XML element from the response.</returns> private static XElement GetStorageAccountProperties( string serviceName) { string uriFormat = "https://management.core.windows.net/{0}" + "/services/storageservices/{1}"; Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, serviceName)); XDocument responseBody; InvokeRequest(uri, "GET", HttpStatusCode.OK, null, out responseBody); return responseBody.Element(wa + "StorageService"); } /// <summary> /// Calls the Create Storage Account operation in the Service Management /// REST API for the specified subscription, storage account name, /// description, label, location or affinity group, and geo-replication /// enabled setting. /// </summary> /// <param name="serviceName">The name of the storage account to update.</param> /// <param name="description">The new description for the storage account.</param> /// <param name="label">The new label for the storage account.</param> /// <param name="affinityGroup">The affinity group name, or null to use a location.</param> /// <param name="location">The location name, or null to use an affinity group.</param> /// <param name="geoReplicationEnabled">The new geo-replication setting, if applicable. /// This optional parameter defaults to null.</param> /// <returns>The requestId for the operation.</returns> private static string CreateStorageAccount( string serviceName, string description, string label, string affinityGroup, string location, bool? geoReplicationEnabled = null) { string uriFormat = "https://management.core.windows.net/{0}" + "/services/storageservices"; Uri uri = new Uri(String.Format(uriFormat, SubscriptionId)); // Location and Affinity Group are mutually exclusive. // Use the location if it isn't null or empty. XElement locationOrAffinityGroup = String.IsNullOrEmpty(location) ? new XElement(wa + "AffinityGroup", affinityGroup) : new XElement(wa + "Location", location); // Create the request XML document XDocument requestBody = new XDocument( new XDeclaration("1.0", "UTF-8", "no"), new XElement( wa + "CreateStorageServiceInput", new XElement(wa + "ServiceName", serviceName), new XElement(wa + "Description", description), new XElement(wa + "Label", label.ToBase64()), locationOrAffinityGroup)); // Add the GeoReplicationEnabled element if the version supports it. if ((geoReplicationEnabled != null) && (String.CompareOrdinal(Version, "2011-12-01") >= 0)) { requestBody.Element( wa + "CreateStorageServiceInput").Add( new XElement( wa + "GeoReplicationEnabled", geoReplicationEnabled.ToString().ToLowerInvariant())); } XDocument responseBody; return InvokeRequest( uri, "POST", HttpStatusCode.Accepted, requestBody, out responseBody); } /// <summary> /// Calls the Get Operation Status operation in the Service /// Management REST API for the specified subscription and requestId /// and returns the Operation XML element from the response. /// </summary> /// <param name="requestId">The requestId of the operation to track.</param> /// <returns>The Operation XML element from the response.</returns> private static XElement GetOperationStatus( string requestId) { string uriFormat = "https://management.core.windows.net/{0}" + "/operations/{1}"; Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, requestId)); XDocument responseBody; InvokeRequest(uri, "GET", HttpStatusCode.OK, null, out responseBody); return responseBody.Element(wa + "Operation"); } /// <summary> /// The results from PollGetOperationStatus are passed in this struct. /// </summary> private struct OperationResult { // The status: InProgress, Failed, Succeeded, or TimedOut. public OperationStatus Status { get; set; } // The http status code of the requestId operation, if any. public HttpStatusCode StatusCode { get; set; } // The approximate running time for PollGetOperationStatus. public TimeSpan RunningTime { get; set; } // The error code for the failed operation. public string Code { get; set; } // The message for the failed operation. public string Message { get; set; } } /// <summary> /// Polls Get Operation Status for the operation specified by requestId /// every pollIntervalSeconds until timeoutSeconds have passed or the /// operation has returned a Failed or Succeeded status. /// </summary> /// <param name="requestId">The requestId of the operation to get status for.</param> /// <param name="pollIntervalSeconds">The interval between calls to Get Operation Status.</param> /// <param name="timeoutSeconds">The maximum number of seconds to poll.</param> /// <returns>An OperationResult structure with status or error information.</returns> private static OperationResult PollGetOperationStatus( string requestId, int pollIntervalSeconds, int timeoutSeconds) { OperationResult result = new OperationResult(); DateTime beginPollTime = DateTime.UtcNow; TimeSpan pollInterval = new TimeSpan(0, 0, pollIntervalSeconds); DateTime endPollTime = beginPollTime + new TimeSpan(0, 0, timeoutSeconds); bool done = false; while (!done) { XElement operation = GetOperationStatus(requestId); result.RunningTime = DateTime.UtcNow - beginPollTime; try { // Turn the Status string into an OperationStatus value result.Status = (OperationStatus)Enum.Parse( typeof(OperationStatus), operation.Element(wa + "Status").Value); } catch (Exception) { throw new ApplicationException(string.Format( "Get Operation Status {0} returned unexpected status: {1}{2}", requestId, Environment.NewLine, operation.ToString(SaveOptions.OmitDuplicateNamespaces))); } switch (result.Status) { case OperationStatus.InProgress: Console.WriteLine( "In progress for {0} seconds", (int)result.RunningTime.TotalSeconds); Thread.Sleep((int)pollInterval.TotalMilliseconds); break; case OperationStatus.Failed: result.StatusCode = (HttpStatusCode)Convert.ToInt32( operation.Element(wa + "HttpStatusCode").Value); XElement error = operation.Element(wa + "Error"); result.Code = error.Element(wa + "Code").Value; result.Message = error.Element(wa + "Message").Value; done = true; break; case OperationStatus.Succeeded: result.StatusCode = (HttpStatusCode)Convert.ToInt32( operation.Element(wa + "HttpStatusCode").Value); done = true; break; } if (!done && DateTime.UtcNow > endPollTime) { result.Status = OperationStatus.TimedOut; done = true; } } return result; } /// <summary> /// Gets the certificate matching the thumbprint from the local store. /// Throws an ArgumentException if a matching certificate is not found. /// </summary> /// <param name="thumbprint">The thumbprint of the certificate to find.</param> /// <returns>The certificate with the specified thumbprint.</returns> private static X509Certificate2 GetStoreCertificate(string thumbprint) { List<StoreLocation> locations = new List<StoreLocation> { StoreLocation.CurrentUser, StoreLocation.LocalMachine }; foreach (var location in locations) { X509Store store = new X509Store("My", location); try { store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection certificates = store.Certificates.Find( X509FindType.FindByThumbprint, thumbprint, false); if (certificates.Count == 1) { return certificates[0]; } } finally { store.Close(); } } throw new ArgumentException(string.Format( "A Certificate with thumbprint '{0}' could not be located.", thumbprint)); } /// <summary> /// A helper function to invoke a Service Management REST API operation. /// Throws an ApplicationException on unexpected status code results. /// </summary> /// <param name="uri">The URI of the operation to invoke using a web request.</param> /// <param name="method">The method of the web request, GET, PUT, POST, or DELETE.</param> /// <param name="expectedCode">The expected status code.</param> /// <param name="requestBody">The XML body to send with the web request. Use null to send no request body.</param> /// <param name="responseBody">The XML body returned by the request, if any.</param> /// <returns>The requestId returned by the operation.</returns> private static string InvokeRequest( Uri uri, string method, HttpStatusCode expectedCode, XDocument requestBody, out XDocument responseBody) { responseBody = null; string requestId = String.Empty; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri); request.Method = method; request.Headers.Add("x-ms-Version", Version); request.ClientCertificates.Add(Certificate); request.ContentType = "application/xml"; if (requestBody != null) { using (Stream requestStream = request.GetRequestStream()) { using (StreamWriter streamWriter = new StreamWriter( requestStream, System.Text.UTF8Encoding.UTF8)) { requestBody.Save(streamWriter, SaveOptions.DisableFormatting); } } } HttpWebResponse response; HttpStatusCode statusCode = HttpStatusCode.Unused; try { response = (HttpWebResponse)request.GetResponse(); } catch (WebException ex) { // GetResponse throws a WebException for 4XX and 5XX status codes response = (HttpWebResponse)ex.Response; } try { statusCode = response.StatusCode; if (response.ContentLength > 0) { using (XmlReader reader = XmlReader.Create(response.GetResponseStream())) { responseBody = XDocument.Load(reader); } } if (response.Headers != null) { requestId = response.Headers["x-ms-request-id"]; } } finally { response.Close(); } if (!statusCode.Equals(expectedCode)) { throw new ApplicationException(string.Format( "Call to {0} returned an error:{1}Status Code: {2} ({3}):{1}{4}", uri.ToString(), Environment.NewLine, (int)statusCode, statusCode, responseBody.ToString(SaveOptions.OmitDuplicateNamespaces))); } return requestId; } } /// <summary> /// Helpful extension methods for converting strings to and from Base-64. /// </summary> public static class StringExtensions { /// <summary> /// Converts a UTF-8 string to a Base-64 version of the string. /// </summary> /// <param name="s">The string to convert to Base-64.</param> /// <returns>The Base-64 converted string.</returns> public static string ToBase64(this string s) { byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s); return Convert.ToBase64String(bytes); } /// <summary> /// Converts a Base-64 encoded string to UTF-8. /// </summary> /// <param name="s">The string to convert from Base-64.</param> /// <returns>The converted UTF-8 string.</returns> public static string FromBase64(this string s) { byte[] bytes = Convert.FromBase64String(s); return System.Text.Encoding.UTF8.GetString(bytes); } } }
此範例程式在執行時會產生類似下面的主控台輸出:
Called Create Storage Account operation: requestId 8ba8bd9cdc50472892a0b3cd3659b297 In progress for 0 seconds In progress for 20 seconds In progress for 41 seconds In progress for 61 seconds In progress for 82 seconds In progress for 103 seconds Succeeded: Operation 8ba8bd9cdc50472892a0b3cd3659b297 completed after 123 seconds with status 200 (OK) New Storage Account Properties for myexamplestorage1: <StorageService xmlns="https://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Url>https://management.core.windows.net/01234567-89ab-cdef-0123-456789abcdef/services/storageservices/myexamplestorage1</Url> <ServiceName>myexamplestorage1</ServiceName> <StorageServiceProperties> <Description>Description for my example storage account</Description> <Location>North Central US</Location> <Label>My example storage account label</Label> <Status>Created</Status> <Endpoints> <Endpoint>http://myexamplestorage1.blob.core.windows.net/</Endpoint> <Endpoint>http://myexamplestorage1.queue.core.windows.net/</Endpoint> <Endpoint>http://myexamplestorage1.table.core.windows.net/</Endpoint> </Endpoints> <GeoReplicationEnabled>true</GeoReplicationEnabled> <GeoPrimaryRegion>usnorth</GeoPrimaryRegion> <StatusOfPrimary>Available</StatusOfPrimary> <GeoSecondaryRegion>ussouth</GeoSecondaryRegion> <StatusOfSecondary>Available</StatusOfSecondary> </StorageServiceProperties> </StorageService> Press any key to continue: