SALES: 1-800-867-1380

Create Storage Account

Updated: August 7, 2014

The Create Storage Account asynchronous operation creates a new storage account in Microsoft Azure.

The Create Storage Account request may be specified as follows. Replace <subscription-id> with your subscription ID.

 

Method Request URI

POST

https://management.core.windows.net/<subscription-id>/services/storageservices

You must make sure that the request that is made to the management service is secure. For additional details, see Authenticating Service Management Requests.

The following table describes the request headers.

 

Request Header Description

Content-Type

Required. Set this header to application/xml.

x-ms-version

Required. Specifies the version of the operation to use for this request. The value of this header must be set to 2011-06-01 or higher. For more information about versioning headers, see Service Management Versioning.

The format for the request body is as follows:

<?xml version="1.0" encoding="utf-8"?>
<CreateStorageServiceInput xmlns="http://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>

The following table describes the elements of the request body.

 

Element Name

Description

Service Name

Required. A name for the storage account that is unique within Azure. Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.

This name is the DNS prefix name and can be used to access blobs, queues, and tables in the storage account.

For example: http://ServiceName.blob.core.windows.net/mycontainer/

Label

Required. A label for the storage account specified as a base64-encoded string. The label may be up to 100 characters in length. The label can be used identify the storage account for your tracking purposes.

Description

Optional. A description for the storage account. The description may be up to 1024 characters in length.

Location

Required if AffinityGroup is not specified. The location where the storage account is created.

You can include either a Location or AffinityGroup element in the request body, but not both. To list available locations, use the List Locations operation.

AffinityGroup

Required if Location is not specified. The name of an existing affinity group in the specified subscription.

You can include either a Location or AffinityGroup element in the request body, but not both. To list available affinity groups, use the List Affinity Groups operation.

GeoReplicationEnabled

Optional. Specifies whether the storage account is created with the geo-replication enabled. If the element is not included in the request body, the default value is true. If set to true, the data in the storage account is replicated across more than one geographic location so as to enable resilience in the face of catastrophic service loss.

The GeoReplicationEnabled element is only available using version 2012-03-01 or higher and is replaced by the AccountType element with version 2014-06-01 or higher.

Name

Optional. Represents the name of an extended storage account property. Each extended property must have both a defined name and value. You can have a maximum of 50 extended property name/value pairs.

The maximum length of the Name element is 64 characters, only alphanumeric characters and underscores are valid in the Name, and the name must start with a letter. Attempting to use other characters, starting the Name with a non-letter character, or entering a name that is identical to that of another extended property owned by the same storage account, will result in a status code 400 (Bad Request) error.

The Name element is only available using version 2012-03-01 or higher.

Value

Optional. Represents the value of an extended storage account property. Each extended property must have both a defined name and value. You can have a maximum of 50 extended property name/value pairs, and each extended property value has a maximum length of 255 characters.

The Value element is only available using version 2012-03-01 or higher.

SecondaryReadEnabled

Optional. Indicates that secondary read is enabled for the storage account.

Possible values are:

  • true

  • false

The SecondaryReadEnabled element is only available using version 2013-11-01 or higher and is replaced by the AccountType element with version 2014-06-01 or higher.

AccountType

Specifies whether the account supports locally-redundant storage, geo-redundant storage, zone-redundant storage, or read access geo-redundant storage.

Possible values are:

  • Standard_LRS

  • Standard_ZRS

  • Standard_GRS

  • Standard_RAGRS

The AccountType element is only available using version 2014-06-01 or higher and it replaces the SecondaryReadEnabled and GeoReplicationEnabled elements.

The response includes an HTTP status code, a set of response headers, and a response body.

A successful operation returns status code 200 (OK). For information about status codes, see Service Management Status and Error Codes.

The response for this operation includes the following headers. The response may also include additional standard HTTP headers. All standard headers conform to the HTTP/1.1 protocol specification.

 

Response Header Description

x-ms-request-id

A value that uniquely identifies a request made against the management service. For an asynchronous operation, you can call Get Operation Status with the value of the header to determine whether the operation is complete, has failed, or is still in progress.

You can create storage accounts programmatically with the Create Storage Account operation, up to the limits available in your subscription. The initial limit on the number of storage accounts for a subscription 20. The operation returns immediately with a request ID, while the storage account creation is performed asynchronously by Azure, because provisioning a new storage account can take several minutes. To find out when the storage account creation operation has completed, you can poll the Get Operation Status operation with the request ID. This will return an XML body with an Operation element containing a Status element which will have a value of InProgress, Failed, or Succeeded, depending on the status of the storage account creation. If you poll until the status is Failed or Succeeded, the Operation element will contain a status code in the StatusCode element, and failed operations will contain additional error information in the Error element. See Get Operation Status for more details.

If the value of x-ms-version is 2012-03-01 or later, a storage account cannot be created in the Anywhere US, Anywhere Europe, or Anywhere Asia regions, which are now deprecated, unless you use a pre-existing affinity group that is set to one of these locations.

This example console program creates a new storage account, setting the description, label, location, and geo-replication state using the Create Storage Account operation, then polls the Get Operation Status operation with the request ID returned from the Create Storage Account operation until the call has succeeded, failed, or polling has timed out. Finally, it calls Get Storage Account Properties to display the properties for the new storage account. Set the value for the x-ms-version header in the Version string, your subscription identifier in SubscriptionId, your management certificate thumbprint in Thumbprint, and set ServiceName to a unique storage account name to run the sample.

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 = "http://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 { getset; }
 
        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, nullout 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, nullout 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 { getset; }
 
            // The http status code of the requestId operation, if any.
            public HttpStatusCode StatusCode { getset; }
 
            // The approximate running time for PollGetOperationStatus.
            public TimeSpan RunningTime { getset; }
 
            // The error code for the failed operation.
            public string Code { getset; }
 
            // The message for the failed operation.
            public string Message { getset; }
        }
 
        /// <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);
        }
    }
}

This example program produces console output something like the following when run:

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="http://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:

Was this page helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft