Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
9e776d9
Temporarily append build number to version number
Aug 30, 2022
81c1e53
Add new params
Sep 2, 2022
00df4e4
Splice in a new submit function, but keep using the old code for Q#
Sep 3, 2022
0f09895
Add TODO comment
Sep 3, 2022
a224fe8
Add logic for new parameter
Sep 7, 2022
eed7748
Merge branch 'main' into submit-jobs-directly-to-service
Sep 26, 2022
5148d68
Merge branch 'main' into submit-jobs-directly-to-service
Oct 10, 2022
7b50958
Merge main, plus job.py changes
Oct 14, 2022
15ce374
Merge branch 'main' into submit-jobs-directly-to-service
Oct 14, 2022
3a502f5
Temporarily add build number to version number
Oct 14, 2022
919a538
In _submit_qir, raise error if --job-input-source is omitted
Oct 14, 2022
f7066cb
Add help examples and more param validation logic
Oct 15, 2022
3e1e9ae
Add input file code
Oct 18, 2022
0d8648b
Add storage.py
Oct 18, 2022
43d4406
Fix Flake8 style rule violations
Oct 18, 2022
61251c6
Clean up some comments and add code for debugging
Oct 19, 2022
9d833e2
Add code to Upload QIR file and submit job
Oct 22, 2022
abf0656
Accept various input formats
Oct 27, 2022
8f6202d
Modify inputParams
Oct 28, 2022
80f0e86
Upload QIR bitcode
Oct 29, 2022
2d2317b
Add --entry-point parameter
Nov 1, 2022
76feb44
Remove commented-out code and unused parameters
Nov 1, 2022
5229192
Merge branch 'main' into submit-jobs-directly-to-service
Nov 1, 2022
599ac9e
Add storage account lookup
Nov 3, 2022
2666aaa
Add parameter defaults and consolidate test input files
Nov 3, 2022
01021fa
Fixed style-rule violations. Worked on tests.
Nov 4, 2022
b08b75a
Add azure-quantum to DEPENDENCIES
Nov 4, 2022
c571a97
Temporarily comment out code in QIR job submit test
Nov 8, 2022
e067a0a
Delete whitespace that Flake8 doesn't like
Nov 8, 2022
9276dab
Add code to submit QIO jobs
Nov 10, 2022
5c71985
Add code from QIO Quickstart notebook
Nov 11, 2022
65290da
Comment out solver call. Submit QIO like QIR.
Nov 15, 2022
96590c6
Add gzip compression for OIO input
Nov 15, 2022
e07577f
Clean up job parameters logic
Nov 15, 2022
84b0bd7
Remove QIO protobuf code. Add initial pass-through logic.
Nov 28, 2022
e131d28
Delete whitespace in blank lines to pass Static Analysis
Nov 28, 2022
c7e72d1
Merge branch 'main' into submit-jobs-directly-to-service
Dec 7, 2022
7d37cc4
Enable pass-through jobs
Dec 14, 2022
df6f9d1
Handle provider names containing dots
Dec 15, 2022
1a6c6cb
Format inputParams correctly for QIR, QIO, and pass-through jobs
Dec 19, 2022
beff23e
Remove qdk-python dependencies
Dec 19, 2022
10bd247
Replace license header in storage.py
Dec 19, 2022
f7e64fc
Add dependency on azure-storage-blob package
Dec 20, 2022
5edae46
Restore qdk-python (azure-quantum) storage dependency and remove expl…
Dec 21, 2022
69055f1
Add a stripped-down storage.py to this repo
Dec 22, 2022
ccd5d97
Convert count to an integer
Dec 23, 2022
d002f3b
Revise and delete comments
Jan 3, 2023
1a3c1d9
Never return a SAS token. Simplify container names.
Jan 4, 2023
a63179b
Handle upload errors
Jan 4, 2023
119f78f
Add get_provider function
Jan 5, 2023
39a97e3
Handle conversion errors from int(shots) and int(count)
Jan 6, 2023
7e75a31
Convert all numeric --job-params values from string to int or float
Jan 7, 2023
f500903
Add unit test for _convert_numeric_params
Jan 9, 2023
f0070af
Add support for tags and metadata
Jan 10, 2023
e219d89
Revise and delete comments
Jan 12, 2023
ff719a6
Merge branch 'main' into submit-jobs-directly-to-service
Jan 12, 2023
afb3f4c
Accept camelCase blob upload params
Jan 14, 2023
f8185ea
Add Quil and Qiskit tests
Jan 24, 2023
1285161
Supply correct default content-type for Rigetti QIR
Jan 24, 2023
c49c307
Correct typo in comment
Jan 24, 2023
b0c5262
Delete commented-out import statements
Jan 24, 2023
9f054dc
Require --job-input-format when --job-input-file is specified
Jan 24, 2023
9686b89
Add more error handling code
Jan 24, 2023
8357ae0
Add fix for Bug 50331
Jan 26, 2023
a8be909
Increment build number for bug bash wheel
Jan 26, 2023
9ab58ca
Make --entry-point required on QIR jobs
Jan 27, 2023
417e641
Delete commented-out code
Jan 27, 2023
1bbf823
Extend entry-point param validation to allow entryPoint in 'items' list
Jan 27, 2023
22952f4
Delete commented-out code
Jan 27, 2023
d9be1dc
Rename storage.py to _storage.py
Jan 27, 2023
c7af324
Increase min CLI core version to 2.41.0
Jan 31, 2023
3cf27dc
Restore version numbers in preparation for merge
Feb 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/quantum/azext_quantum/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
type: command
short-summary: Submit a job to run on Azure Quantum, and waits for the result.
examples:
- name: Submit the Q# program from the current folder and wait for the result.
- name: Submit a Q# program from the current folder and wait for the result.
text: |-
az quantum execute -g MyResourceGroup -w MyWorkspace -l MyLocation -t MyTarget
- name: Submit and wait for a Q# program from the current folder with job and program parameters.
Expand All @@ -32,7 +32,7 @@
type: command
short-summary: Equivalent to `az quantum execute`
examples:
- name: Submit the Q# program from the current folder and wait for the result.
- name: Submit a Q# program from the current folder and wait for the result.
text: |-
az quantum run -g MyResourceGroup -w MyWorkspace -l MyLocation -t MyTarget
- name: Submit and wait for a Q# program from the current folder with job and program parameters.
Expand Down Expand Up @@ -81,24 +81,29 @@

