Export (0) Print
Expand All

Update Storage Account

Updated: August 7, 2014

The Update Storage Account asynchronous operation updates the label, the description, and enables or disables the geo-replication status for the specified storage account.

The Update Storage Account request may be specified as follows. Replace <subscription-id> with your subscription ID, and <service-name> with the name of your storage account.

 

Method Request URI

PUT

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

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 of the request body is as follows:


<?xml version="1.0" encoding="utf-8"?>
<UpdateStorageServiceInput xmlns="http://schemas.microsoft.com/windowsazure">
  <Description>description-of-storage-account</Description>
  <Label>base64-encoded-label</Label>
  <GeoReplicationEnabled>geo-replication-indicator</GeoReplicationEnabled>
  <ExtendedProperties>
    <ExtendedProperty>
      <Name>property-name</Name>
      <Value>property-value</Value>
    </ExtendedProperty>
  </ExtendedProperties>
  <CustomDomains>
    <CustomDomain>
      <Name>name-of-custom-domain</Name>
      <UseSubDomainName>cname-validation-indicator</UseSubDomainName>
    </CustomDomain>
  </CustomDomains>
  <SecondaryReadEnabled>secondary-read-indicator</SecondaryReadEnabled>
  <AccountType>type-of-storage-account</AccountType>
</UpdateStorageServiceInput>

The following table describes the elements of the request body.

 

Element Name

Description

Label

Optional. Specifies a base-64 encoded name for the storage account. The label may be up to 100 characters in length. The label can be used identify the storage account for your tracking purposes. You must specify a value for either Label or Description, or for both.

Description

Optional. A description for the storage account. The description may be up to 1024 characters in length. You must specify a value for either Label or Description, or for both.

GeoReplicationEnabled

Optional. Enables or disables geo-replication on the specified the storage. 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. If set to false, geo-replication is disabled. If the element is not included in the request body, the current value is left unchanged.

ImportantImportant
If you have enabled geo-replication you can elect to disable it by setting this element to false. When disabled, your data is no longer replicated to a secondary data center and any data in the secondary location will be removed.

Enabling geo-replication once it has been disabled will result in the storage account being billed for replicating the current copy of data to the secondary data center. After the existing copy of the data is replicated to the secondary data center, updates are geo-replicated at no additional charge.

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.

ExtendedProperties

Specifies the name and value of an extended property that was added to the storage account.

CustomDomains

Specifies the custom domains that are associated with the storage account.

The CustomDomains element is only available using version 2013-06-01 or higher.

SecondaryReadEnabled

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, or read access geo-redundant storage. Zone-redundant storage is not an option when you update a storage account.

Possible values are:

  • Standard_LRS

  • 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.

Specifies the name and value of an extended property that was added to the storage account.

 

Element name Description

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.

Specifies the custom domains that are associated with the storage account.

 

Element name Description

CustomDomain

Specifies information about a custom domain that is associated with the storage account.

Name

Specifies the name of the custom domain.

UseSubDomainName

Indicates whether indirect CName validation is enabled.

Possible values are:

  • true

  • false

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.

Use the Update Storage Account operation to change the description, label, or geo-replication setting value for a storage account. You can use the Get Storage Account Properties operation to review these values.

The following example calls the Get Storage Account Properties operation to list the initial property values for the storage account, updates the Label and Description properties with a call to the Update Storage Account operation, then displays the updated results with another call to Get Storage Account Properties. Change the value of the Version string to the desired version, the Thumbprint value to the thumbprint for your management certificate, the SubscriptionId to your subscription identifier, and the ServiceName value to the name of your storage account 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.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 = "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>
        /// 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);

                // Get the initial property values for the storage account.
                // Convert the Label property to a readable value for display.
                XElement initialProperties =
                    GetStorageAccountProperties(ServiceName);
                XElement labelElement = initialProperties.Descendants(wa + "Label").First();
                labelElement.Value = labelElement.Value.FromBase64();
                Console.WriteLine(
                    "Storage Account Properties for {0}:{1}{2}",
                    ServiceName,
                    Environment.NewLine,
                    initialProperties.ToString(SaveOptions.OmitDuplicateNamespaces));

                // Update the label and description of the storage account.
                string label = String.Format("updated_{0}_label", ServiceName);
                string description = String.Format(
                    "Updated description for {0}",
                    ServiceName);
                UpdateStorageAccount(ServiceName, label, description, 
                    geoReplicationEnabled: false);

                // Get the updated property values for the storage account.
                // Convert the Label property to a readable value for display.
                XElement updatedProperties =
                    GetStorageAccountProperties(ServiceName);
                labelElement = updatedProperties.Descendants(wa + "Label").First();
                labelElement.Value = labelElement.Value.FromBase64();
                Console.WriteLine(
                    "Updated 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 Update Storage Account operation in the Service Management 
        /// REST API for the specified subscription, storage account name, new 
        /// description, label, and geo-replication enabled setting.
        /// </summary>
        /// <param name="serviceName">The name of the storage account to update.</param>
        /// <param name="label">The new label for the storage account.</param>
        /// <param name="description">The new description for the storage account.</param>
        /// <param name="geoReplicationEnabled">The new geo-replication setting, if applicable. 
        /// This optional parameter defaults to null.</param>
        private static void UpdateStorageAccount(
            string serviceName,
            string label,
            string description,
            bool? geoReplicationEnabled = null)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/services/storageservices/{1}";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, serviceName));
            XDocument requestBody = new XDocument(
                new XDeclaration("1.0", "UTF-8", "no"),
                new XElement(
                    wa + "UpdateStorageServiceInput",
                    new XElement(wa + "Description", description),
                    new XElement(wa + "Label", label.ToBase64())));

            // Add the GeoReplicationEnabled element if the version supports it.
            if ((geoReplicationEnabled != null) &&
                (String.CompareOrdinal(Version, "2011-12-01") >= 0))
            {
                requestBody.Element(wa + "UpdateStorageServiceInput").Add(
                    new XElement(
                        wa + "GeoReplicationEnabled", 
                        geoReplicationEnabled.ToString().ToLowerInvariant()));
            }

            XDocument responseBody;
            InvokeRequest(uri, "PUT", HttpStatusCode.OK, requestBody, out responseBody);
        }

        /// <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);
        }
    }
}

When run, the example program will generate output something like the following:

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>myexamplestorage1 description</Description>
    <Location>North Central US</Location>
    <Label>My Example 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>
Updated 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>Updated description for myexamplestorage1</Description>
    <Location>North Central US</Location>
    <Label>updated_myexamplestorage1_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>false</GeoReplicationEnabled>
  </StorageServiceProperties>
</StorageService>
Press any key to continue:

See Also

Show:
© 2014 Microsoft