Commit 0174f227 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

[WIP] work on Azure integration



Since we'll submit the qir llvm file, it doesn't fit the traditional Accelerator API.
Just make a standalone app for testing.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 356a3e2f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19,3 +19,4 @@ endif()
#set_target_properties(qcor-mlir-tool
#                        PROPERTIES INSTALL_RPATH "${MLIR_INSTALL_DIR}/lib:${CMAKE_BINARY_DIR}/mlir/parsers/openqasm:${CMAKE_BINARY_DIR}/lib")
install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/qcor-mlir-tool DESTINATION bin)
add_subdirectory(azure)
 No newline at end of file
+7 −0
Original line number Diff line number Diff line
add_executable(azure-qir-tool azure-qir-tool.cpp)
target_include_directories(azure-qir-tool PUBLIC ${XACC_ROOT}/include ${XACC_ROOT}/include/xacc)
target_link_libraries(azure-qir-tool cpr curl)
target_link_directories(azure-qir-tool PRIVATE ${XACC_ROOT}/lib)
target_compile_features(azure-qir-tool
                        PUBLIC
                        cxx_std_17)
 No newline at end of file
+106 −0
Original line number Diff line number Diff line
#include <filesystem>
#include <fstream>
#include <iostream>
#include <json.hpp>
#include <regex>
#include "cpr/cpr.h"

namespace {
std::vector<std::string> split(const std::string &s, char delim) {
  std::vector<std::string> elems;
  std::stringstream ss(s);
  for (std::string item; std::getline(ss, item, delim);) {
    *(std::back_inserter(elems))++ = item;
  }
  return elems;
}

std::string trim(const std::string &str) {
  return std::regex_replace(str, std::regex("(^[ ]+)|([ ]+$)"), "");
}

std::string getBaseUrl(const std::string &region,
                       const std::string &subscriptionId,
                       const std::string &resourceGroup,
                       const std::string &workspaceName) {
  const auto formatRegion = [](const std::string &rawRegionString) {
    std::string regionString = rawRegionString;
    // e.g., East US -> eastus
    regionString.erase(
        std::remove_if(regionString.begin(), regionString.end(), isspace),
        regionString.end());
    std::transform(regionString.begin(), regionString.end(),
                   regionString.begin(), ::tolower);
    return regionString;
  };
  return "https://" + formatRegion(region) +
         ".quantum.azure.com/v1.0/subscriptions/" + subscriptionId +
         "/resourceGroups/" + resourceGroup +
         "/providers/Microsoft.Quantum/workspaces/" + workspaceName;
}

std::pair<std::string, std::string>
getConfigInfo(const std::string &configFilePath) {
  std::ifstream configFile(configFilePath);
  const std::string contents((std::istreambuf_iterator<char>(configFile)),
                             std::istreambuf_iterator<char>());
  const auto lines = split(contents, '\n');
  std::string token, location, subscriptionId, resourceGroup, workspaceName;
  for (const auto &line : lines) {
    if (line.find("key") != std::string::npos) {
      token = trim(split(line, ':')[1]);
    }
    if (line.find("Location") != std::string::npos) {
      location = trim(split(line, ':')[1]);
    }
    if (line.find("Resource ID") != std::string::npos) {
      const auto resourcePath = trim(split(line, ':')[1]);
      const auto components = split(resourcePath, '/');
      for (size_t i = 0; i < components.size(); ++i) {
        if (components[i] == "subscriptions") {
          subscriptionId = components[i + 1];
        }
        if (components[i] == "resourceGroups") {
          resourceGroup = components[i + 1];
        }
        if (components[i] == "Workspaces") {
          workspaceName = components[i + 1];
        }
      }
    }
  }
  assert(!token.empty());
  assert(!subscriptionId.empty());
  assert(!resourceGroup.empty());
  assert(!workspaceName.empty());
  assert(!location.empty());
  return std::make_pair(
      getBaseUrl(location, subscriptionId, resourceGroup, workspaceName),
      token);
}
} // namespace

int main(int argc, char **argv) {
  const std::string azureConfigFilename(std::string(getenv("HOME")) +
                                        "/.azure_config");
  if (std::filesystem::exists(azureConfigFilename)) {
    const auto [baseUrl, accessToken] = getConfigInfo(azureConfigFilename);
    std::cout << "baseUrl: " << baseUrl << std::endl;
    std::cout << "token: " << accessToken << std::endl;
    cpr::Header cprHeaders;
    cprHeaders.insert({"Content-type", "application/json"});
    cprHeaders.insert({"Connection", "keep-alive"});
    cprHeaders.insert({"Accept", "application/json"});
    cprHeaders.insert({"Authorization", "Bearer " + accessToken});
    // Testing: query provider status
    const std::string path = "/providerStatus";
    cpr::Parameters cprParams;
    auto r = cpr::Get(cpr::Url{baseUrl + path}, cprHeaders, cprParams,
                      cpr::VerifySsl(false));
    std::cout << "Response:" << r.text << "\n";
  } else {
    std::cerr << "Could not find Azure Quantum configuration file "
              << azureConfigFilename << "\n";
    return 1;
  }
}
 No newline at end of file