diff --git a/README.md b/README.md
index cc269ef1224..eab23b86ae4 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@ Welcome to the Microsoft Quantum Development Kit!
This repository contains the runtime components for the [Quantum Development Kit](https://docs.microsoft.com/quantum/).
It consists of the libraries and packages needed to create and simulate quantum applications using Q#.
+- **[Azure/](./src/Azure/)**: Source for client package to create and manage jobs in Azure Quantum.
- **[Simulation/](./src/Simulation/)**: Source for Q# simulation. Includes code generation, full-state and other simulators.
- **[xUnit/](./src/Xunit/)**: Source for the xUnit's Q# test-case discoverer.
diff --git a/Simulation.sln b/Simulation.sln
index ca07a7fe45b..252a287f9d0 100644
--- a/Simulation.sln
+++ b/Simulation.sln
@@ -3,6 +3,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28809.33
MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{99E234BC-997E-4E63-9F5C-3C3977543404}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure", "Azure", "{A1E878CB-ADF1-457A-9223-06F96ED8F7A6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.Quantum.Client", "src\Azure\Azure.Quantum.Client\Microsoft.Azure.Quantum.Client.csproj", "{DF654202-0008-4CDE-B35E-018CEFD0FC68}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.Quantum.Client.Test", "src\Azure\Azure.Quantum.Client.Test\Microsoft.Azure.Quantum.Client.Test.csproj", "{1467128C-90E4-4723-B5C7-9469B83F54A6}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Runtime.Core", "src\Simulation\Core\Microsoft.Quantum.Runtime.Core.csproj", "{E9123D45-C1B0-4462-8810-D26ED6D31944}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime", "src\Simulation\QCTraceSimulator\Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj", "{058CB08D-BFA7-41E2-BE6B-0A0A72054F91}"
@@ -53,6 +61,38 @@ Global
RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Debug|x64.Build.0 = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Release|x64.ActiveCfg = Release|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.Release|x64.Build.0 = Release|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Debug|x64.Build.0 = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.MinSizeRel|x64.Build.0 = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Release|x64.ActiveCfg = Release|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.Release|x64.Build.0 = Release|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
+ {1467128C-90E4-4723-B5C7-9469B83F54A6}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{E9123D45-C1B0-4462-8810-D26ED6D31944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9123D45-C1B0-4462-8810-D26ED6D31944}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9123D45-C1B0-4462-8810-D26ED6D31944}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -297,6 +337,9 @@ Global
{09C842CB-930C-4C7D-AD5F-E30DE4A55820} = {34D419E9-CCF1-4E48-9FA4-3AD4B86BEEB4}
{2F5796A7-4AF8-4B78-928A-0A3A80752F9D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820}
{944FE7EF-9220-4CC6-BB20-CE517195B922} = {A567C185-A429-418B-AFDE-6F1785BA4A77}
+ {A1E878CB-ADF1-457A-9223-06F96ED8F7A6} = {99E234BC-997E-4E63-9F5C-3C3977543404}
+ {DF654202-0008-4CDE-B35E-018CEFD0FC68} = {A1E878CB-ADF1-457A-9223-06F96ED8F7A6}
+ {1467128C-90E4-4723-B5C7-9469B83F54A6} = {A1E878CB-ADF1-457A-9223-06F96ED8F7A6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821}
diff --git a/build/manifest.ps1 b/build/manifest.ps1
index cf7afbc72b4..07a8fca41f3 100644
--- a/build/manifest.ps1
+++ b/build/manifest.ps1
@@ -5,6 +5,7 @@
@{
Packages = @(
+ "Microsoft.Azure.Quantum.Client",
"Microsoft.Quantum.CsharpGeneration",
"Microsoft.Quantum.Development.Kit",
"Microsoft.Quantum.QSharp.Core",
@@ -13,6 +14,7 @@
"Microsoft.Quantum.Xunit"
);
Assemblies = @(
+ ".\src\Azure\Azure.Quantum.Client\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Azure.Quantum.Client.dll",
".\src\simulation\CsharpGeneration\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.CsharpGeneration.dll",
".\src\simulation\CsharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.CsharpGeneration.App.dll",
".\src\simulation\CsharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.RoslynWrapper.dll",
diff --git a/build/pack.ps1 b/build/pack.ps1
index 53c7d617f7f..7aa7227d8da 100644
--- a/build/pack.ps1
+++ b/build/pack.ps1
@@ -54,6 +54,7 @@ function Pack-Dotnet() {
Write-Host "##[info]Using nuget to create packages"
+Pack-Dotnet '../src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj'
Pack-One '../src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj' '-IncludeReferencedProjects'
Pack-Dotnet '../src/Simulation/Core/Microsoft.Quantum.Runtime.Core.csproj'
Pack-Dotnet '../src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj'
diff --git a/src/Azure/Azure.Quantum.Client.Test/Helpers/MockHelper.cs b/src/Azure/Azure.Quantum.Client.Test/Helpers/MockHelper.cs
new file mode 100644
index 00000000000..3cdc42675aa
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client.Test/Helpers/MockHelper.cs
@@ -0,0 +1,34 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Moq;
+using Moq.Protected;
+
+namespace Microsoft.Azure.Quantum.Test
+{
+ public static class MockHelper
+ {
+ internal static HttpRequestMessage RequestMessage { get; private set; }
+
+ internal static HttpResponseMessage ResponseMessage { get; set; }
+
+ public static HttpClient GetHttpClientMock()
+ {
+ Mock mock = new Mock();
+
+ mock.Protected()
+ .Setup>("SendAsync", ItExpr.IsAny(), ItExpr.IsAny())
+ .Returns((HttpRequestMessage request, CancellationToken token) =>
+ {
+ RequestMessage = request;
+ return Task.FromResult(ResponseMessage);
+ });
+
+ return new HttpClient(mock.Object);
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client.Test/Helpers/TestConstants.cs b/src/Azure/Azure.Quantum.Client.Test/Helpers/TestConstants.cs
new file mode 100644
index 00000000000..2d35b2cfe14
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client.Test/Helpers/TestConstants.cs
@@ -0,0 +1,15 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+namespace Microsoft.Azure.Quantum.Test
+{
+ public static class TestConstants
+ {
+ public const string SubscriptionId = "sub1";
+ public const string ResourceGroupName = "rg1";
+ public const string WorkspaceName = "ws1";
+ public const string ProviderId = "provider1";
+ public const string Endpoint = "https://test";
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client.Test/Microsoft.Azure.Quantum.Client.Test.csproj b/src/Azure/Azure.Quantum.Client.Test/Microsoft.Azure.Quantum.Client.Test.csproj
new file mode 100644
index 00000000000..7965e696874
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client.Test/Microsoft.Azure.Quantum.Client.Test.csproj
@@ -0,0 +1,34 @@
+
+
+
+ netcoreapp3.1
+ x64
+ false
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+ ..\Common\StyleCop.ruleset
+ Microsoft.Azure.Quantum.Test
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs
new file mode 100644
index 00000000000..eb96b2d1e00
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs
@@ -0,0 +1,233 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using Microsoft.Azure.Quantum.Client;
+using Microsoft.Azure.Quantum.Client.Models;
+using Microsoft.Rest;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Newtonsoft.Json;
+
+namespace Microsoft.Azure.Quantum.Test
+{
+ [TestClass]
+ public class WorkspaceTest
+ {
+ [TestMethod]
+ public void SubmitJobTest()
+ {
+ string jobId = Guid.NewGuid().ToString();
+
+ // Craft response
+ SetJobResponseMessage(jobId);
+
+ // Create Job
+ IWorkspace workspace = GetWorkspace();
+
+ JobDetails jobDetails = CreateJobDetails(jobId);
+ CloudJob job = new CloudJob(workspace, jobDetails);
+ CloudJob receivedJob;
+
+ // -ve cases
+ try
+ {
+ jobDetails.ContainerUri = null;
+ receivedJob = workspace.SubmitJob(job);
+ Assert.Fail();
+ }
+ catch (ValidationException)
+ {
+ jobDetails.ContainerUri = "https://uri";
+ }
+
+ try
+ {
+ jobDetails.ProviderId = null;
+ receivedJob = workspace.SubmitJob(job);
+ Assert.Fail();
+ }
+ catch (ValidationException)
+ {
+ jobDetails.ProviderId = TestConstants.ProviderId;
+ }
+
+ // Success
+ receivedJob = workspace.SubmitJob(job);
+
+ // Validate request
+ ValidateJobRequestMessage(jobId, HttpMethod.Put);
+
+ // Validate response
+ Assert.IsNotNull(receivedJob);
+
+ Assert.IsNotNull(receivedJob.Workspace);
+
+ Assert.AreEqual(
+ expected: jobId,
+ actual: receivedJob.Details.Id);
+ }
+
+ [TestMethod]
+ public void GetJobTest()
+ {
+ string jobId = Guid.NewGuid().ToString();
+
+ // Craft response
+ SetJobResponseMessage(jobId);
+
+ // Get Job
+ IWorkspace workspace = GetWorkspace();
+
+ CloudJob receivedJob = workspace.GetJob(jobId);
+
+ // Validate request
+ ValidateJobRequestMessage(jobId, HttpMethod.Get);
+
+ // Validate response
+ Assert.IsNotNull(receivedJob);
+
+ Assert.IsNotNull(receivedJob.Workspace);
+
+ Assert.AreEqual(
+ expected: jobId,
+ actual: receivedJob.Details.Id);
+ }
+
+ [TestMethod]
+ public void CancelJobTest()
+ {
+ string jobId = Guid.NewGuid().ToString();
+
+ // Craft response
+ SetJobResponseMessage(jobId);
+
+ // Cancel Job
+ IWorkspace workspace = GetWorkspace();
+
+ CloudJob receivedJob = workspace.CancelJob(jobId);
+
+ // Validate request
+ ValidateJobRequestMessage(jobId, HttpMethod.Delete);
+
+ // Validate response
+ Assert.IsNotNull(receivedJob);
+
+ Assert.IsNotNull(receivedJob.Workspace);
+
+ Assert.AreEqual(
+ expected: jobId,
+ actual: receivedJob.Details.Id);
+
+ // Convenience method
+ CloudJob job = new CloudJob(workspace, CreateJobDetails(jobId));
+ string newJobId = Guid.NewGuid().ToString();
+ SetJobResponseMessage(newJobId);
+
+ Assert.AreEqual(
+ jobId,
+ job.Details.Id);
+
+ job.CancelAsync().Wait();
+
+ Assert.AreEqual(
+ newJobId,
+ job.Details.Id);
+ }
+
+ [TestMethod]
+ public void ListJobsTest()
+ {
+ // Craft response
+ JobDetails jobDetails = new JobDetails
+ {
+ ProviderId = TestConstants.ProviderId,
+ };
+
+ Page page = new Page()
+ {
+ Items = new List { jobDetails },
+ };
+
+ MockHelper.ResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(JsonConvert.SerializeObject(page)),
+ };
+
+ // Cancel Job
+ IWorkspace workspace = GetWorkspace();
+
+ List receivedJobs = workspace.ListJobs().ToList();
+
+ // Validate request
+ ValidateJobRequestMessage(null, HttpMethod.Get);
+
+ // Validate response
+ Assert.IsNotNull(receivedJobs);
+
+ Assert.IsNotNull(receivedJobs.Single().Workspace);
+
+ Assert.AreEqual(
+ expected: jobDetails.ProviderId,
+ actual: receivedJobs.Single().Details.ProviderId);
+ }
+
+ private static IWorkspace GetWorkspace()
+ {
+ return new Workspace(
+ subscriptionId: TestConstants.SubscriptionId,
+ resourceGroupName: TestConstants.ResourceGroupName,
+ workspaceName: TestConstants.WorkspaceName)
+ {
+ // Mock jobs client (only needed for unit tests)
+ JobsClient = new QuantumClient(MockHelper.GetHttpClientMock(), true)
+ {
+ SubscriptionId = TestConstants.SubscriptionId,
+ ResourceGroupName = TestConstants.ResourceGroupName,
+ WorkspaceName = TestConstants.WorkspaceName,
+ BaseUri = new Uri(TestConstants.Endpoint),
+ }.Jobs,
+ };
+ }
+
+ private static void SetJobResponseMessage(string jobId)
+ {
+ MockHelper.ResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(JsonConvert.SerializeObject(CreateJobDetails(jobId))),
+ };
+ }
+
+ private static JobDetails CreateJobDetails(string jobId)
+ {
+ return new JobDetails(
+ id: jobId,
+ containerUri: "https://uri",
+ inputDataFormat: "format1",
+ providerId: TestConstants.ProviderId,
+ target: "target");
+ }
+
+ private static void ValidateJobRequestMessage(
+ string jobId,
+ HttpMethod method)
+ {
+ var requestMessage = MockHelper.RequestMessage;
+
+ // Url
+ string expectedUri = $"{TestConstants.Endpoint}/v1.0/subscriptions/{TestConstants.SubscriptionId}/resourceGroups/{TestConstants.ResourceGroupName}/providers/Microsoft.Quantum/workspaces/{TestConstants.WorkspaceName}/jobs/{jobId}";
+ Assert.AreEqual(
+ expected: expectedUri.TrimEnd('/'),
+ actual: requestMessage.RequestUri.ToString());
+
+ // Method
+ Assert.AreEqual(
+ expected: method,
+ actual: requestMessage.Method);
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Authentication/AuthorizationClientHandler.cs b/src/Azure/Azure.Quantum.Client/Authentication/AuthorizationClientHandler.cs
new file mode 100644
index 00000000000..8617be8c8dd
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Authentication/AuthorizationClientHandler.cs
@@ -0,0 +1,49 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.Azure.Quantum.Authentication
+{
+ ///
+ /// Authorization client handler class.
+ ///
+ internal class AuthorizationClientHandler : HttpClientHandler
+ {
+ private const string AuthorizationHeaderName = "Authorization";
+ private const string BearerScheme = "Bearer";
+
+ private readonly IAccessTokenProvider accessTokenProvider;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The access token provider.
+ public AuthorizationClientHandler(IAccessTokenProvider accessTokenProvider)
+ {
+ this.accessTokenProvider = accessTokenProvider;
+ }
+
+ ///
+ /// Creates an instance of based on the information provided in the as an operation that will not block.
+ ///
+ /// The HTTP request message.
+ /// A cancellation token to cancel the operation.
+ ///
+ /// The task object representing the asynchronous operation.
+ ///
+ protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ if (!request.Headers.Contains(AuthorizationHeaderName))
+ {
+ string accessToken = await this.accessTokenProvider.GetAccessTokenAsync(cancellationToken);
+ request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(BearerScheme, accessToken);
+ }
+
+ return await base.SendAsync(request, cancellationToken);
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Authentication/CustomAccessTokenProvider.cs b/src/Azure/Azure.Quantum.Client/Authentication/CustomAccessTokenProvider.cs
new file mode 100644
index 00000000000..b20e013b091
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Authentication/CustomAccessTokenProvider.cs
@@ -0,0 +1,128 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Linq;
+using System.Net.Http;
+using System.Security.Authentication;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Azure.Quantum.Utility;
+using Microsoft.Identity.Client;
+using Microsoft.Identity.Client.Extensions.Msal;
+
+namespace Microsoft.Azure.Quantum.Authentication
+{
+ ///
+ /// This class manually uses MSAL to get an access token.
+ /// It first tries to get silently, if that doesn't work, it tries to get interactively.
+ ///
+ ///
+ internal class CustomAccessTokenProvider : IAccessTokenProvider
+ {
+ private readonly LazyAsync applicationLazy;
+ private readonly string[] scopes;
+ private readonly string subscriptionId;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Subscription Id of the account in use.
+ public CustomAccessTokenProvider(string subscriptionId)
+ {
+ static async Task GetSubscriptionTenantUri(string subscriptionId)
+ {
+ var uri = $"https://management.azure.com/subscriptions/{subscriptionId}?api-version=2018-01-01";
+ try
+ {
+ static string GetTenantUriFromHeader(System.Net.Http.Headers.AuthenticationHeaderValue header) =>
+ header
+ .Parameter
+ .Replace("Bearer ", string.Empty)
+ .Split(",")
+ .Select(part => part.Split("="))
+ .ToDictionary(rg => rg[0], rg => rg[1])["authorization_uri"]
+ .Trim('\'', '"');
+
+ using var client = new HttpClient();
+ var httpResult = await client.GetAsync(uri);
+
+ return httpResult
+ .Headers
+ .WwwAuthenticate
+ .Select(GetTenantUriFromHeader)
+ .Single();
+ }
+ catch (System.Exception ex)
+ {
+ throw new AuthenticationException("Unable to extract tenantUri!", ex);
+ }
+ }
+
+ this.scopes = new string[] { Constants.Aad.Audience };
+ this.subscriptionId = subscriptionId;
+ this.applicationLazy =
+ new LazyAsync(async () =>
+ {
+ var application = PublicClientApplicationBuilder
+ .Create(Constants.Aad.ApplicationId)
+ .WithDefaultRedirectUri()
+ .WithAuthority(await GetSubscriptionTenantUri(subscriptionId))
+ .Build();
+ var cacheHelper = await CreateCacheHelperAsync();
+ cacheHelper.RegisterCache(application.UserTokenCache);
+ return application;
+ });
+ }
+
+ ///
+ /// Tries to get access token silently, if didn't work, tries to get it interactively.
+ ///
+ /// The cancellation token.
+ /// A encapsulating the access token.
+ public async Task GetAccessTokenAsync(CancellationToken cancellationToken)
+ {
+ var application = applicationLazy.Value;
+
+ try
+ {
+ var accounts = await application.GetAccountsAsync();
+
+ // Try silently first
+ var result = await application
+ .AcquireTokenSilent(scopes, accounts.FirstOrDefault())
+ .ExecuteAsync();
+
+ return result.AccessToken;
+ }
+ catch (MsalUiRequiredException)
+ {
+ // Didn't work, perform interactive logging
+ var result = await application
+ .AcquireTokenInteractive(scopes)
+ .ExecuteAsync();
+
+ return result.AccessToken;
+ }
+ }
+
+ private static async Task CreateCacheHelperAsync()
+ {
+ StorageCreationProperties storageProperties;
+
+ storageProperties = new StorageCreationPropertiesBuilder(
+ Constants.Aad.CacheFileName,
+ MsalCacheHelper.UserRootDirectory,
+ Constants.Aad.ApplicationId)
+ .WithMacKeyChain(
+ Constants.Aad.KeyChainServiceName,
+ Constants.Aad.KeyChainAccountName)
+ .Build();
+
+ var cacheHelper = await MsalCacheHelper.CreateAsync(storageProperties).ConfigureAwait(false);
+
+ cacheHelper.VerifyPersistence();
+ return cacheHelper;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Azure/Azure.Quantum.Client/Authentication/IAccessTokenProvider.cs b/src/Azure/Azure.Quantum.Client/Authentication/IAccessTokenProvider.cs
new file mode 100644
index 00000000000..4ad34c537f4
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Authentication/IAccessTokenProvider.cs
@@ -0,0 +1,22 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.Azure.Quantum.Authentication
+{
+ ///
+ /// Generic interface to retrieve access token. This is not exposed to the user.
+ ///
+ internal interface IAccessTokenProvider
+ {
+ ///
+ /// Gets the access token.
+ ///
+ /// The cancellation token.
+ /// Access token string
+ Task GetAccessTokenAsync(CancellationToken cancellationToken);
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Authentication/StaticAccessTokenProvider.cs b/src/Azure/Azure.Quantum.Client/Authentication/StaticAccessTokenProvider.cs
new file mode 100644
index 00000000000..bcbfe47bfd4
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Authentication/StaticAccessTokenProvider.cs
@@ -0,0 +1,38 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Azure.Quantum.Utility;
+
+namespace Microsoft.Azure.Quantum.Authentication
+{
+ ///
+ /// This class accepts an access token string and provides it.
+ ///
+ ///
+ internal class StaticAccessTokenProvider : IAccessTokenProvider
+ {
+ private readonly string accessToken;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public StaticAccessTokenProvider(string accessToken)
+ {
+ Ensure.NotNullOrWhiteSpace(accessToken, nameof(accessToken));
+
+ this.accessToken = accessToken;
+ }
+
+ ///
+ /// Returns the static access token.
+ ///
+ /// The cancellation token.
+ public Task GetAccessTokenAsync(CancellationToken cancellationToken)
+ {
+ return Task.FromResult(this.accessToken);
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Authentication/TokenCredentialProvider.cs b/src/Azure/Azure.Quantum.Client/Authentication/TokenCredentialProvider.cs
new file mode 100644
index 00000000000..53b8c3fcd60
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Authentication/TokenCredentialProvider.cs
@@ -0,0 +1,44 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Core;
+using Microsoft.Azure.Quantum.Utility;
+
+namespace Microsoft.Azure.Quantum.Authentication
+{
+ ///
+ /// A provider for TokenCredential
+ ///
+ ///
+ internal class TokenCredentialProvider : IAccessTokenProvider
+ {
+ private readonly TokenCredential tokenCredential;
+ private readonly string[] scopes;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The token credential.
+ public TokenCredentialProvider(TokenCredential tokenCredential)
+ {
+ this.tokenCredential = tokenCredential;
+ this.scopes = new string[] { Constants.Aad.Audience };
+ }
+
+ ///
+ /// Gets the access token.
+ ///
+ /// The cancellation token.
+ ///
+ /// Access token string
+ ///
+ public async Task GetAccessTokenAsync(CancellationToken cancellationToken)
+ {
+ AccessToken accessToken = await this.tokenCredential.GetTokenAsync(new TokenRequestContext(this.scopes), cancellationToken);
+ return accessToken.Token;
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs
new file mode 100644
index 00000000000..32137454db7
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs
@@ -0,0 +1,96 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Azure.Quantum.Client.Models;
+using Microsoft.Azure.Quantum.Utility;
+using Microsoft.Quantum.Runtime;
+
+namespace Microsoft.Azure.Quantum
+{
+ ///
+ /// Cloud job class.
+ ///
+ public class CloudJob : IQuantumMachineJob
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The workspace.
+ /// The job details.
+ public CloudJob(IWorkspace workspace, JobDetails jobDetails)
+ {
+ Ensure.NotNull(workspace, nameof(workspace));
+ Ensure.NotNull(jobDetails, nameof(jobDetails));
+
+ Workspace = workspace;
+ Details = jobDetails;
+ }
+
+ ///
+ /// Gets whether job execution failed.
+ ///
+ public bool Failed => !InProgress &&
+ !Succeeded;
+
+ ///
+ /// Gets the job id.
+ ///
+ public string Id => Details.Id;
+
+ ///
+ /// Gets whether the job execution has completed.
+ ///
+ public bool InProgress => Status != "Cancelled" &&
+ Status != "Failed" &&
+ Status != "Succeeded";
+
+ ///
+ /// Gets the status of the submitted job.
+ ///
+ public string Status => Details.Status;
+
+ ///
+ /// Gets whether the job execution completed successfully.
+ ///
+ public bool Succeeded => Status == "Succeeded";
+
+ ///
+ /// Gets an URI to access the job.
+ ///
+ public Uri Uri => throw new NotImplementedException();
+
+ ///
+ /// Gets the workspace.
+ ///
+ public IWorkspace Workspace { get; private set; }
+
+ ///
+ /// Gets the job details.
+ ///
+ public JobDetails Details { get; private set; }
+
+ ///
+ /// Refreshes the job.
+ ///
+ /// The cancellation token.
+ public async Task RefreshAsync(CancellationToken cancellationToken = default)
+ {
+ CloudJob job = (CloudJob)await this.Workspace.GetJobAsync(this.Details.Id, cancellationToken);
+ this.Details = job.Details;
+ }
+
+ ///
+ /// Cancels the job.
+ ///
+ /// The cancellation token.
+ public async Task CancelAsync(CancellationToken cancellationToken = default)
+ {
+ CloudJob job = (CloudJob)await this.Workspace.CancelJobAsync(this.Details.Id, cancellationToken);
+ this.Details = job.Details;
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs
new file mode 100644
index 00000000000..91bbb6d3132
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs
@@ -0,0 +1,55 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Quantum.Runtime;
+
+namespace Microsoft.Azure.Quantum
+{
+ ///
+ /// IWorkspace interface.
+ ///
+ public interface IWorkspace
+ {
+ ///
+ /// Submits the job.
+ ///
+ /// The job definition.
+ /// The cancellation token.
+ /// The job response.
+ Task SubmitJobAsync(
+ CloudJob jobDefinition,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Cancels the job.
+ ///
+ /// The job identifier.
+ /// The cancellation token.
+ /// The job response.
+ Task CancelJobAsync(
+ string jobId,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets the job.
+ ///
+ /// The job identifier.
+ /// The cancellation token.
+ /// The job object.
+ Task GetJobAsync(
+ string jobId,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Lists the jobs.
+ ///
+ /// The cancellation token.
+ /// List of jobs
+ Task> ListJobsAsync(
+ CancellationToken cancellationToken = default);
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs
new file mode 100644
index 00000000000..9af37ffd70e
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs
@@ -0,0 +1,181 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Core;
+using Microsoft.Azure.Quantum.Authentication;
+using Microsoft.Azure.Quantum.Client;
+using Microsoft.Azure.Quantum.Client.Models;
+using Microsoft.Azure.Quantum.Storage;
+using Microsoft.Azure.Quantum.Utility;
+using Microsoft.Quantum.Runtime;
+
+namespace Microsoft.Azure.Quantum
+{
+ ///
+ /// Workspace class.
+ ///
+ ///
+ public class Workspace : IWorkspace
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The subscription identifier.
+ /// Name of the resource group.
+ /// Name of the workspace.
+ /// The token credential.
+ /// The base URI.
+ public Workspace(
+ string subscriptionId,
+ string resourceGroupName,
+ string workspaceName,
+ TokenCredential tokenCredential = null,
+ Uri baseUri = null)
+ : this(
+ subscriptionId,
+ resourceGroupName,
+ workspaceName,
+ tokenCredential == null ? null : new TokenCredentialProvider(tokenCredential),
+ baseUri)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The subscription identifier.
+ /// Name of the resource group.
+ /// Name of the workspace.
+ /// The access token.
+ /// The base URI.
+ public Workspace(
+ string subscriptionId,
+ string resourceGroupName,
+ string workspaceName,
+ string accessToken,
+ Uri baseUri = null)
+ : this(
+ subscriptionId,
+ resourceGroupName,
+ workspaceName,
+ new StaticAccessTokenProvider(accessToken),
+ baseUri)
+ {
+ }
+
+ private Workspace(
+ string subscriptionId,
+ string resourceGroupName,
+ string workspaceName,
+ IAccessTokenProvider accessTokenProvider,
+ Uri baseUri = null)
+ {
+ Ensure.NotNullOrWhiteSpace(subscriptionId, nameof(subscriptionId));
+ Ensure.NotNullOrWhiteSpace(resourceGroupName, nameof(resourceGroupName));
+ Ensure.NotNullOrWhiteSpace(workspaceName, nameof(workspaceName));
+
+ accessTokenProvider = accessTokenProvider ?? new CustomAccessTokenProvider(subscriptionId);
+
+ Ensure.NotNull(accessTokenProvider, nameof(accessTokenProvider));
+
+ this.JobsClient = new QuantumClient(new AuthorizationClientHandler(accessTokenProvider))
+ {
+ BaseUri = baseUri ?? new Uri(Constants.DefaultBaseUri),
+ SubscriptionId = subscriptionId,
+ ResourceGroupName = resourceGroupName,
+ WorkspaceName = workspaceName,
+ }.Jobs;
+ }
+
+ ///
+ /// Gets or sets the jobs client.
+ /// Internal only.
+ ///
+ ///
+ /// The jobs client.
+ ///
+ internal IJobsOperations JobsClient { get; set; }
+
+ ///
+ /// Submits the job.
+ ///
+ /// The job definition.
+ /// The cancellation token.
+ ///
+ /// The job response.
+ ///
+ public async Task SubmitJobAsync(
+ CloudJob jobDefinition,
+ CancellationToken cancellationToken = default)
+ {
+ Ensure.NotNull(jobDefinition, nameof(jobDefinition));
+ Ensure.NotNullOrWhiteSpace(jobDefinition.Details.Id, nameof(jobDefinition.Details.Id));
+
+ JobDetails jobDetails = await this.JobsClient.PutAsync(
+ jobId: jobDefinition.Details.Id,
+ jobDefinition: jobDefinition.Details,
+ cancellationToken: cancellationToken);
+
+ return new CloudJob(this, jobDetails);
+ }
+
+ ///
+ /// Cancels the job.
+ ///
+ /// The job identifier.
+ /// The cancellation token.
+ /// Cloud job.
+ public async Task CancelJobAsync(string jobId, CancellationToken cancellationToken = default)
+ {
+ Ensure.NotNullOrWhiteSpace(jobId, nameof(jobId));
+
+ JobDetails jobDetails = await this.JobsClient.DeleteAsync(
+ jobId: jobId,
+ cancellationToken: cancellationToken);
+
+ return new CloudJob(this, jobDetails);
+ }
+
+ ///
+ /// Gets the job.
+ ///
+ /// The job identifier.
+ /// The cancellation token.
+ ///
+ /// The job response.
+ ///
+ public async Task GetJobAsync(string jobId, CancellationToken cancellationToken = default)
+ {
+ Ensure.NotNullOrWhiteSpace(jobId, nameof(jobId));
+
+ JobDetails jobDetails = await this.JobsClient.GetAsync(
+ jobId: jobId,
+ cancellationToken: cancellationToken);
+
+ return new CloudJob(this, jobDetails);
+ }
+
+ ///
+ /// Lists the jobs.
+ ///
+ /// The cancellation token.
+ ///
+ /// List of jobs.
+ ///
+ public async Task> ListJobsAsync(CancellationToken cancellationToken = default)
+ {
+ var jobs = await this.JobsClient.ListAsync(
+ cancellationToken: cancellationToken);
+
+ return jobs
+ .Select(details => new CloudJob(this, details));
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/WorkspaceExtensions.cs b/src/Azure/Azure.Quantum.Client/JobManagement/WorkspaceExtensions.cs
new file mode 100644
index 00000000000..4f5c60589ec
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/WorkspaceExtensions.cs
@@ -0,0 +1,59 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Collections.Generic;
+
+namespace Microsoft.Azure.Quantum
+{
+ ///
+ /// Extension methods for Workspace.
+ ///
+ public static class WorkspaceExtensions
+ {
+ ///
+ /// Submits the job.
+ ///
+ /// The workspace.
+ /// The job definition.
+ /// The job response.
+ public static CloudJob SubmitJob(
+ this IWorkspace workspace,
+ CloudJob jobDefinition)
+ {
+ return workspace.SubmitJobAsync(jobDefinition).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Cancels the job.
+ ///
+ /// The workspace.
+ /// The job identifier.
+ /// The job response.
+ public static CloudJob CancelJob(this IWorkspace workspace, string jobId)
+ {
+ return workspace.CancelJobAsync(jobId).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Gets the job.
+ ///
+ /// The workspace.
+ /// The job identifier.
+ /// The job response.
+ public static CloudJob GetJob(this IWorkspace workspace, string jobId)
+ {
+ return workspace.GetJobAsync(jobId).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Lists the jobs.
+ ///
+ /// The workspace.
+ /// List of job identifiers.
+ public static IEnumerable ListJobs(this IWorkspace workspace)
+ {
+ return workspace.ListJobsAsync().GetAwaiter().GetResult();
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
new file mode 100644
index 00000000000..d6ca6671156
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Threading.Tasks;
+using Microsoft.Quantum.Runtime;
+
+namespace Microsoft.Azure.Quantum
+{
+ public static class QuantumMachineFactory
+ {
+ ///
+ /// Creates a quantum machine for job submission to an Azure Quantum workspace.
+ ///
+ /// The Azure Quantum workspace.
+ /// The execution target for job submission.
+ /// The connection string for the Azure storage account.
+ /// A quantum machine for job submission targeting targetName.
+ public static IQuantumMachine? CreateMachine(Workspace workspace, string targetName, string storageAccountConnectionString)
+ {
+ if (string.IsNullOrEmpty(targetName))
+ {
+ return null;
+ }
+
+ if (targetName.StartsWith("ionq."))
+ {
+ var ionQType = Type.GetType(
+ "Microsoft.Quantum.Providers.IonQ.Targets.IonQQuantumMachine, Microsoft.Quantum.Providers.IonQ",
+ throwOnError: true);
+ return (IQuantumMachine)Activator.CreateInstance(
+ ionQType, targetName, storageAccountConnectionString, workspace);
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj
new file mode 100644
index 00000000000..d4b6c807b9e
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Microsoft.Azure.Quantum.Client.csproj
@@ -0,0 +1,49 @@
+
+
+
+
+
+ netstandard2.1
+ x64
+ Client library for Azure Quantum.
+
+
+
+ https://docs.microsoft.com/quantum/
+ See: https://docs.microsoft.com/quantum/relnotes/
+ MIT
+ https://github.com/microsoft/qsharp-runtime
+ Azure Quantum Q# Qsharp
+ https://secure.gravatar.com/avatar/bd1f02955b2853ba0a3b1cdc2434e8ec.png
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ ..\Common\StyleCop.ruleset
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Azure/Azure.Quantum.Client/Properties/AssemblyInfo.cs b/src/Azure/Azure.Quantum.Client/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..098be651ff1
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Properties/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Microsoft.Azure.Quantum.Client.Test" + DelaySign.PUBLIC_KEY)]
\ No newline at end of file
diff --git a/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs
new file mode 100644
index 00000000000..5e30e1f20f4
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Storage/IJobStorageHelper.cs
@@ -0,0 +1,62 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Bond;
+
+namespace Microsoft.Azure.Quantum.Storage
+{
+ ///
+ /// Job storage helper.
+ ///
+ public interface IJobStorageHelper
+ {
+ ///
+ /// Gets the underlying storage helper.
+ ///
+ IStorageHelper StorageHelper { get; }
+
+ ///
+ /// Uploads the job input.
+ ///
+ /// The job id.
+ /// The input.
+ /// Serialization protocol of the input to upload.
+ /// The cancellation token.
+ /// Container uri + Input uri.
+ Task<(string containerUri, string inputUri)> UploadJobInputAsync(
+ string jobId,
+ Stream input,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Uploads the job program output mapping.
+ ///
+ /// The job id.
+ /// The job program output mapping.
+ /// Serialization protocol of the mapping to upload.
+ /// The cancellation token.
+ /// Container uri + Mapping uri.
+ Task<(string containerUri, string mappingUri)> UploadJobMappingAsync(
+ string jobId,
+ Stream mapping,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Downloads the job's execution output.
+ ///
+ /// The job id.
+ /// The destination stream.
+ /// The cancellation token.
+ /// Serialization protocol of the downloaded execution output.
+ Task DownloadJobOutputAsync(
+ string jobId,
+ Stream destination,
+ CancellationToken cancellationToken = default);
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs
new file mode 100644
index 00000000000..72eb5db7f23
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs
@@ -0,0 +1,72 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Bond;
+using Microsoft.WindowsAzure.Storage.Blob;
+
+namespace Microsoft.Azure.Quantum.Storage
+{
+ public interface IStorageHelper
+ {
+ ///
+ /// Downloads the BLOB.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The destination.
+ /// The cancellation token.
+ /// Serialization protocol of the downloaded BLOB.
+ Task DownloadBlobAsync(
+ string containerName,
+ string blobName,
+ Stream destination,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Uploads the BLOB.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The input.
+ /// Serialization protocol of the BLOB to upload.
+ /// The cancellation token.
+ /// async task.
+ Task UploadBlobAsync(
+ string containerName,
+ string blobName,
+ Stream input,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets the BLOB sas URI.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The expiry interval.
+ /// The permissions.
+ /// Blob uri.
+ string GetBlobSasUri(
+ string containerName,
+ string blobName,
+ TimeSpan expiryInterval,
+ SharedAccessBlobPermissions permissions);
+
+ ///
+ /// Gets the BLOB container sas URI.
+ ///
+ /// Name of the container.
+ /// The expiry interval.
+ /// The permissions.
+ /// Container uri.
+ string GetBlobContainerSasUri(
+ string containerName,
+ TimeSpan expiryInterval,
+ SharedAccessBlobPermissions permissions);
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs
new file mode 100644
index 00000000000..ac52ac1ae4d
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs
@@ -0,0 +1,133 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Bond;
+using Microsoft.Azure.Quantum.Utility;
+using Microsoft.WindowsAzure.Storage.Blob;
+
+namespace Microsoft.Azure.Quantum.Storage
+{
+ public class JobStorageHelper : IJobStorageHelper
+ {
+ private readonly TimeSpan expiryInterval;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection string.
+ public JobStorageHelper(string connectionString)
+ {
+ this.StorageHelper = new StorageHelper(connectionString);
+ this.expiryInterval = TimeSpan.FromDays(Constants.Storage.ExpiryIntervalInDays);
+ }
+
+ ///
+ /// Gets the underlying storage helper.
+ ///
+ public IStorageHelper StorageHelper { get; }
+
+ ///
+ /// Uploads the job input.
+ ///
+ /// The job id.
+ /// The input.
+ /// Serialization protocol of the input to upload.
+ /// The cancellation token.
+ ///
+ /// Container uri + Input uri.
+ ///
+ public async Task<(string containerUri, string inputUri)> UploadJobInputAsync(
+ string jobId,
+ Stream input,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default)
+ {
+ string containerName = GetContainerName(jobId);
+ await this.StorageHelper.UploadBlobAsync(
+ containerName,
+ Constants.Storage.InputBlobName,
+ input,
+ protocol,
+ cancellationToken);
+
+ string containerUri = this.StorageHelper.GetBlobContainerSasUri(
+ containerName,
+ this.expiryInterval,
+ SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read);
+
+ string inputUri = this.StorageHelper.GetBlobSasUri(
+ containerName,
+ Constants.Storage.InputBlobName,
+ this.expiryInterval,
+ SharedAccessBlobPermissions.Read);
+
+ return (containerUri, inputUri);
+ }
+
+ ///
+ /// Uploads the job program output mapping.
+ ///
+ /// The job id.
+ /// The job program output mapping.
+ /// Serialization protocol of the mapping to upload.
+ /// The cancellation token.
+ /// Container uri + Mapping uri.
+ public async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync(
+ string jobId,
+ Stream mapping,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default)
+ {
+ string containerName = GetContainerName(jobId);
+ await this.StorageHelper.UploadBlobAsync(
+ containerName,
+ Constants.Storage.MappingBlobName,
+ mapping,
+ protocol,
+ cancellationToken);
+
+ string containerUri = this.StorageHelper.GetBlobContainerSasUri(
+ containerName,
+ this.expiryInterval,
+ SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read);
+
+ string mappingUri = this.StorageHelper.GetBlobSasUri(
+ containerName,
+ Constants.Storage.MappingBlobName,
+ this.expiryInterval,
+ SharedAccessBlobPermissions.Read);
+
+ return (containerUri, mappingUri);
+ }
+
+ ///
+ /// Downloads the job's execution output.
+ ///
+ /// The job id.
+ /// The destination stream.
+ /// The cancellation token.
+ /// Serialization protocol of the downloaded execution output.
+ public Task DownloadJobOutputAsync(
+ string jobId,
+ Stream destination,
+ CancellationToken cancellationToken = default)
+ {
+ string containerName = GetContainerName(jobId);
+ return this.StorageHelper.DownloadBlobAsync(
+ containerName,
+ "rawOutputData", // TODO: 14643
+ destination,
+ cancellationToken);
+ }
+
+ private static string GetContainerName(string jobId)
+ {
+ return Constants.Storage.ContainerNamePrefix + jobId.ToLowerInvariant();
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs
new file mode 100644
index 00000000000..350a97f0f10
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs
@@ -0,0 +1,144 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Bond;
+using Microsoft.WindowsAzure.Storage;
+using Microsoft.WindowsAzure.Storage.Blob;
+
+namespace Microsoft.Azure.Quantum.Storage
+{
+ internal class StorageHelper : IStorageHelper
+ {
+ private readonly string connectionString;
+ private readonly CloudStorageAccount storageAccount;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection string.
+ public StorageHelper(string connectionString)
+ {
+ this.connectionString = connectionString;
+ this.storageAccount = CloudStorageAccount.Parse(connectionString);
+ }
+
+ ///
+ /// Downloads the BLOB.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The destination.
+ /// The cancellation token.
+ /// Serialization protocol of the downloaded BLOB.
+ public async Task DownloadBlobAsync(
+ string containerName,
+ string blobName,
+ Stream destination,
+ CancellationToken cancellationToken = default)
+ {
+ BlobClient blob = await this.GetBlobClient(containerName, blobName, false, cancellationToken);
+ await blob.DownloadToAsync(destination, cancellationToken);
+ return ProtocolType.COMPACT_PROTOCOL;
+ }
+
+ ///
+ /// Uploads the BLOB.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The input.
+ /// Serialization protocol of the BLOB to upload.
+ /// The cancellation token.
+ /// Async task.
+ public async Task UploadBlobAsync(
+ string containerName,
+ string blobName,
+ Stream input,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default)
+ {
+ BlobClient blob = await this.GetBlobClient(containerName, blobName, true, cancellationToken);
+ await blob.UploadAsync(input, overwrite: true, cancellationToken);
+ }
+
+ ///
+ /// Gets the BLOB sas URI.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The expiry interval.
+ /// The permissions.
+ /// Blob uri.
+ public string GetBlobSasUri(
+ string containerName,
+ string blobName,
+ TimeSpan expiryInterval,
+ SharedAccessBlobPermissions permissions)
+ {
+ SharedAccessBlobPolicy adHocSAS = CreateSharedAccessBlobPolicy(expiryInterval, permissions);
+
+ CloudBlob blob = this.storageAccount
+ .CreateCloudBlobClient()
+ .GetContainerReference(containerName)
+ .GetBlobReference(blobName);
+
+ return blob.Uri + blob.GetSharedAccessSignature(adHocSAS);
+ }
+
+ ///
+ /// Gets the BLOB container sas URI.
+ ///
+ /// Name of the container.
+ /// The expiry interval.
+ /// The permissions.
+ /// Container uri.
+ public string GetBlobContainerSasUri(
+ string containerName,
+ TimeSpan expiryInterval,
+ SharedAccessBlobPermissions permissions)
+ {
+ SharedAccessBlobPolicy adHocPolicy = CreateSharedAccessBlobPolicy(expiryInterval, permissions);
+
+ // Generate the shared access signature on the container, setting the constraints directly on the signature.
+ CloudBlobContainer container = this.storageAccount.CreateCloudBlobClient().GetContainerReference(containerName);
+ return container.Uri + container.GetSharedAccessSignature(adHocPolicy, null);
+ }
+
+ private async Task GetBlobClient(
+ string containerName,
+ string blobName,
+ bool createContainer,
+ CancellationToken cancellationToken)
+ {
+ BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
+ BlobContainerClient blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName);
+
+ if (createContainer)
+ {
+ await blobContainerClient.CreateIfNotExistsAsync(PublicAccessType.Blob, cancellationToken: cancellationToken);
+ }
+
+ return blobContainerClient.GetBlobClient(blobName);
+ }
+
+ private static SharedAccessBlobPolicy CreateSharedAccessBlobPolicy(
+ TimeSpan expiryInterval,
+ SharedAccessBlobPermissions permissions)
+ {
+ return new SharedAccessBlobPolicy()
+ {
+ // When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
+ // Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
+ SharedAccessExpiryTime = DateTime.UtcNow.Add(expiryInterval),
+ Permissions = permissions,
+ };
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Utility/Constants.cs b/src/Azure/Azure.Quantum.Client/Utility/Constants.cs
new file mode 100644
index 00000000000..8dde31e9a76
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Utility/Constants.cs
@@ -0,0 +1,35 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+namespace Microsoft.Azure.Quantum.Utility
+{
+ internal static class Constants
+ {
+ internal const string DefaultBaseUri = "https://app-jobscheduler-prod.azurewebsites.net/";
+
+ internal static class Aad
+ {
+ internal const string ApplicationId = "84ba0947-6c53-4dd2-9ca9-b3694761521b";
+
+ // TODO: Confirm audience
+ internal const string Audience = "https://quantum.microsoft.com/Jobs.ReadWrite";
+
+ // Cache settings
+ internal const string CacheFileName = "msal_cache.dat";
+
+ // Mac Keychain settings
+ internal const string KeyChainServiceName = "msal_service";
+ internal const string KeyChainAccountName = "msal_account";
+ }
+
+ internal static class Storage
+ {
+ internal const string ContainerNamePrefix = "quantum-job-";
+ internal const string InputBlobName = "inputData";
+ internal const string MappingBlobName = "mappingData";
+ internal const string OutputBlobName = "outputData";
+ internal const int ExpiryIntervalInDays = 14;
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Utility/Ensure.cs b/src/Azure/Azure.Quantum.Client/Utility/Ensure.cs
new file mode 100644
index 00000000000..d9045d37790
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Utility/Ensure.cs
@@ -0,0 +1,40 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+
+namespace Microsoft.Azure.Quantum.Utility
+{
+ ///
+ /// Validation class.
+ ///
+ internal static class Ensure
+ {
+ ///
+ /// Ensures not null or whitespace.
+ ///
+ /// The value.
+ /// The name.
+ public static void NotNullOrWhiteSpace(string value, string name)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new ArgumentException(name);
+ }
+ }
+
+ ///
+ /// Ensures not null.
+ ///
+ /// The value.
+ /// The name.
+ public static void NotNull(object value, string name)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(name);
+ }
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Utility/LazyAsync.cs b/src/Azure/Azure.Quantum.Client/Utility/LazyAsync.cs
new file mode 100644
index 00000000000..99af6446af0
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Utility/LazyAsync.cs
@@ -0,0 +1,44 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Based on https://gist.github.com/johnazariah/ab269f7e005d538ed706b7a9cdb15bf1
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace Microsoft.Azure.Quantum.Utility
+{
+ internal sealed class LazyAsync
+ {
+ private readonly Lazy> instance;
+ private readonly Lazy valueL;
+
+ ///
+ /// Constructor for use with synchronous factories
+ ///
+ public LazyAsync(Func synchronousFactory)
+ : this(new Lazy>(() => Task.Run(synchronousFactory)))
+ {
+ }
+
+ ///
+ /// Constructor for use with asynchronous factories
+ ///
+ public LazyAsync(Func> asynchronousFactory)
+ : this(new Lazy>(() => asynchronousFactory()))
+ {
+ }
+
+ // private constructor which sets both fields
+ private LazyAsync(Lazy> instance)
+ {
+ this.instance = instance;
+ this.valueL = new Lazy(() => this.instance.Value.GetAwaiter().GetResult());
+ }
+
+ public T Value => valueL.Value;
+
+ public TaskAwaiter GetAwaiter() => instance.Value.GetAwaiter();
+ }
+}
\ No newline at end of file
diff --git a/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs
new file mode 100644
index 00000000000..74fd4d11463
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs
@@ -0,0 +1,136 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// JobsOperations operations.
+ ///
+ public partial interface IJobsOperations
+ {
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task>> ListWithHttpMessagesAsync(Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ ///
+ /// Get job by id
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task> GetWithHttpMessagesAsync(string jobId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ ///
+ /// Create a job.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task> PutWithHttpMessagesAsync(string jobId, JobDetails jobDefinition, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ ///
+ /// Delete a job.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task> DeleteWithHttpMessagesAsync(string jobId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task>> ListNextWithHttpMessagesAsync(string nextPageLink, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs
new file mode 100644
index 00000000000..2cc635ca7c8
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs
@@ -0,0 +1,68 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// ProvidersOperations operations.
+ ///
+ public partial interface IProvidersOperations
+ {
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task>> GetStatusWithHttpMessagesAsync(Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ ///
+ /// The headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ Task>> GetStatusNextWithHttpMessagesAsync(string nextPageLink, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs
new file mode 100644
index 00000000000..f4ae50f1a37
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs
@@ -0,0 +1,89 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using Newtonsoft.Json;
+
+ ///
+ /// Azure Quantum REST API client
+ ///
+ public partial interface IQuantumClient : System.IDisposable
+ {
+ ///
+ /// The base URI of the service.
+ ///
+ System.Uri BaseUri { get; set; }
+
+ ///
+ /// Gets or sets json serialization settings.
+ ///
+ JsonSerializerSettings SerializationSettings { get; }
+
+ ///
+ /// Gets or sets json deserialization settings.
+ ///
+ JsonSerializerSettings DeserializationSettings { get; }
+
+ ///
+ /// Credentials needed for the client to connect to Azure.
+ ///
+ ServiceClientCredentials Credentials { get; }
+
+ ///
+ /// The Azure subscription ID. This is a GUID-formatted string (e.g.
+ /// 00000000-0000-0000-0000-000000000000)
+ ///
+ string SubscriptionId { get; set; }
+
+ ///
+ /// Name of an Azure resource group.
+ ///
+ string ResourceGroupName { get; set; }
+
+ ///
+ /// Name of the workspace.
+ ///
+ string WorkspaceName { get; set; }
+
+ ///
+ /// The preferred language for the response.
+ ///
+ string AcceptLanguage { get; set; }
+
+ ///
+ /// The retry timeout in seconds for Long Running Operations. Default
+ /// value is 30.
+ ///
+ int? LongRunningOperationRetryTimeout { get; set; }
+
+ ///
+ /// Whether a unique x-ms-client-request-id should be generated. When
+ /// set to true a unique x-ms-client-request-id value is generated and
+ /// included in each request. Default is true.
+ ///
+ bool? GenerateClientRequestId { get; set; }
+
+
+ ///
+ /// Gets the IJobsOperations.
+ ///
+ IJobsOperations Jobs { get; }
+
+ ///
+ /// Gets the IProvidersOperations.
+ ///
+ IProvidersOperations Providers { get; }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs
new file mode 100644
index 00000000000..81697920294
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs
@@ -0,0 +1,994 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using Newtonsoft.Json;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Http;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// JobsOperations operations.
+ ///
+ internal partial class JobsOperations : IServiceOperations, IJobsOperations
+ {
+ ///
+ /// Initializes a new instance of the JobsOperations class.
+ ///
+ ///
+ /// Reference to the service client.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ internal JobsOperations(QuantumClient client)
+ {
+ if (client == null)
+ {
+ throw new System.ArgumentNullException("client");
+ }
+ Client = client;
+ }
+
+ ///
+ /// Gets a reference to the QuantumClient
+ ///
+ public QuantumClient Client { get; private set; }
+
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task>> ListWithHttpMessagesAsync(Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (Client.SubscriptionId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId");
+ }
+ if (Client.ResourceGroupName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ResourceGroupName");
+ }
+ if (Client.WorkspaceName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.WorkspaceName");
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "List", tracingParameters);
+ }
+ // Construct URL
+ var _baseUrl = Client.BaseUri.AbsoluteUri;
+ var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs").ToString();
+ _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId));
+ _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(Client.ResourceGroupName));
+ _url = _url.Replace("{workspaceName}", System.Uri.EscapeDataString(Client.WorkspaceName));
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("GET");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200)
+ {
+ var ex = new CloudException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ CloudError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex = new CloudException(_errorBody.Message);
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ ex.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse>();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ ///
+ /// Get job by id
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task> GetWithHttpMessagesAsync(string jobId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (Client.SubscriptionId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId");
+ }
+ if (Client.ResourceGroupName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ResourceGroupName");
+ }
+ if (Client.WorkspaceName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.WorkspaceName");
+ }
+ if (jobId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "jobId");
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("jobId", jobId);
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "Get", tracingParameters);
+ }
+ // Construct URL
+ var _baseUrl = Client.BaseUri.AbsoluteUri;
+ var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}").ToString();
+ _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId));
+ _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(Client.ResourceGroupName));
+ _url = _url.Replace("{workspaceName}", System.Uri.EscapeDataString(Client.WorkspaceName));
+ _url = _url.Replace("{jobId}", System.Uri.EscapeDataString(jobId));
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("GET");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200)
+ {
+ var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ ///
+ /// Create a job.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task> PutWithHttpMessagesAsync(string jobId, JobDetails jobDefinition, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (Client.SubscriptionId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId");
+ }
+ if (Client.ResourceGroupName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ResourceGroupName");
+ }
+ if (Client.WorkspaceName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.WorkspaceName");
+ }
+ if (jobId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "jobId");
+ }
+ if (jobDefinition == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "jobDefinition");
+ }
+ if (jobDefinition != null)
+ {
+ jobDefinition.Validate();
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("jobId", jobId);
+ tracingParameters.Add("jobDefinition", jobDefinition);
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "Put", tracingParameters);
+ }
+ // Construct URL
+ var _baseUrl = Client.BaseUri.AbsoluteUri;
+ var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}").ToString();
+ _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId));
+ _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(Client.ResourceGroupName));
+ _url = _url.Replace("{workspaceName}", System.Uri.EscapeDataString(Client.WorkspaceName));
+ _url = _url.Replace("{jobId}", System.Uri.EscapeDataString(jobId));
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("PUT");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ if(jobDefinition != null)
+ {
+ _requestContent = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(jobDefinition, Client.SerializationSettings);
+ _httpRequest.Content = new StringContent(_requestContent, System.Text.Encoding.UTF8);
+ _httpRequest.Content.Headers.ContentType =System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
+ }
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200 && (int)_statusCode != 201)
+ {
+ var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 201)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ ///
+ /// Delete a job.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task> DeleteWithHttpMessagesAsync(string jobId, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (Client.SubscriptionId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId");
+ }
+ if (Client.ResourceGroupName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ResourceGroupName");
+ }
+ if (Client.WorkspaceName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.WorkspaceName");
+ }
+ if (jobId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "jobId");
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("jobId", jobId);
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "Delete", tracingParameters);
+ }
+ // Construct URL
+ var _baseUrl = Client.BaseUri.AbsoluteUri;
+ var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/jobs/{jobId}").ToString();
+ _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId));
+ _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(Client.ResourceGroupName));
+ _url = _url.Replace("{workspaceName}", System.Uri.EscapeDataString(Client.WorkspaceName));
+ _url = _url.Replace("{jobId}", System.Uri.EscapeDataString(jobId));
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("DELETE");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200 && (int)_statusCode != 204)
+ {
+ var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task>> ListNextWithHttpMessagesAsync(string nextPageLink, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (nextPageLink == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "nextPageLink");
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("nextPageLink", nextPageLink);
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "ListNext", tracingParameters);
+ }
+ // Construct URL
+ string _url = "{nextLink}";
+ _url = _url.Replace("{nextLink}", nextPageLink);
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("GET");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200)
+ {
+ var ex = new CloudException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ CloudError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex = new CloudException(_errorBody.Message);
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ ex.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse>();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs
new file mode 100644
index 00000000000..bfec9488a12
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs
@@ -0,0 +1,193 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// Extension methods for JobsOperations.
+ ///
+ public static partial class JobsOperationsExtensions
+ {
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ public static IPage List(this IJobsOperations operations)
+ {
+ return operations.ListAsync().GetAwaiter().GetResult();
+ }
+
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task> ListAsync(this IJobsOperations operations, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.ListWithHttpMessagesAsync(null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ ///
+ /// Get job by id
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ public static JobDetails Get(this IJobsOperations operations, string jobId)
+ {
+ return operations.GetAsync(jobId).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Get job by id
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task GetAsync(this IJobsOperations operations, string jobId, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.GetWithHttpMessagesAsync(jobId, null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ ///
+ /// Create a job.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ ///
+ public static JobDetails Put(this IJobsOperations operations, string jobId, JobDetails jobDefinition)
+ {
+ return operations.PutAsync(jobId, jobDefinition).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Create a job.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task PutAsync(this IJobsOperations operations, string jobId, JobDetails jobDefinition, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.PutWithHttpMessagesAsync(jobId, jobDefinition, null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ ///
+ /// Delete a job.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ public static JobDetails Delete(this IJobsOperations operations, string jobId)
+ {
+ return operations.DeleteAsync(jobId).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Delete a job.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// Id of the job.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task DeleteAsync(this IJobsOperations operations, string jobId, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.DeleteWithHttpMessagesAsync(jobId, null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ public static IPage ListNext(this IJobsOperations operations, string nextPageLink)
+ {
+ return operations.ListNextAsync(nextPageLink).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// List jobs.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task> ListNextAsync(this IJobsOperations operations, string nextPageLink, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.ListNextWithHttpMessagesAsync(nextPageLink, null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs
new file mode 100644
index 00000000000..82627baecd0
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs
@@ -0,0 +1,233 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client.Models
+{
+ using Microsoft.Rest;
+ using Newtonsoft.Json;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ ///
+ /// Job details.
+ ///
+ public partial class JobDetails
+ {
+ ///
+ /// Initializes a new instance of the JobDetails class.
+ ///
+ public JobDetails()
+ {
+ CustomInit();
+ }
+
+ ///
+ /// Initializes a new instance of the JobDetails class.
+ ///
+ /// The blob container SAS uri, the
+ /// container is used to host job data.
+ /// The format of the input data.
+ /// The unique identifier for the
+ /// provider.
+ /// The target identifier to run the job.
+ /// The job id.
+ /// The job name. Is not required for the name to be
+ /// unique and it's only used for display purposes.
+ /// The input blob SAS uri, if specified, it
+ /// will override the default input blob in the container.
+ /// The input parameters for the job. JSON
+ /// object used by the target solver. It is expected that the size of
+ /// this object is small and only used to specify parameters for the
+ /// execution target, not the input data.
+ /// The job metadata. Metadata provides client
+ /// the ability to store client-specific information
+ /// The output blob SAS uri. When a job
+ /// finishes successfully, results will be uploaded to this
+ /// blob.
+ /// The format of the output
+ /// data.
+ /// The job status. Possible values include:
+ /// 'Waiting', 'Executing', 'Succeeded', 'Failed', 'Cancelled'
+ /// The creation time of the job.
+ /// The time when the job began
+ /// execution.
+ /// The time when the job finished
+ /// execution.
+ /// The time when a job was successfully
+ /// cancelled.
+ /// The error data for the job. This is
+ /// expected only when Status 'Failed'.
+ public JobDetails(string containerUri, string inputDataFormat, string providerId, string target, string id = default(string), string name = default(string), string inputDataUri = default(string), object inputParams = default(object), IDictionary metadata = default(IDictionary), string outputDataUri = default(string), string outputDataFormat = default(string), string status = default(string), string creationTime = default(string), string beginExecutionTime = default(string), string endExecutionTime = default(string), string cancellationTime = default(string), RestError errorData = default(RestError))
+ {
+ Id = id;
+ Name = name;
+ ContainerUri = containerUri;
+ InputDataUri = inputDataUri;
+ InputDataFormat = inputDataFormat;
+ InputParams = inputParams;
+ ProviderId = providerId;
+ Target = target;
+ Metadata = metadata;
+ OutputDataUri = outputDataUri;
+ OutputDataFormat = outputDataFormat;
+ Status = status;
+ CreationTime = creationTime;
+ BeginExecutionTime = beginExecutionTime;
+ EndExecutionTime = endExecutionTime;
+ CancellationTime = cancellationTime;
+ ErrorData = errorData;
+ CustomInit();
+ }
+
+ ///
+ /// An initialization method that performs custom operations like setting defaults
+ ///
+ partial void CustomInit();
+
+ ///
+ /// Gets or sets the job id.
+ ///
+ [JsonProperty(PropertyName = "id")]
+ public string Id { get; set; }
+
+ ///
+ /// Gets or sets the job name. Is not required for the name to be
+ /// unique and it's only used for display purposes.
+ ///
+ [JsonProperty(PropertyName = "name")]
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the blob container SAS uri, the container is used to
+ /// host job data.
+ ///
+ [JsonProperty(PropertyName = "containerUri")]
+ public string ContainerUri { get; set; }
+
+ ///
+ /// Gets or sets the input blob SAS uri, if specified, it will override
+ /// the default input blob in the container.
+ ///
+ [JsonProperty(PropertyName = "inputDataUri")]
+ public string InputDataUri { get; set; }
+
+ ///
+ /// Gets or sets the format of the input data.
+ ///
+ [JsonProperty(PropertyName = "inputDataFormat")]
+ public string InputDataFormat { get; set; }
+
+ ///
+ /// Gets or sets the input parameters for the job. JSON object used by
+ /// the target solver. It is expected that the size of this object is
+ /// small and only used to specify parameters for the execution target,
+ /// not the input data.
+ ///
+ [JsonProperty(PropertyName = "inputParams")]
+ public object InputParams { get; set; }
+
+ ///
+ /// Gets or sets the unique identifier for the provider.
+ ///
+ [JsonProperty(PropertyName = "providerId")]
+ public string ProviderId { get; set; }
+
+ ///
+ /// Gets or sets the target identifier to run the job.
+ ///
+ [JsonProperty(PropertyName = "target")]
+ public string Target { get; set; }
+
+ ///
+ /// Gets or sets the job metadata. Metadata provides client the ability
+ /// to store client-specific information
+ ///
+ [JsonProperty(PropertyName = "metadata")]
+ public IDictionary Metadata { get; set; }
+
+ ///
+ /// Gets or sets the output blob SAS uri. When a job finishes
+ /// successfully, results will be uploaded to this blob.
+ ///
+ [JsonProperty(PropertyName = "outputDataUri")]
+ public string OutputDataUri { get; set; }
+
+ ///
+ /// Gets or sets the format of the output data.
+ ///
+ [JsonProperty(PropertyName = "outputDataFormat")]
+ public string OutputDataFormat { get; set; }
+
+ ///
+ /// Gets the job status. Possible values include: 'Waiting',
+ /// 'Executing', 'Succeeded', 'Failed', 'Cancelled'
+ ///
+ [JsonProperty(PropertyName = "status")]
+ public string Status { get; private set; }
+
+ ///
+ /// Gets the creation time of the job.
+ ///
+ [JsonProperty(PropertyName = "creationTime")]
+ public string CreationTime { get; private set; }
+
+ ///
+ /// Gets the time when the job began execution.
+ ///
+ [JsonProperty(PropertyName = "beginExecutionTime")]
+ public string BeginExecutionTime { get; private set; }
+
+ ///
+ /// Gets the time when the job finished execution.
+ ///
+ [JsonProperty(PropertyName = "endExecutionTime")]
+ public string EndExecutionTime { get; private set; }
+
+ ///
+ /// Gets the time when a job was successfully cancelled.
+ ///
+ [JsonProperty(PropertyName = "cancellationTime")]
+ public string CancellationTime { get; private set; }
+
+ ///
+ /// Gets the error data for the job. This is expected only when Status
+ /// 'Failed'.
+ ///
+ [JsonProperty(PropertyName = "errorData")]
+ public RestError ErrorData { get; private set; }
+
+ ///
+ /// Validate the object.
+ ///
+ ///
+ /// Thrown if validation fails
+ ///
+ public virtual void Validate()
+ {
+ if (ContainerUri == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "ContainerUri");
+ }
+ if (InputDataFormat == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "InputDataFormat");
+ }
+ if (ProviderId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "ProviderId");
+ }
+ if (Target == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "Target");
+ }
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs b/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs
new file mode 100644
index 00000000000..7ab5d320626
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs
@@ -0,0 +1,53 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client.Models
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Newtonsoft.Json;
+ using System.Collections;
+ using System.Collections.Generic;
+
+ ///
+ /// Defines a page in Azure responses.
+ ///
+ /// Type of the page content items
+ [JsonObject]
+ public class Page : IPage
+ {
+ ///
+ /// Gets the link to the next page.
+ ///
+ [JsonProperty("nextLink")]
+ public string NextPageLink { get; private set; }
+
+ [JsonProperty("value")]
+ internal IList Items { get; set; }
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ /// A an enumerator that can be used to iterate through the collection.
+ public IEnumerator GetEnumerator()
+ {
+ return Items == null ? System.Linq.Enumerable.Empty().GetEnumerator() : Items.GetEnumerator();
+ }
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ /// A an enumerator that can be used to iterate through the collection.
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs b/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs
new file mode 100644
index 00000000000..43baf39b445
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs
@@ -0,0 +1,69 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client.Models
+{
+ using Newtonsoft.Json;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ ///
+ /// Providers status.
+ ///
+ public partial class ProviderStatus
+ {
+ ///
+ /// Initializes a new instance of the ProviderStatus class.
+ ///
+ public ProviderStatus()
+ {
+ CustomInit();
+ }
+
+ ///
+ /// Initializes a new instance of the ProviderStatus class.
+ ///
+ /// Provider id.
+ /// Provider availability. Possible
+ /// values include: 'Available', 'Degraded', 'Unavailable'
+ public ProviderStatus(string id = default(string), string currentAvailability = default(string), IList targets = default(IList))
+ {
+ Id = id;
+ CurrentAvailability = currentAvailability;
+ Targets = targets;
+ CustomInit();
+ }
+
+ ///
+ /// An initialization method that performs custom operations like setting defaults
+ ///
+ partial void CustomInit();
+
+ ///
+ /// Gets provider id.
+ ///
+ [JsonProperty(PropertyName = "id")]
+ public string Id { get; private set; }
+
+ ///
+ /// Gets provider availability. Possible values include: 'Available',
+ /// 'Degraded', 'Unavailable'
+ ///
+ [JsonProperty(PropertyName = "currentAvailability")]
+ public string CurrentAvailability { get; private set; }
+
+ ///
+ ///
+ [JsonProperty(PropertyName = "targets")]
+ public IList Targets { get; private set; }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs
new file mode 100644
index 00000000000..4917d841e8e
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs
@@ -0,0 +1,66 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client.Models
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Serialization;
+ using Newtonsoft.Json;
+ using System.Linq;
+
+ ///
+ /// An Error response.
+ ///
+ [JsonTransformation]
+ public partial class RestError
+ {
+ ///
+ /// Initializes a new instance of the RestError class.
+ ///
+ public RestError()
+ {
+ CustomInit();
+ }
+
+ ///
+ /// Initializes a new instance of the RestError class.
+ ///
+ /// An identifier for the error. Codes are invariant
+ /// and are intended to be consumed programmatically.
+ /// A message describing the error, intended to
+ /// be suitable for displaying in a user interface.
+ public RestError(string code = default(string), string message = default(string))
+ {
+ Code = code;
+ Message = message;
+ CustomInit();
+ }
+
+ ///
+ /// An initialization method that performs custom operations like setting defaults
+ ///
+ partial void CustomInit();
+
+ ///
+ /// Gets or sets an identifier for the error. Codes are invariant and
+ /// are intended to be consumed programmatically.
+ ///
+ [JsonProperty(PropertyName = "error.code")]
+ public string Code { get; set; }
+
+ ///
+ /// Gets or sets a message describing the error, intended to be
+ /// suitable for displaying in a user interface.
+ ///
+ [JsonProperty(PropertyName = "error.message")]
+ public string Message { get; set; }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs
new file mode 100644
index 00000000000..cb5804185a0
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs
@@ -0,0 +1,61 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client.Models
+{
+ using Microsoft.Rest;
+
+ ///
+ /// Exception thrown for an invalid response with RestError information.
+ ///
+ public partial class RestErrorException : RestException
+ {
+ ///
+ /// Gets information about the associated HTTP request.
+ ///
+ public HttpRequestMessageWrapper Request { get; set; }
+
+ ///
+ /// Gets information about the associated HTTP response.
+ ///
+ public HttpResponseMessageWrapper Response { get; set; }
+
+ ///
+ /// Gets or sets the body object.
+ ///
+ public RestError Body { get; set; }
+
+ ///
+ /// Initializes a new instance of the RestErrorException class.
+ ///
+ public RestErrorException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the RestErrorException class.
+ ///
+ /// The exception message.
+ public RestErrorException(string message)
+ : this(message, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the RestErrorException class.
+ ///
+ /// The exception message.
+ /// Inner exception.
+ public RestErrorException(string message, System.Exception innerException)
+ : base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs b/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs
new file mode 100644
index 00000000000..78c150b3c95
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs
@@ -0,0 +1,79 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client.Models
+{
+ using Newtonsoft.Json;
+ using System.Linq;
+
+ ///
+ /// Target status.
+ ///
+ public partial class TargetStatus
+ {
+ ///
+ /// Initializes a new instance of the TargetStatus class.
+ ///
+ public TargetStatus()
+ {
+ CustomInit();
+ }
+
+ ///
+ /// Initializes a new instance of the TargetStatus class.
+ ///
+ /// Target id.
+ /// Target availability. Possible
+ /// values include: 'Available', 'Degraded', 'Unavailable'
+ /// Average queue time in
+ /// seconds.
+ /// A page with detailed status of the
+ /// provider.
+ public TargetStatus(string id = default(string), string currentAvailability = default(string), long? averageQueueTime = default(long?), string statusPage = default(string))
+ {
+ Id = id;
+ CurrentAvailability = currentAvailability;
+ AverageQueueTime = averageQueueTime;
+ StatusPage = statusPage;
+ CustomInit();
+ }
+
+ ///
+ /// An initialization method that performs custom operations like setting defaults
+ ///
+ partial void CustomInit();
+
+ ///
+ /// Gets target id.
+ ///
+ [JsonProperty(PropertyName = "id")]
+ public string Id { get; private set; }
+
+ ///
+ /// Gets target availability. Possible values include: 'Available',
+ /// 'Degraded', 'Unavailable'
+ ///
+ [JsonProperty(PropertyName = "currentAvailability")]
+ public string CurrentAvailability { get; private set; }
+
+ ///
+ /// Gets average queue time in seconds.
+ ///
+ [JsonProperty(PropertyName = "averageQueueTime")]
+ public long? AverageQueueTime { get; private set; }
+
+ ///
+ /// Gets a page with detailed status of the provider.
+ ///
+ [JsonProperty(PropertyName = "statusPage")]
+ public string StatusPage { get; private set; }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs
new file mode 100644
index 00000000000..625e3d0457b
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs
@@ -0,0 +1,397 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using Newtonsoft.Json;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Http;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// ProvidersOperations operations.
+ ///
+ internal partial class ProvidersOperations : IServiceOperations, IProvidersOperations
+ {
+ ///
+ /// Initializes a new instance of the ProvidersOperations class.
+ ///
+ ///
+ /// Reference to the service client.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ internal ProvidersOperations(QuantumClient client)
+ {
+ if (client == null)
+ {
+ throw new System.ArgumentNullException("client");
+ }
+ Client = client;
+ }
+
+ ///
+ /// Gets a reference to the QuantumClient
+ ///
+ public QuantumClient Client { get; private set; }
+
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task>> GetStatusWithHttpMessagesAsync(Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (Client.SubscriptionId == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId");
+ }
+ if (Client.ResourceGroupName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ResourceGroupName");
+ }
+ if (Client.WorkspaceName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.WorkspaceName");
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "GetStatus", tracingParameters);
+ }
+ // Construct URL
+ var _baseUrl = Client.BaseUri.AbsoluteUri;
+ var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/providerStatus").ToString();
+ _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId));
+ _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(Client.ResourceGroupName));
+ _url = _url.Replace("{workspaceName}", System.Uri.EscapeDataString(Client.WorkspaceName));
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("GET");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200)
+ {
+ var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse>();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ ///
+ /// Headers that will be added to request.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ ///
+ /// Thrown when the operation returned an invalid status code
+ ///
+ ///
+ /// Thrown when unable to deserialize the response
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ ///
+ /// A response object containing the response body and response headers.
+ ///
+ public async Task>> GetStatusNextWithHttpMessagesAsync(string nextPageLink, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (nextPageLink == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "nextPageLink");
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("nextPageLink", nextPageLink);
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "GetStatusNext", tracingParameters);
+ }
+ // Construct URL
+ string _url = "{nextLink}";
+ _url = _url.Replace("{nextLink}", nextPageLink);
+ List _queryParameters = new List();
+ if (_queryParameters.Count > 0)
+ {
+ _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters);
+ }
+ // Create HTTP transport objects
+ var _httpRequest = new HttpRequestMessage();
+ HttpResponseMessage _httpResponse = null;
+ _httpRequest.Method = new HttpMethod("GET");
+ _httpRequest.RequestUri = new System.Uri(_url);
+ // Set Headers
+ if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value)
+ {
+ _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString());
+ }
+ if (Client.AcceptLanguage != null)
+ {
+ if (_httpRequest.Headers.Contains("accept-language"))
+ {
+ _httpRequest.Headers.Remove("accept-language");
+ }
+ _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage);
+ }
+
+
+ if (customHeaders != null)
+ {
+ foreach(var _header in customHeaders)
+ {
+ if (_httpRequest.Headers.Contains(_header.Key))
+ {
+ _httpRequest.Headers.Remove(_header.Key);
+ }
+ _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value);
+ }
+ }
+
+ // Serialize Request
+ string _requestContent = null;
+ // Set Credentials
+ if (Client.Credentials != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ }
+ // Send Request
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.SendRequest(_invocationId, _httpRequest);
+ }
+ cancellationToken.ThrowIfCancellationRequested();
+ _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse);
+ }
+ HttpStatusCode _statusCode = _httpResponse.StatusCode;
+ cancellationToken.ThrowIfCancellationRequested();
+ string _responseContent = null;
+ if ((int)_statusCode != 200)
+ {
+ var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ if (_errorBody != null)
+ {
+ ex.Body = _errorBody;
+ }
+ }
+ catch (JsonException)
+ {
+ // Ignore the exception
+ }
+ ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent);
+ ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent);
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Error(_invocationId, ex);
+ }
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw ex;
+ }
+ // Create Result
+ var _result = new AzureOperationResponse>();
+ _result.Request = _httpRequest;
+ _result.Response = _httpResponse;
+ if (_httpResponse.Headers.Contains("x-ms-request-id"))
+ {
+ _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault();
+ }
+ // Deserialize Response
+ if ((int)_statusCode == 200)
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ try
+ {
+ _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ }
+ catch (JsonException ex)
+ {
+ _httpRequest.Dispose();
+ if (_httpResponse != null)
+ {
+ _httpResponse.Dispose();
+ }
+ throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
+ }
+ }
+ if (_shouldTrace)
+ {
+ ServiceClientTracing.Exit(_invocationId, _result);
+ }
+ return _result;
+ }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs
new file mode 100644
index 00000000000..649d483f64a
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs
@@ -0,0 +1,87 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// Extension methods for ProvidersOperations.
+ ///
+ public static partial class ProvidersOperationsExtensions
+ {
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ public static IPage GetStatus(this IProvidersOperations operations)
+ {
+ return operations.GetStatusAsync().GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task> GetStatusAsync(this IProvidersOperations operations, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.GetStatusWithHttpMessagesAsync(null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ public static IPage GetStatusNext(this IProvidersOperations operations, string nextPageLink)
+ {
+ return operations.GetStatusNextAsync(nextPageLink).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Get provider status.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ /// The NextLink from the previous successful call to List operation.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task> GetStatusNextAsync(this IProvidersOperations operations, string nextPageLink, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.GetStatusNextWithHttpMessagesAsync(nextPageLink, null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs
new file mode 100644
index 00000000000..3d193cee37a
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs
@@ -0,0 +1,371 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+//
+// Code generated by Microsoft (R) AutoRest Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is
+// regenerated.
+//
+
+namespace Microsoft.Azure.Quantum.Client
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Microsoft.Rest.Serialization;
+ using Models;
+ using Newtonsoft.Json;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Http;
+
+ ///
+ /// Azure Quantum REST API client
+ ///
+ public partial class QuantumClient : ServiceClient, IQuantumClient, IAzureClient
+ {
+ ///
+ /// The base URI of the service.
+ ///
+ public System.Uri BaseUri { get; set; }
+
+ ///
+ /// Gets or sets json serialization settings.
+ ///
+ public JsonSerializerSettings SerializationSettings { get; private set; }
+
+ ///
+ /// Gets or sets json deserialization settings.
+ ///
+ public JsonSerializerSettings DeserializationSettings { get; private set; }
+
+ ///
+ /// Credentials needed for the client to connect to Azure.
+ ///
+ public ServiceClientCredentials Credentials { get; private set; }
+
+ ///
+ /// The Azure subscription ID. This is a GUID-formatted string (e.g.
+ /// 00000000-0000-0000-0000-000000000000)
+ ///
+ public string SubscriptionId { get; set; }
+
+ ///
+ /// Name of an Azure resource group.
+ ///
+ public string ResourceGroupName { get; set; }
+
+ ///
+ /// Name of the workspace.
+ ///
+ public string WorkspaceName { get; set; }
+
+ ///
+ /// The preferred language for the response.
+ ///
+ public string AcceptLanguage { get; set; }
+
+ ///
+ /// The retry timeout in seconds for Long Running Operations. Default value is
+ /// 30.
+ ///
+ public int? LongRunningOperationRetryTimeout { get; set; }
+
+ ///
+ /// Whether a unique x-ms-client-request-id should be generated. When set to
+ /// true a unique x-ms-client-request-id value is generated and included in
+ /// each request. Default is true.
+ ///
+ public bool? GenerateClientRequestId { get; set; }
+
+ ///
+ /// Gets the IJobsOperations.
+ ///
+ public virtual IJobsOperations Jobs { get; private set; }
+
+ ///
+ /// Gets the IProvidersOperations.
+ ///
+ public virtual IProvidersOperations Providers { get; private set; }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// HttpClient to be used
+ ///
+ ///
+ /// True: will dispose the provided httpClient on calling QuantumClient.Dispose(). False: will not dispose provided httpClient
+ internal QuantumClient(HttpClient httpClient, bool disposeHttpClient) : base(httpClient, disposeHttpClient)
+ {
+ Initialize();
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ protected QuantumClient(params DelegatingHandler[] handlers) : base(handlers)
+ {
+ Initialize();
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Optional. The http client handler used to handle http transport.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ internal QuantumClient(HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : base(rootHandler, handlers)
+ {
+ Initialize();
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Optional. The base URI of the service.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ protected QuantumClient(System.Uri baseUri, params DelegatingHandler[] handlers) : this(handlers)
+ {
+ if (baseUri == null)
+ {
+ throw new System.ArgumentNullException("baseUri");
+ }
+ BaseUri = baseUri;
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Optional. The base URI of the service.
+ ///
+ ///
+ /// Optional. The http client handler used to handle http transport.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ protected QuantumClient(System.Uri baseUri, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers)
+ {
+ if (baseUri == null)
+ {
+ throw new System.ArgumentNullException("baseUri");
+ }
+ BaseUri = baseUri;
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Required. Credentials needed for the client to connect to Azure.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ public QuantumClient(ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : this(handlers)
+ {
+ if (credentials == null)
+ {
+ throw new System.ArgumentNullException("credentials");
+ }
+ Credentials = credentials;
+ if (Credentials != null)
+ {
+ Credentials.InitializeServiceClient(this);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Required. Credentials needed for the client to connect to Azure.
+ ///
+ ///
+ /// HttpClient to be used
+ ///
+ ///
+ /// True: will dispose the provided httpClient on calling QuantumClient.Dispose(). False: will not dispose provided httpClient
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ public QuantumClient(ServiceClientCredentials credentials, HttpClient httpClient, bool disposeHttpClient) : this(httpClient, disposeHttpClient)
+ {
+ if (credentials == null)
+ {
+ throw new System.ArgumentNullException("credentials");
+ }
+ Credentials = credentials;
+ if (Credentials != null)
+ {
+ Credentials.InitializeServiceClient(this);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Required. Credentials needed for the client to connect to Azure.
+ ///
+ ///
+ /// Optional. The http client handler used to handle http transport.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ public QuantumClient(ServiceClientCredentials credentials, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers)
+ {
+ if (credentials == null)
+ {
+ throw new System.ArgumentNullException("credentials");
+ }
+ Credentials = credentials;
+ if (Credentials != null)
+ {
+ Credentials.InitializeServiceClient(this);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Optional. The base URI of the service.
+ ///
+ ///
+ /// Required. Credentials needed for the client to connect to Azure.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ public QuantumClient(System.Uri baseUri, ServiceClientCredentials credentials, params DelegatingHandler[] handlers) : this(handlers)
+ {
+ if (baseUri == null)
+ {
+ throw new System.ArgumentNullException("baseUri");
+ }
+ if (credentials == null)
+ {
+ throw new System.ArgumentNullException("credentials");
+ }
+ BaseUri = baseUri;
+ Credentials = credentials;
+ if (Credentials != null)
+ {
+ Credentials.InitializeServiceClient(this);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the QuantumClient class.
+ ///
+ ///
+ /// Optional. The base URI of the service.
+ ///
+ ///
+ /// Required. Credentials needed for the client to connect to Azure.
+ ///
+ ///
+ /// Optional. The http client handler used to handle http transport.
+ ///
+ ///
+ /// Optional. The delegating handlers to add to the http client pipeline.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ public QuantumClient(System.Uri baseUri, ServiceClientCredentials credentials, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : this(rootHandler, handlers)
+ {
+ if (baseUri == null)
+ {
+ throw new System.ArgumentNullException("baseUri");
+ }
+ if (credentials == null)
+ {
+ throw new System.ArgumentNullException("credentials");
+ }
+ BaseUri = baseUri;
+ Credentials = credentials;
+ if (Credentials != null)
+ {
+ Credentials.InitializeServiceClient(this);
+ }
+ }
+
+ ///
+ /// An optional partial-method to perform custom initialization.
+ ///
+ partial void CustomInitialize();
+ ///
+ /// Initializes client properties.
+ ///
+ private void Initialize()
+ {
+ Jobs = new JobsOperations(this);
+ Providers = new ProvidersOperations(this);
+ BaseUri = new System.Uri("https://app-jobscheduler-prod.azurewebsites.net");
+ AcceptLanguage = "en-US";
+ LongRunningOperationRetryTimeout = 30;
+ GenerateClientRequestId = true;
+ SerializationSettings = new JsonSerializerSettings
+ {
+ Formatting = Newtonsoft.Json.Formatting.Indented,
+ DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat,
+ DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc,
+ NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
+ ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize,
+ ContractResolver = new ReadOnlyJsonContractResolver(),
+ Converters = new List
+ {
+ new Iso8601TimeSpanConverter()
+ }
+ };
+ SerializationSettings.Converters.Add(new TransformationJsonConverter());
+ DeserializationSettings = new JsonSerializerSettings
+ {
+ DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat,
+ DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc,
+ NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
+ ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize,
+ ContractResolver = new ReadOnlyJsonContractResolver(),
+ Converters = new List
+ {
+ new Iso8601TimeSpanConverter()
+ }
+ };
+ CustomInitialize();
+ DeserializationSettings.Converters.Add(new TransformationJsonConverter());
+ DeserializationSettings.Converters.Add(new CloudErrorJsonConverter());
+ }
+ }
+}
diff --git a/src/Azure/Common/AssemblyCommon.props b/src/Azure/Common/AssemblyCommon.props
new file mode 100644
index 00000000000..79fb4f744d9
--- /dev/null
+++ b/src/Azure/Common/AssemblyCommon.props
@@ -0,0 +1,23 @@
+
+
+
+ Microsoft
+ Microsoft
+ Microsoft Quantum Development Kit Preview
+ © Microsoft Corporation. All rights reserved.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Azure/Common/DelaySign.cs b/src/Azure/Common/DelaySign.cs
new file mode 100644
index 00000000000..4d6d06f28ef
--- /dev/null
+++ b/src/Azure/Common/DelaySign.cs
@@ -0,0 +1,29 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Reflection;
+
+// Attributes for delay-signing
+#if SIGNED
+[assembly:AssemblyKeyFile("..\\..\\..\\Build\\267DevDivSNKey2048.snk")]
+[assembly:AssemblyDelaySign(true)]
+#endif
+
+internal static class DelaySign
+{
+#pragma warning disable SA1310 // Fields should not have underscore.
+#if SIGNED
+ public const string PUBLIC_KEY = ", PublicKey=" +
+ "002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1" +
+ "a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a2" +
+ "35e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b" +
+ "5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c" +
+ "8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f" +
+ "9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f3" +
+ "02d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd9" +
+ "11f0571aaf3d54da12b11ddec375b3";
+#else
+ public const string PUBLIC_KEY = "";
+#endif
+}
diff --git a/src/Azure/Common/StyleCop.ruleset b/src/Azure/Common/StyleCop.ruleset
new file mode 100644
index 00000000000..24532383c6b
--- /dev/null
+++ b/src/Azure/Common/StyleCop.ruleset
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Azure/Common/stylecop.json b/src/Azure/Common/stylecop.json
new file mode 100644
index 00000000000..79ab17994dd
--- /dev/null
+++ b/src/Azure/Common/stylecop.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "documentationRules": {
+ "companyName": "Microsoft Corporation"
+ },
+ "orderingRules": {
+ "usingDirectivesPlacement": "outsideNamespace"
+ }
+ }
+}