diff --git a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs
index a953436ceaa..f0c9300de19 100644
--- a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs
+++ b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs
@@ -9,7 +9,6 @@
using Microsoft.Azure.Quantum.Client;
using Microsoft.Azure.Quantum.Client.Models;
using Microsoft.Azure.Quantum.Exceptions;
-using Microsoft.Rest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
@@ -184,13 +183,13 @@ private static IWorkspace GetWorkspace()
workspaceName: TestConstants.WorkspaceName)
{
// Mock jobs client (only needed for unit tests)
- JobsClient = new QuantumClient(MockHelper.GetHttpClientMock(), true)
+ QuantumClient = new QuantumClient(MockHelper.GetHttpClientMock(), true)
{
SubscriptionId = TestConstants.SubscriptionId,
ResourceGroupName = TestConstants.ResourceGroupName,
WorkspaceName = TestConstants.WorkspaceName,
BaseUri = new Uri(TestConstants.Endpoint),
- }.Jobs,
+ },
};
}
diff --git a/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs b/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs
index 9e3bbc53d4a..5bef01d9787 100644
--- a/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs
+++ b/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs
@@ -1,10 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-using System;
-
namespace Microsoft.Azure.Quantum.Exceptions
{
+ using System;
+
///
/// The exception that is thrown when an error related to the Azure storage client occurs.
///
@@ -46,19 +46,16 @@ public StorageClientException(
/// Initializes a new instance of the class with a specified error message, a reference to another exception that caused this one and more detailes that are specific to the storage client.
///
/// Error message that explains the reason for the exception.
- /// Connection string used by the storage client.
/// Name of the container involved in the operation that caused the exception.
/// Name of the BLOB involved in the operation that caused the exception.
/// Exception that is the cause of the current one.
public StorageClientException(
string message,
- string connectionString,
string containerName,
string blobName,
Exception inner)
: base(
$"{BaseMessage}: {message}{Environment.NewLine}" +
- $"ConnectionString: {connectionString}{Environment.NewLine}" +
$"ContainerName: {containerName}{Environment.NewLine}" +
$"BlobName: {blobName}",
inner)
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs
index 9f3c54a7be8..746de8c57b1 100644
--- a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs
@@ -1,15 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-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
{
+ using System;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Microsoft.Azure.Quantum.Client.Models;
+ using Microsoft.Azure.Quantum.Utility;
+ using Microsoft.Quantum.Runtime;
+
///
/// Cloud job class.
///
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs
index 9ad313e8c8f..eaa2db3f1b2 100644
--- a/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs
@@ -50,5 +50,17 @@ Task GetJobAsync(
/// List of jobs
Task> ListJobsAsync(
CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets as SAS Uri for the storage account associated with the workspace.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The cancellation token.
+ /// Sas Uri.
+ Task GetSasUriAsync(
+ string containerName,
+ string blobName = null,
+ CancellationToken cancellationToken = default);
}
}
diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs
index 856b9dc6dca..c123010c18b 100644
--- a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs
+++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs
@@ -1,30 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-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.Exceptions;
-using Microsoft.Azure.Quantum.Utility;
-
namespace Microsoft.Azure.Quantum
{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using global::Azure.Core;
+ using Microsoft.Azure.Quantum.Authentication;
+ using Microsoft.Azure.Quantum.Client;
+ using Microsoft.Azure.Quantum.Client.Models;
+ using Microsoft.Azure.Quantum.Exceptions;
+ using Microsoft.Azure.Quantum.Utility;
+
///
/// Workspace class.
///
///
public class Workspace : IWorkspace
{
- private readonly Uri BaseUri;
- private readonly string ResourceGroupName;
- private readonly string SubscriptionId;
- private readonly string WorkspaceName;
+ private readonly Uri baseUri;
+ private readonly string resourceGroupName;
+ private readonly string subscriptionId;
+ private readonly string workspaceName;
///
/// Initializes a new instance of the class.
@@ -79,13 +79,13 @@ private Workspace(
IAccessTokenProvider accessTokenProvider,
Uri baseUri = null)
{
- BaseUri = baseUri ?? new Uri(Constants.DefaultBaseUri);
+ this.baseUri = baseUri ?? new Uri(Constants.DefaultBaseUri);
Ensure.NotNullOrWhiteSpace(subscriptionId, nameof(subscriptionId));
- SubscriptionId = subscriptionId;
+ this.subscriptionId = subscriptionId;
Ensure.NotNullOrWhiteSpace(resourceGroupName, nameof(resourceGroupName));
- ResourceGroupName = resourceGroupName;
+ this.resourceGroupName = resourceGroupName;
Ensure.NotNullOrWhiteSpace(workspaceName, nameof(workspaceName));
- WorkspaceName = workspaceName;
+ this.workspaceName = workspaceName;
try
{
@@ -100,13 +100,13 @@ private Workspace(
try
{
- this.JobsClient = new QuantumClient(new AuthorizationClientHandler(accessTokenProvider))
+ this.QuantumClient = new QuantumClient(new AuthorizationClientHandler(accessTokenProvider))
{
- BaseUri = BaseUri,
+ BaseUri = this.baseUri,
SubscriptionId = subscriptionId,
ResourceGroupName = resourceGroupName,
WorkspaceName = workspaceName,
- }.Jobs;
+ };
}
catch (Exception ex)
{
@@ -121,7 +121,7 @@ private Workspace(
///
/// The jobs client.
///
- internal IJobsOperations JobsClient { get; set; }
+ internal IQuantumClient QuantumClient { get; set; }
///
/// Submits the job.
@@ -140,7 +140,7 @@ public async Task SubmitJobAsync(
try
{
- JobDetails jobDetails = await this.JobsClient.PutAsync(
+ JobDetails jobDetails = await this.QuantumClient.Jobs.PutAsync(
jobId: jobDefinition.Details.Id,
jobDefinition: jobDefinition.Details,
cancellationToken: cancellationToken);
@@ -165,7 +165,7 @@ public async Task CancelJobAsync(string jobId, CancellationToken cance
try
{
- JobDetails jobDetails = await this.JobsClient.DeleteAsync(
+ JobDetails jobDetails = await this.QuantumClient.Jobs.DeleteAsync(
jobId: jobId,
cancellationToken: cancellationToken);
@@ -191,7 +191,7 @@ public async Task GetJobAsync(string jobId, CancellationToken cancella
try
{
- JobDetails jobDetails = await this.JobsClient.GetAsync(
+ JobDetails jobDetails = await this.QuantumClient.Jobs.GetAsync(
jobId: jobId,
cancellationToken: cancellationToken);
@@ -214,7 +214,7 @@ public async Task> ListJobsAsync(CancellationToken cancell
{
try
{
- var jobs = await this.JobsClient.ListAsync(
+ var jobs = await this.QuantumClient.Jobs.ListAsync(
cancellationToken: cancellationToken);
return jobs
@@ -226,6 +226,27 @@ public async Task> ListJobsAsync(CancellationToken cancell
}
}
+ ///
+ /// Gets as SAS Uri for the linked storage account.
+ ///
+ /// Name of the container.
+ /// Name of the BLOB.
+ /// The cancellation token.
+ ///
+ /// Sas Uri.
+ ///
+ public async Task GetSasUriAsync(string containerName, string blobName = null, CancellationToken cancellationToken = default)
+ {
+ BlobDetails details = new BlobDetails
+ {
+ ContainerName = containerName,
+ BlobName = blobName,
+ };
+
+ var response = await this.QuantumClient.Storage.SasUriAsync(details, cancellationToken);
+ return response.SasUri;
+ }
+
private WorkspaceClientException CreateException(
Exception inner,
string message,
@@ -233,10 +254,10 @@ private WorkspaceClientException CreateException(
{
return new WorkspaceClientException(
message,
- SubscriptionId,
- ResourceGroupName,
- WorkspaceName,
- BaseUri,
+ subscriptionId,
+ resourceGroupName,
+ workspaceName,
+ baseUri,
jobId,
inner);
}
diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
index 94ab65f2368..fe7aa8a6184 100644
--- a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
+++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs
@@ -47,8 +47,8 @@ targetName is null
: (IQuantumMachine)Activator.CreateInstance(
machineType,
targetName,
- storageAccountConnectionString,
- workspace);
+ workspace,
+ storageAccountConnectionString);
}
}
}
\ No newline at end of file
diff --git a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs
index 6b8f937890f..d1e010f9e9e 100644
--- a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs
+++ b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs
@@ -1,27 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using Bond;
-using Microsoft.WindowsAzure.Storage.Blob;
-
namespace Microsoft.Azure.Quantum.Storage
{
+ using System;
+ using System.IO;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Bond;
+ using global::Azure.Storage.Blobs;
+ using Microsoft.WindowsAzure.Storage.Blob;
+
public interface IStorageHelper
{
///
/// Downloads the BLOB.
///
- /// Name of the container.
+ /// Container client.
/// Name of the BLOB.
/// The destination.
/// The cancellation token.
/// Serialization protocol of the downloaded BLOB.
Task DownloadBlobAsync(
- string containerName,
+ BlobContainerClient containerClient,
string blobName,
Stream destination,
CancellationToken cancellationToken = default);
@@ -29,14 +30,14 @@ Task DownloadBlobAsync(
///
/// Uploads the BLOB.
///
- /// Name of the container.
+ /// Container client.
/// Name of the BLOB.
/// The input.
/// Serialization protocol of the BLOB to upload.
/// The cancellation token.
/// async task.
Task UploadBlobAsync(
- string containerName,
+ BlobContainerClient containerClient,
string blobName,
Stream input,
ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
@@ -45,12 +46,14 @@ Task UploadBlobAsync(
///
/// Gets the BLOB sas URI.
///
+ /// Storage account connection string.
/// Name of the container.
/// Name of the BLOB.
/// The expiry interval.
/// The permissions.
/// Blob uri.
string GetBlobSasUri(
+ string connectionString,
string containerName,
string blobName,
TimeSpan expiryInterval,
@@ -59,11 +62,13 @@ string GetBlobSasUri(
///
/// Gets the BLOB container sas URI.
///
+ /// Storage account connection string.
/// Name of the container.
/// The expiry interval.
/// The permissions.
/// Container uri.
string GetBlobContainerSasUri(
+ string connectionString,
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
index 17fc10a7103..4898e24c6db 100644
--- a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs
+++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs
@@ -1,19 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-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
+ using System;
+ using System.IO;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Bond;
+ using global::Azure.Storage.Blobs;
+ using Microsoft.Azure.Quantum.Exceptions;
+ using Microsoft.Azure.Quantum.Utility;
+ using Microsoft.WindowsAzure.Storage;
+ using Microsoft.WindowsAzure.Storage.Blob;
+
+ public class JobStorageHelper : JobStorageHelperBase
{
- private readonly TimeSpan expiryInterval;
+ private readonly string connectionString;
///
/// Initializes a new instance of the class.
@@ -21,14 +24,19 @@ public class JobStorageHelper : IJobStorageHelper
/// The connection string.
public JobStorageHelper(string connectionString)
{
- this.StorageHelper = new StorageHelper(connectionString);
- this.expiryInterval = TimeSpan.FromDays(Constants.Storage.ExpiryIntervalInDays);
- }
+ this.connectionString = connectionString;
- ///
- /// Gets the underlying storage helper.
- ///
- public IStorageHelper StorageHelper { get; }
+ try
+ {
+ _ = CloudStorageAccount.Parse(connectionString);
+ }
+ catch (Exception ex)
+ {
+ throw new StorageClientException(
+ "An error related to the cloud storage account occurred",
+ ex);
+ }
+ }
///
/// Uploads the job input.
@@ -40,29 +48,34 @@ public JobStorageHelper(string connectionString)
///
/// Container uri + Input uri.
///
- public async Task<(string containerUri, string inputUri)> UploadJobInputAsync(
+ public override async Task<(string containerUri, string inputUri)> UploadJobInputAsync(
string jobId,
Stream input,
ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
CancellationToken cancellationToken = default)
{
string containerName = GetContainerName(jobId);
+
+ BlobContainerClient containerClient = await this.GetContainerClient(containerName);
+
await this.StorageHelper.UploadBlobAsync(
- containerName,
+ containerClient,
Constants.Storage.InputBlobName,
input,
protocol,
cancellationToken);
string containerUri = this.StorageHelper.GetBlobContainerSasUri(
+ this.connectionString,
containerName,
- this.expiryInterval,
+ this.ExpiryInterval,
SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read);
string inputUri = this.StorageHelper.GetBlobSasUri(
+ this.connectionString,
containerName,
Constants.Storage.InputBlobName,
- this.expiryInterval,
+ this.ExpiryInterval,
SharedAccessBlobPermissions.Read);
return (containerUri, inputUri);
@@ -76,57 +89,42 @@ await this.StorageHelper.UploadBlobAsync(
/// Serialization protocol of the mapping to upload.
/// The cancellation token.
/// Container uri + Mapping uri.
- public async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync(
+ public override async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync(
string jobId,
Stream mapping,
ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
CancellationToken cancellationToken = default)
{
string containerName = GetContainerName(jobId);
+ BlobContainerClient containerClient = await this.GetContainerClient(containerName);
+
await this.StorageHelper.UploadBlobAsync(
- containerName,
+ containerClient,
Constants.Storage.MappingBlobName,
mapping,
protocol,
cancellationToken);
string containerUri = this.StorageHelper.GetBlobContainerSasUri(
+ this.connectionString,
containerName,
- this.expiryInterval,
+ this.ExpiryInterval,
SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read);
string mappingUri = this.StorageHelper.GetBlobSasUri(
+ this.connectionString,
containerName,
Constants.Storage.MappingBlobName,
- this.expiryInterval,
+ 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)
+ protected override Task GetContainerClient(string containerName, CancellationToken cancellationToken = default)
{
- return Constants.Storage.ContainerNamePrefix + jobId.ToLowerInvariant();
+ BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
+ return Task.FromResult(blobServiceClient.GetBlobContainerClient(containerName));
}
}
}
diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs
new file mode 100644
index 00000000000..29f1c232016
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs
@@ -0,0 +1,98 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace Microsoft.Azure.Quantum.Storage
+{
+ using System;
+ using System.IO;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Bond;
+ using global::Azure.Storage.Blobs;
+ using Microsoft.Azure.Quantum.Utility;
+
+ public abstract class JobStorageHelperBase : IJobStorageHelper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JobStorageHelperBase()
+ {
+ this.StorageHelper = new StorageHelper();
+ this.ExpiryInterval = TimeSpan.FromDays(Constants.Storage.ExpiryIntervalInDays);
+ }
+
+ ///
+ /// Gets the underlying storage helper.
+ ///
+ public IStorageHelper StorageHelper { get; }
+
+ ///
+ /// Gets the expiry interval.
+ ///
+ protected TimeSpan ExpiryInterval { get; private set; }
+
+ ///
+ /// Downloads the job's execution output.
+ ///
+ /// The job id.
+ /// The destination stream.
+ /// The cancellation token.
+ /// Serialization protocol of the downloaded execution output.
+ public async Task DownloadJobOutputAsync(
+ string jobId,
+ Stream destination,
+ CancellationToken cancellationToken = default)
+ {
+ string containerName = GetContainerName(jobId);
+ BlobContainerClient containerClient = await this.GetContainerClient(containerName);
+
+ return await this.StorageHelper.DownloadBlobAsync(
+ containerClient,
+ "rawOutputData", // TODO: 14643
+ destination,
+ cancellationToken);
+ }
+
+ ///
+ /// Uploads the job input.
+ ///
+ /// The job id.
+ /// The input.
+ /// Serialization protocol of the input to upload.
+ /// The cancellation token.
+ /// Container uri + Input uri.
+ public abstract 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.
+ public abstract Task<(string containerUri, string mappingUri)> UploadJobMappingAsync(
+ string jobId,
+ Stream mapping,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets the container client.
+ ///
+ /// Name of the container.
+ /// Cancellation token.
+ /// Container client.
+ protected abstract Task GetContainerClient(string containerName, CancellationToken cancellationToken = default);
+
+ protected static string GetContainerName(string jobId)
+ {
+ return Constants.Storage.ContainerNamePrefix + jobId.ToLowerInvariant();
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs
new file mode 100644
index 00000000000..4d6dba0334c
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs
@@ -0,0 +1,107 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace Microsoft.Azure.Quantum.Storage
+{
+ using System;
+ using System.IO;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Bond;
+ using global::Azure.Storage.Blobs;
+ using Microsoft.Azure.Quantum.Utility;
+
+ public class LinkedStorageJobHelper : JobStorageHelperBase
+ {
+ private readonly IWorkspace workspace;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The workspace.
+ public LinkedStorageJobHelper(IWorkspace workspace)
+ {
+ this.workspace = workspace;
+ }
+
+ ///
+ /// Uploads the job input.
+ ///
+ /// The job id.
+ /// The input.
+ /// Serialization protocol of the input to upload.
+ /// The cancellation token.
+ ///
+ /// Container uri + Input uri without SAS.
+ ///
+ public override async Task<(string containerUri, string inputUri)> UploadJobInputAsync(
+ string jobId,
+ Stream input,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default)
+ {
+ string containerName = GetContainerName(jobId);
+
+ BlobContainerClient containerClient = await this.GetContainerClient(containerName);
+
+ await this.StorageHelper.UploadBlobAsync(
+ containerClient,
+ Constants.Storage.InputBlobName,
+ input,
+ protocol,
+ cancellationToken);
+
+ Uri inputUri = containerClient
+ .GetBlobClient(Constants.Storage.InputBlobName)
+ .Uri;
+
+ return (GetUriPath(containerClient.Uri), GetUriPath(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 without SAS.
+ public override async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync(
+ string jobId,
+ Stream mapping,
+ ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
+ CancellationToken cancellationToken = default)
+ {
+ string containerName = GetContainerName(jobId);
+ BlobContainerClient containerClient = await this.GetContainerClient(containerName);
+
+ await this.StorageHelper.UploadBlobAsync(
+ containerClient,
+ Constants.Storage.MappingBlobName,
+ mapping,
+ protocol,
+ cancellationToken);
+
+ Uri mappingUri = containerClient
+ .GetBlobClient(Constants.Storage.MappingBlobName)
+ .Uri;
+
+ return (GetUriPath(containerClient.Uri), GetUriPath(mappingUri));
+ }
+
+ protected override async Task GetContainerClient(string containerName, CancellationToken cancellationToken = default)
+ {
+ // Calls the service to get a container SAS Uri
+ var containerUri = await this.workspace.GetSasUriAsync(
+ containerName: containerName,
+ cancellationToken: cancellationToken);
+
+ return new BlobContainerClient(new Uri(containerUri));
+ }
+
+ private string GetUriPath(Uri uri)
+ {
+ return uri.GetLeftPart(UriPartial.Path);
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs
index ac97887a266..e3ee0787da2 100644
--- a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs
+++ b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs
@@ -1,64 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-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.Azure.Quantum.Exceptions;
-using Microsoft.WindowsAzure.Storage;
-using Microsoft.WindowsAzure.Storage.Blob;
-
namespace Microsoft.Azure.Quantum.Storage
{
+ using System;
+ using System.IO;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Bond;
+ using global::Azure.Storage.Blobs;
+ using global::Azure.Storage.Blobs.Models;
+ using Microsoft.Azure.Quantum.Exceptions;
+ using Microsoft.WindowsAzure.Storage;
+ using Microsoft.WindowsAzure.Storage.Blob;
+
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;
-
- try
- {
- this.storageAccount = CloudStorageAccount.Parse(connectionString);
- }
- catch (Exception ex)
- {
- throw CreateException(ex, "An error related to the cloud storage account occurred");
- }
- }
-
///
/// Downloads the BLOB.
///
- /// Name of the container.
+ /// Container client.
/// Name of the BLOB.
/// The destination.
/// The cancellation token.
/// Serialization protocol of the downloaded BLOB.
public async Task DownloadBlobAsync(
- string containerName,
+ BlobContainerClient containerClient,
string blobName,
Stream destination,
CancellationToken cancellationToken = default)
{
try
{
- BlobClient blob = await this.GetBlobClient(containerName, blobName, false, cancellationToken);
+ BlobClient blob = containerClient.GetBlobClient(blobName);
await blob.DownloadToAsync(destination, cancellationToken);
}
catch (Exception ex)
{
- throw CreateException(ex, "Could not download BLOB", containerName, blobName);
+ throw CreateException(ex, "Could not download BLOB", containerClient.Name, blobName);
}
return ProtocolType.COMPACT_PROTOCOL;
@@ -67,14 +46,14 @@ public async Task DownloadBlobAsync(
///
/// Uploads the BLOB.
///
- /// Name of the container.
+ /// Container client.
/// Name of the BLOB.
/// The input.
/// Serialization protocol of the BLOB to upload.
/// The cancellation token.
/// Async task.
public async Task UploadBlobAsync(
- string containerName,
+ BlobContainerClient containerClient,
string blobName,
Stream input,
ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL,
@@ -82,24 +61,30 @@ public async Task UploadBlobAsync(
{
try
{
- BlobClient blob = await this.GetBlobClient(containerName, blobName, true, cancellationToken);
+ // Ensure container is created
+ await containerClient.CreateIfNotExistsAsync(PublicAccessType.Blob, cancellationToken: cancellationToken);
+
+ // Upload blob
+ BlobClient blob = containerClient.GetBlobClient(blobName);
await blob.UploadAsync(input, overwrite: true, cancellationToken);
}
catch (Exception ex)
{
- throw CreateException(ex, "Could not upload BLOB", containerName, blobName);
+ throw CreateException(ex, "Could not upload BLOB", containerClient.Name, blobName);
}
}
///
/// Gets the BLOB sas URI.
///
+ /// Storage account connection string.
/// Name of the container.
/// Name of the BLOB.
/// The expiry interval.
/// The permissions.
/// Blob uri.
public string GetBlobSasUri(
+ string connectionString,
string containerName,
string blobName,
TimeSpan expiryInterval,
@@ -109,7 +94,8 @@ public string GetBlobSasUri(
{
SharedAccessBlobPolicy adHocSAS = CreateSharedAccessBlobPolicy(expiryInterval, permissions);
- CloudBlob blob = this.storageAccount
+ CloudBlob blob = CloudStorageAccount
+ .Parse(connectionString)
.CreateCloudBlobClient()
.GetContainerReference(containerName)
.GetBlobReference(blobName);
@@ -125,11 +111,13 @@ public string GetBlobSasUri(
///
/// Gets the BLOB container sas URI.
///
+ /// Storage account connection string.
/// Name of the container.
/// The expiry interval.
/// The permissions.
/// Container uri.
public string GetBlobContainerSasUri(
+ string connectionString,
string containerName,
TimeSpan expiryInterval,
SharedAccessBlobPermissions permissions)
@@ -139,7 +127,10 @@ public string GetBlobContainerSasUri(
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);
+ CloudBlobContainer container = CloudStorageAccount
+ .Parse(connectionString)
+ .CreateCloudBlobClient().GetContainerReference(containerName);
+
return container.Uri + container.GetSharedAccessSignature(adHocPolicy, null);
}
catch (Exception ex)
@@ -156,29 +147,11 @@ private StorageClientException CreateException (
{
return new StorageClientException(
message,
- connectionString,
containerName,
blobName,
inner);
}
- 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)
diff --git a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs
index f4ae50f1a37..db391fa0911 100644
--- a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs
+++ b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs
@@ -85,5 +85,10 @@ public partial interface IQuantumClient : System.IDisposable
///
IProvidersOperations Providers { get; }
+ ///
+ /// Gets the IStorageOperations.
+ ///
+ IStorageOperations Storage { get; }
+
}
}
diff --git a/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs
new file mode 100644
index 00000000000..4010389be24
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs
@@ -0,0 +1,50 @@
+//
+// 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;
+
+ ///
+ /// StorageOperations operations.
+ ///
+ public partial interface IStorageOperations
+ {
+ ///
+ /// Gets a URL with SAS token for a container/blob in the storage
+ /// account associated with the workspace. The SAS URL can be used to
+ /// upload job input and/or download job output.
+ ///
+ ///
+ ///
+ ///
+ /// 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> SasUriWithHttpMessagesAsync(BlobDetails blobDetails, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs
index 81697920294..cf7e04ca42a 100644
--- a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs
+++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs
@@ -169,7 +169,7 @@ internal JobsOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- CloudError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ CloudError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex = new CloudException(_errorBody.Message);
@@ -211,7 +211,7 @@ internal JobsOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
@@ -358,7 +358,7 @@ internal JobsOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex.Body = _errorBody;
@@ -395,7 +395,7 @@ internal JobsOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
@@ -529,7 +529,7 @@ internal JobsOperations(QuantumClient client)
string _requestContent = null;
if(jobDefinition != null)
{
- _requestContent = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(jobDefinition, Client.SerializationSettings);
+ _requestContent = 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");
}
@@ -559,7 +559,7 @@ internal JobsOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex.Body = _errorBody;
@@ -596,7 +596,7 @@ internal JobsOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
@@ -614,7 +614,7 @@ internal JobsOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
@@ -761,7 +761,7 @@ internal JobsOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex.Body = _errorBody;
@@ -798,7 +798,7 @@ internal JobsOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
@@ -929,7 +929,7 @@ internal JobsOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- CloudError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ CloudError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex = new CloudException(_errorBody.Message);
@@ -971,7 +971,7 @@ internal JobsOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs
new file mode 100644
index 00000000000..6698af8a001
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs
@@ -0,0 +1,73 @@
+//
+// 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.Linq;
+
+ ///
+ /// Blob details.
+ ///
+ public partial class BlobDetails
+ {
+ ///
+ /// Initializes a new instance of the BlobDetails class.
+ ///
+ public BlobDetails()
+ {
+ CustomInit();
+ }
+
+ ///
+ /// Initializes a new instance of the BlobDetails class.
+ ///
+ /// The container name.
+ /// The blob name.
+ public BlobDetails(string containerName, string blobName = default(string))
+ {
+ ContainerName = containerName;
+ BlobName = blobName;
+ CustomInit();
+ }
+
+ ///
+ /// An initialization method that performs custom operations like setting defaults
+ ///
+ partial void CustomInit();
+
+ ///
+ /// Gets or sets the container name.
+ ///
+ [JsonProperty(PropertyName = "containerName")]
+ public string ContainerName { get; set; }
+
+ ///
+ /// Gets or sets the blob name.
+ ///
+ [JsonProperty(PropertyName = "blobName")]
+ public string BlobName { get; set; }
+
+ ///
+ /// Validate the object.
+ ///
+ ///
+ /// Thrown if validation fails
+ ///
+ public virtual void Validate()
+ {
+ if (ContainerName == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "ContainerName");
+ }
+ }
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs
index 4917d841e8e..466b3737fa8 100644
--- a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs
@@ -18,7 +18,7 @@ namespace Microsoft.Azure.Quantum.Client.Models
///
/// An Error response.
///
- [JsonTransformation]
+ [Rest.Serialization.JsonTransformation]
public partial class RestError
{
///
diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs b/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs
new file mode 100644
index 00000000000..b811d2e06a6
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.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 Newtonsoft.Json;
+ using System.Linq;
+
+ ///
+ /// Get SAS URL operation response.
+ ///
+ public partial class SasUriResponse
+ {
+ ///
+ /// Initializes a new instance of the SasUriResponse class.
+ ///
+ public SasUriResponse()
+ {
+ CustomInit();
+ }
+
+ ///
+ /// Initializes a new instance of the SasUriResponse class.
+ ///
+ /// A URL with a SAS token to upload a blob for
+ /// execution in the given workspace.
+ public SasUriResponse(string sasUri = default(string))
+ {
+ SasUri = sasUri;
+ CustomInit();
+ }
+
+ ///
+ /// An initialization method that performs custom operations like setting defaults
+ ///
+ partial void CustomInit();
+
+ ///
+ /// Gets or sets a URL with a SAS token to upload a blob for execution
+ /// in the given workspace.
+ ///
+ [JsonProperty(PropertyName = "sasUri")]
+ public string SasUri { get; set; }
+
+ }
+}
diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs
index 625e3d0457b..9cf8af20c06 100644
--- a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs
+++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs
@@ -169,7 +169,7 @@ internal ProvidersOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex.Body = _errorBody;
@@ -206,7 +206,7 @@ internal ProvidersOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
@@ -337,7 +337,7 @@ internal ProvidersOperations(QuantumClient client)
try
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
- RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
+ RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings);
if (_errorBody != null)
{
ex.Body = _errorBody;
@@ -374,7 +374,7 @@ internal ProvidersOperations(QuantumClient client)
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
- _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
+ _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings);
}
catch (JsonException ex)
{
diff --git a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs
index 3d193cee37a..2fdcd086b3c 100644
--- a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs
+++ b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs
@@ -90,6 +90,11 @@ public partial class QuantumClient : ServiceClient, IQuantumClien
///
public virtual IProvidersOperations Providers { get; private set; }
+ ///
+ /// Gets the IStorageOperations.
+ ///
+ public virtual IStorageOperations Storage { get; private set; }
+
///
/// Initializes a new instance of the QuantumClient class.
///
@@ -333,6 +338,7 @@ private void Initialize()
{
Jobs = new JobsOperations(this);
Providers = new ProvidersOperations(this);
+ Storage = new StorageOperations(this);
BaseUri = new System.Uri("https://app-jobscheduler-prod.azurewebsites.net");
AcceptLanguage = "en-US";
LongRunningOperationRetryTimeout = 30;
diff --git a/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs
new file mode 100644
index 00000000000..38ac48aa70f
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs
@@ -0,0 +1,248 @@
+//
+// 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;
+
+ ///
+ /// StorageOperations operations.
+ ///
+ internal partial class StorageOperations : IServiceOperations, IStorageOperations
+ {
+ ///
+ /// Initializes a new instance of the StorageOperations class.
+ ///
+ ///
+ /// Reference to the service client.
+ ///
+ ///
+ /// Thrown when a required parameter is null
+ ///
+ internal StorageOperations(QuantumClient client)
+ {
+ if (client == null)
+ {
+ throw new System.ArgumentNullException("client");
+ }
+ Client = client;
+ }
+
+ ///
+ /// Gets a reference to the QuantumClient
+ ///
+ public QuantumClient Client { get; private set; }
+
+ ///
+ /// Gets a URL with SAS token for a container/blob in the storage account
+ /// associated with the workspace. The SAS URL can be used to upload job input
+ /// and/or download job output.
+ ///
+ ///
+ ///
+ ///
+ /// 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> SasUriWithHttpMessagesAsync(BlobDetails blobDetails, 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 (blobDetails == null)
+ {
+ throw new ValidationException(ValidationRules.CannotBeNull, "blobDetails");
+ }
+ if (blobDetails != null)
+ {
+ blobDetails.Validate();
+ }
+ // Tracing
+ bool _shouldTrace = ServiceClientTracing.IsEnabled;
+ string _invocationId = null;
+ if (_shouldTrace)
+ {
+ _invocationId = ServiceClientTracing.NextInvocationId.ToString();
+ Dictionary tracingParameters = new Dictionary();
+ tracingParameters.Add("blobDetails", blobDetails);
+ tracingParameters.Add("cancellationToken", cancellationToken);
+ ServiceClientTracing.Enter(_invocationId, this, "SasUri", 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}/storage/sasUri").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("POST");
+ _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(blobDetails != null)
+ {
+ _requestContent = Rest.Serialization.SafeJsonConvert.SerializeObject(blobDetails, 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)
+ {
+ var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode));
+ try
+ {
+ _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
+ RestError _errorBody = 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 = 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/StorageOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs
new file mode 100644
index 00000000000..ec883e16100
--- /dev/null
+++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.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
+{
+ using Microsoft.Rest;
+ using Microsoft.Rest.Azure;
+ using Models;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ ///
+ /// Extension methods for StorageOperations.
+ ///
+ public static partial class StorageOperationsExtensions
+ {
+ ///
+ /// Gets a URL with SAS token for a container/blob in the storage account
+ /// associated with the workspace. The SAS URL can be used to upload job input
+ /// and/or download job output.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ ///
+ public static SasUriResponse SasUri(this IStorageOperations operations, BlobDetails blobDetails)
+ {
+ return operations.SasUriAsync(blobDetails).GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Gets a URL with SAS token for a container/blob in the storage account
+ /// associated with the workspace. The SAS URL can be used to upload job input
+ /// and/or download job output.
+ ///
+ ///
+ /// The operations group for this extension method.
+ ///
+ ///
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public static async Task SasUriAsync(this IStorageOperations operations, BlobDetails blobDetails, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ using (var _result = await operations.SasUriWithHttpMessagesAsync(blobDetails, null, cancellationToken).ConfigureAwait(false))
+ {
+ return _result.Body;
+ }
+ }
+
+ }
+}