내보내기(0) 인쇄
모두 확장

작업 상태 가져오기

업데이트 날짜: 2014년 4월

Get Operation Status 작업은 지정된 작업의 상태를 반환합니다. 비동기 작업을 호출한 후 Get Operation Status를 호출하여 작업이 성공했는지, 실패했는지, 계속 진행 중인지 여부를 확인할 수 있습니다.

다음과 같이 Get Operation Status 요청을 지정할 수 있습니다. <subscription-id>를 구독 ID로 바꾸고, <request-id>를 추적할 요청의 요청 ID로 바꾸십시오. 모든 요청의 x-ms-request-id 응답 헤더에 요청 ID가 반환됩니다.

 

메서드 요청 URI HTTP 버전

GET

https://management.core.windows.net/<subscription-id>/operations/<request-id>

HTTP/1.1

다음 표에서는 필수 요청 헤더와 선택적 요청 헤더에 대해 설명합니다.

 

요청 헤더 설명

x-ms-version

필수 사항입니다. 이 요청에 사용할 작업의 버전을 지정합니다. 이 헤더는 2009-10-01 이후로 설정되어야 합니다. 버전 헤더에 대한 자세한 내용은 서비스 관리 버전 관리를 참조하십시오.

응답에는 HTTP 상태 코드, 응답 헤더 집합 및 응답 본문이 포함되어 있습니다.

작업이 성공하면 상태 코드 200(정상)이 반환됩니다.

상태 코드에 대한 자세한 내용은 서비스 관리 상태 및 오류 코드를 참조하십시오.

이 작업의 응답에는 다음과 같은 헤더가 포함됩니다. 응답에는 추가 표준 HTTP 헤더가 포함될 수도 있습니다. 모든 표준 헤더는 HTTP/1.1 프로토콜 사양을 따릅니다.

 

응답 헤더 설명

x-ms-request-id

관리 서비스에 대해 수행된 요청을 고유하게 식별하는 값입니다.

응답 본문에는 지정된 비동기 작업이 성공했는지, 진행 중인지, 실패했는지 여부를 나타내는 상태가 포함됩니다. 이 상태는 Get Operation Status 작업 자체에 대해 반환되는 HTTP 상태 코드와는 별개입니다.

비동기 작업이 성공한 경우 성공한 요청에 대한 HTTP 상태 코드가 응답 본문에 포함됩니다.

비동기 작업이 실패한 경우 실패한 요청에 대한 HTTP 상태 코드 및 실패와 관련된 오류 정보가 응답 본문에 포함됩니다.


<?xml version="1.0" encoding="utf-8"?>
  <Operation xmlns="http://schemas.microsoft.com/windowsazure">
    <ID>request-id</ID>
    <Status>InProgress|Succeeded|Failed</Status>
    <!--Response includes HTTP status code only if the operation succeeded or failed -->
    <HttpStatusCode>http-status-code-for-asynchronous-operation</HttpStatusCode>
    <!--Response includes additional error information only if the operation failed -->
    <Error>
      <Code>error-code</Code>
      <Message>error-message</Message>
    </Error>
  </Operation>

다음 표에서는 응답 본문의 주요 요소에 대해 설명합니다.

 

요소 이름 설명

ID

비동기 요청의 요청 ID입니다. 비동기 요청의 x-ms-request-id 응답 헤더에 이 값이 반환됩니다.

Status

비동기 요청의 상태입니다. 가능한 값은 InProgress, Succeeded 또는 Failed입니다.

HttpStatusCode

비동기 요청의 HTTP 상태 코드입니다.

Code

비동기 요청이 실패한 경우 반환되는 관리 서비스 오류 코드입니다. 서비스에서 반환하는 가능한 오류 코드에 대한 자세한 내용은 서비스 관리 상태 및 오류 코드를 참조하십시오.

Message

비동기 요청이 실패한 경우 반환되는 관리 서비스 오류 메시지입니다.