helps['quantum job submit'] = """
type: command
short-summary: Submit a Q# project to run on Azure Quantum.
short-summary: Submit a program or circuit to run on Azure Quantum.
examples:
- name: Submit the Q# program from the current folder.
- name: Submit a Q# program from the current folder.
text: |-
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
-t MyTarget --job-name MyJob
- name: Submit the Q# program from the current folder with job parameters for a target.
- name: Submit a Q# program from the current folder with job parameters for a target.
text: |-
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
-t MyTarget --job-name MyJob --job-params param1=value1 param2=value2
- name: Submit the Q# program with program parameters (e.g. n-qubits = 2).
- name: Submit a Q# program with program parameters (e.g. n-qubits = 2).
text: |-
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation \\
-t MyTarget --job-name MyJob -- --n-qubits=2
- name: Submit a Q# program from the current folder with a target-capability parameter.
text: |-
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation -t MyTarget \\
--target-capability MyTargetCapability
- name: Submit QIR bitcode from a file in the current folder.
text: |-
az quantum job submit -g MyResourceGroup -w MyWorkspace -l MyLocation -t MyTarget \\
--job-name MyJob --job-input-format qir.v1 --job-input-file MyQirBitcode.bc \\
--entry-point MyQirEntryPoint
"""

helps['quantum job wait'] = """
Expand Down
17 changes: 16 additions & 1 deletion src/quantum/azext_quantum/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
# pylint: disable=line-too-long,protected-access,no-self-use,too-many-statements

import argparse
import json
from knack.arguments import CLIArgumentType
from azure.cli.core.azclierror import InvalidArgumentValueError, CLIError
from azure.cli.core.util import shell_safe_json_parse
Expand Down Expand Up @@ -53,6 +52,10 @@ def load_arguments(self, _):
provider_sku_list_type = CLIArgumentType(options_list=['--provider-sku-list', '-r'], help='Comma separated list of Provider/SKU pairs. Separate the Provider and SKU with a slash. Enclose the entire list in quotes. Values from `az quantum offerings list -l <location> -o table`')
auto_accept_type = CLIArgumentType(help='If specified, provider terms are accepted without an interactive Y/N prompt.')
autoadd_only_type = CLIArgumentType(help='If specified, only the plans flagged "autoAdd" are displayed.')
job_input_file_type = CLIArgumentType(help='The location of the input file to submit. Required for QIR, QIO, and pass-through jobs. Ignored on Q# jobs.')
job_input_format_type = CLIArgumentType(help='The format of the file to submit. Omit this parameter on Q# jobs.')
job_output_format_type = CLIArgumentType(help='The expected job output format. Ignored on Q# jobs.')
entry_point_type = CLIArgumentType(help='The entry point for the QIR program or circuit. Required for QIR. Ignored on Q# jobs.')

with self.argument_context('quantum workspace') as c:
c.argument('workspace_name', workspace_name_type)
Expand Down Expand Up @@ -84,6 +87,10 @@ def load_arguments(self, _):
with self.argument_context('quantum job submit') as c:
c.argument('job_params', job_params_type)
c.argument('target_capability', target_capability_type)
c.argument('job_input_file', job_input_file_type)
c.argument('job_input_format', job_input_format_type)
c.argument('job_output_format', job_output_format_type)
c.argument('entry_point', entry_point_type)
c.positional('program_args', program_args_type)

with self.argument_context('quantum execute') as c:
Expand All @@ -96,6 +103,10 @@ def load_arguments(self, _):
c.argument('no_build', no_build_type)
c.argument('job_params', job_params_type)
c.argument('target_capability', target_capability_type)
c.argument('job_input_file', job_input_file_type)
c.argument('job_input_format', job_input_format_type)
c.argument('job_output_format', job_output_format_type)
c.argument('entry_point', entry_point_type)
c.positional('program_args', program_args_type)

with self.argument_context('quantum run') as c:
Expand All @@ -108,6 +119,10 @@ def load_arguments(self, _):
c.argument('no_build', no_build_type)
c.argument('job_params', job_params_type)
c.argument('target_capability', target_capability_type)
c.argument('job_input_file', job_input_file_type)
c.argument('job_input_format', job_input_format_type)
c.argument('job_output_format', job_output_format_type)
c.argument('entry_point', entry_point_type)
c.positional('program_args', program_args_type)

with self.argument_context('quantum offerings') as c:
Expand Down
116 changes: 116 additions & 0 deletions src/quantum/azext_quantum/_storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# This file is a reduced version of qdk-python\azure-quantum\azure\quantum\storage.py
# It only contains the functions required to do inputData blob upload for job submission.
# Other cosmetic changes were made to appease the Azure CLI CI/CD checks.

# Unused imports were removed to reduce Pylint style-rule violations.
import logging
from datetime import datetime, timedelta
from typing import Any
from azure.storage.blob import (
BlobServiceClient,
ContainerClient,
BlobClient,
BlobSasPermissions,
ContentSettings,
generate_blob_sas,
)

logger = logging.getLogger(__name__)


def create_container(
connection_string: str, container_name: str
) -> ContainerClient:
"""
Creates and initialize a container; returns the client needed to access it.
"""
blob_service_client = BlobServiceClient.from_connection_string(
connection_string
)
logger.info(
f'{"Initializing storage client for account:"}'
+ f"{blob_service_client.account_name}"
)

container_client = blob_service_client.get_container_client(container_name)
create_container_using_client(container_client)
return container_client


def create_container_using_client(container_client: ContainerClient):
"""
Creates the container if it doesn't already exist.
"""
if not container_client.exists():
logger.debug(
f'{" - uploading to **new** container:"}'
f"{container_client.container_name}"
)
container_client.create_container()


def upload_blob(
container: ContainerClient,
blob_name: str,
content_type: str,
content_encoding: str,
data: Any,
return_sas_token: bool = True,
) -> str:
"""
Uploads the given data to a blob record.
If a blob with the given name already exist, it throws an error.