<subscription-id>로 지정된 구독에 연결된 관리 인증서를 사용하여 이 작업을 인증할 수 있습니다. 자세한 내용은 서비스 관리 요청 인증을 참조하십시오.

완료되기까지의 처리 시간이 긴 서비스 관리 작업은 비동기 패턴으로 구현되었습니다. 성공한 모든 서비스 관리 REST API 작업 요청은 고유한 요청 ID를 반환하며 이 ID는 작업의 최종 상태를 확인하는 데 사용될 수 있습니다. 이 작업은 작업이 성공 또는 실패할 때까지 요청 ID와 함께 Get Operation Status를 폴링하여 수행합니다. 비동기 서비스 관리 작업 요청은 결과가 신속하게 반환됩니다. 비동기 작업 요청에 대한 오류 응답은 요청이 실패했으며 Windows Azure에서 보류 중인 비동기 작업이 없음을 나타냅니다. 작업 요청은 요청이 성공적으로 수행되었으며 Windows Azure에서 보류 중임을 나타내기 위해 상태 코드 202(수락)를 반환합니다. Get Operation Status 호출이 실패한 경우, 예를 들어 요청 ID가 구독에 대해 수행된 실제 서비스 관리 작업 요청과 일치하지 않는 Get Operation Status 작업은 오류 상태 코드 및 오류 응답 본문을 반환합니다. 상태 코드 200(정상)은 Get Operation Status 호출이 성공적으로 수행되었음을 나타내며, 반환되는 응답 본문에 요청 ID 매개 변수로 지정된 작업의 상태가 기록됩니다. 응답 본문에서 비동기 작업의 상태를 확인해야 합니다. Operation 요소 또는 응답 본문에는 보류 중인 작업의 현재 상태를 나타내는 Status 요소 값(InProgress, Failed 또는 Succeeded일 수 있음)이 포함됩니다. Status 요소에 InProgress가 포함될 때까지 Get Operation Status를 계속 폴링합니다. Status 요소 값이 Succeeded 또는 Failed인 경우 Operation 요소에 완료된 비동기 작업의 상태 코드가 포함된 HttpStatusCode 요소도 포함됩니다. Status 요소에 Failed가 포함된 경우 Operation 요소에 비동기 작업 오류에 대한 자세한 정보를 제공하는 CodeMessage 요소와 함께 Error 요소가 포함됩니다.

이 예제 콘솔 프로그램에서는 저장소 계정 만들기 작업을 사용하여 설명, 레이블 및 위치를 설정해 새 저장소 계정을 만듭니다. 그런 다음 저장소 계정 만들기 작업에서 반환된 요청 ID를 사용하여 호출이 성공 또는 실패하거나 폴링 시간이 초과할 때까지 Get Operation Status 작업을 폴링합니다. 마지막으로 저장소 계정 속성 가져오기를 호출하여 새 저장소 계정의 속성을 표시합니다. 샘플을 실행하려면 Version 문자열에 x-ms-version 헤더 값을 설정하고, SubscriptionId에 구독 ID를 설정하고, 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-10-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 = GetCertificate(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";
                string requestId = CreateStorageAccount(
                    ServiceName, 
                    description, 
                    label, 
                    null, 
                    location);
                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, and location or affinity group.
        /// </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>
        /// <returns>The requestId for the operation.</returns>
        private static string CreateStorageAccount(
            string serviceName,
            string description,
            string label,
            string affinityGroup,
            string location)
        {
            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));
 
            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 GetCertificate(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="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>
  </StorageServiceProperties>
</StorageService>
Press any key to continue:

Microsoft는 MSDN 웹 사이트에 대한 귀하의 의견을 이해하기 위해 온라인 설문 조사를 진행하고 있습니다. 참여하도록 선택하시면 MSDN 웹 사이트에서 나가실 때 온라인 설문 조사가 표시됩니다.

참여하시겠습니까?
표시:
© 2014 Microsoft