Returns a uri with a SAS token to access the newly created blob.
"""
create_container_using_client(container)
logger.info(
f"Uploading blob '{blob_name}'"
+ f"to container '{container.container_name}'"
+ f"on account: '{container.account_name}'"
)

content_settings = ContentSettings(
content_type=content_type, content_encoding=content_encoding
)

blob = container.get_blob_client(blob_name)

blob.upload_blob(data, content_settings=content_settings)
logger.debug(f" - blob '{blob_name}' uploaded. generating sas token.")

if return_sas_token:
uri = get_blob_uri_with_sas_token(blob)
else:
uri = remove_sas_token(blob.url)
logger.debug(f" - blob access url: '{uri}'.")

return uri


def get_blob_uri_with_sas_token(blob: BlobClient):
"""Returns a URI for the given blob that contains a SAS Token"""
sas_token = generate_blob_sas(
blob.account_name,
blob.container_name,
blob.blob_name,
account_key=blob.credential.account_key,
permission=BlobSasPermissions(read=True),
expiry=datetime.utcnow() + timedelta(days=14),
)

return blob.url + "?" + sas_token


def remove_sas_token(sas_uri: str) -> str:
"""Removes the SAS Token from the given URI if it contains one"""
index = sas_uri.find("?")
if index != -1:
sas_uri = sas_uri[0:index]

return sas_uri
2 changes: 1 addition & 1 deletion src/quantum/azext_quantum/azext_metadata.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"azext.isPreview": true,
"azext.minCliCoreVersion": "2.23.0"
"azext.minCliCoreVersion": "2.41.0"
}
Loading