-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #292 from Learnware-LAMDA/offline_check
feat(backend): verify learnware offline
- Loading branch information
Showing
16 changed files
with
443 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from kubernetes import client, config, utils | ||
import yaml | ||
import time | ||
import shortuuid | ||
import os | ||
|
||
|
||
def run_check(env_path, learnware_path, checker_name): | ||
config.load_incluster_config() | ||
|
||
k8s_client = client.ApiClient() | ||
v1 = client.CoreV1Api() | ||
|
||
template_file = os.path.join("learnware-check.yaml") | ||
with open(template_file) as fin: | ||
template_content = fin.read() | ||
pass | ||
|
||
current_pod_name = os.environ["HOSTNAME"] | ||
current_pod_image = v1.read_namespaced_pod(name=current_pod_name, namespace="learnware").spec.containers[0].image | ||
|
||
pod_name = str(shortuuid.uuid()).lower() | ||
template_content = template_content.replace("{{NAME}}", pod_name) | ||
template_content = template_content.replace("{{LEARNWARE_PATH}}", learnware_path) | ||
template_content = template_content.replace("{{CHECKER_NAME}}", checker_name) | ||
template_content = template_content.replace("{{ENV_PATH}}", env_path) | ||
template_content = template_content.replace("{{IMAGE}}", current_pod_image) | ||
|
||
template_dict = yaml.safe_load(template_content) | ||
|
||
pod = utils.create_from_dict(k8s_client, template_dict)[0] | ||
|
||
# wait for pod end | ||
while True: | ||
pod = v1.read_namespaced_pod(name=pod.metadata.name, namespace="learnware") | ||
print(f"Pod status: {pod.status.phase}") | ||
if pod.status.phase not in ["Pending", "Running"]: | ||
break | ||
|
||
time.sleep(1) | ||
pass | ||
|
||
if pod.status.phase == "Succeeded": | ||
v1.delete_namespaced_pod(name=pod.metadata.name, namespace="learnware") | ||
return True, "Success" | ||
else: | ||
# read logs of the pod | ||
logs = v1.read_namespaced_pod_log(name=pod.metadata.name, namespace="learnware") | ||
v1.delete_namespaced_pod(name=pod.metadata.name, namespace="learnware") | ||
return False, logs | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,4 +40,5 @@ shortuuid | |
pysocks | ||
redis | ||
fast_pytorch_kmeans | ||
concurrent-log-handler | ||
concurrent-log-handler | ||
kubernetes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
"""this script is executed in k8s pod | ||
""" | ||
import argparse | ||
|
||
from learnware.market import EasyStatChecker, BaseChecker | ||
from learnware.learnware import get_learnware_from_dirpath | ||
import os | ||
import json | ||
|
||
|
||
def verify_learnware(learnware_path, checker_name): | ||
"""verify learnware script""" | ||
checker = eval(checker_name + "()") | ||
semantic_path = os.path.join(learnware_path, "semantic_specification.json") | ||
with open(semantic_path, "r") as f: | ||
semantic_spec = json.load(f) | ||
pass | ||
learnware = get_learnware_from_dirpath("testid", semantic_spec=semantic_spec, learnware_dirpath=learnware_path) | ||
|
||
result, message = checker(learnware) | ||
# learnware package is not updated | ||
# if result != BaseChecker.USABLE_LEARNWARE: | ||
if result != 1: | ||
raise RuntimeError(message) | ||
pass | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser(description="Verify learnware script") | ||
parser.add_argument("--learnware_path", type=str, help="learnware path") | ||
parser.add_argument("--checker_name", type=str, help="checker name") | ||
|
||
args = parser.parse_args() | ||
|
||
verify_learnware(args.learnware_path, args.checker_name) | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import unittest | ||
from scripts import main | ||
import multiprocessing | ||
import context | ||
from context import config as C | ||
import requests | ||
import os | ||
import shutil | ||
from tests import common_test_operations as testops | ||
import time | ||
import restful.utils as utils | ||
import hashlib | ||
|
||
|
||
class TestDatasets(unittest.TestCase): | ||
def setUpClass() -> None: | ||
testops.cleanup_folder() | ||
unittest.TestCase.setUpClass() | ||
testops.set_config("datasets_path", os.path.join("tests")) | ||
mp_context = multiprocessing.get_context("spawn") | ||
TestDatasets.server_process = mp_context.Process(target=main.main) | ||
TestDatasets.server_process.start() | ||
testops.wait_port_open(C.listen_port, 10) | ||
context.init_database() | ||
testops.clear_db() | ||
TestDatasets.username = "test" | ||
TestDatasets.email = "test@localhost" | ||
TestDatasets.password = "test" | ||
testops.url_request( | ||
"auth/register", | ||
{ | ||
"username": TestDatasets.username, | ||
"password": TestDatasets.password, | ||
"email": TestDatasets.email, | ||
"confirm_email": False, | ||
}, | ||
) | ||
|
||
def tearDownClass() -> None: | ||
unittest.TestCase.tearDownClass() | ||
TestDatasets.server_process.kill() | ||
testops.cleanup_folder() | ||
testops.reset_config() | ||
|
||
def test_list(self): | ||
headers = testops.login(TestDatasets.email, TestDatasets.password) | ||
result = testops.url_request("datasets/list_datasets", headers=headers) | ||
|
||
self.assertEqual(result["code"], 0) | ||
self.assertIn("data/stat.json", result["data"]["datasets"]) | ||
|
||
pass | ||
|
||
def test_download( | ||
self, | ||
): | ||
result = testops.url_request( | ||
"datasets/download_datasets", {"dataset": "data/stat.json"}, method="get", return_response=True | ||
) | ||
|
||
with open(os.path.join("tests", "data", "stat.json"), "rb") as fin: | ||
file_content = fin.read() | ||
pass | ||
self.assertTrue(testops.check_bytes_same(result.content, file_content)) | ||
pass | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import os | ||
import context | ||
import unittest | ||
import multiprocessing | ||
from scripts import main | ||
from context import config as C | ||
import tempfile | ||
import zipfile | ||
import common_test_operations as testops | ||
from learnware.config import C as learnware_config | ||
from learnware.client.utils import install_environment, system_execute | ||
from lib import engine as engine_utils | ||
from lib import kubernetes_utils | ||
from scripts.monitor_learnware_verify import verify_learnware_with_conda_checker | ||
import shortuuid | ||
|
||
|
||
class TestKubernetesUtils(unittest.TestCase): | ||
def setUpClass() -> None: | ||
pass | ||
|
||
def tearDownClass() -> None: | ||
pass | ||
|
||
def test_verify_valid_learnware(self): | ||
learnware_path = os.path.join("tests", "data", "test_learnware.zip") | ||
semantic_spec = testops.test_learnware_semantic_specification_table() | ||
learnware_id = "testid" | ||
|
||
with tempfile.TemporaryDirectory() as learnware_folder: | ||
engine_utils.repack_learnware_folder(learnware_path, learnware_folder, learnware_id, semantic_spec) | ||
env_path = str(shortuuid.uuid()) | ||
env_path = os.path.join(context.config["env_path"], env_path) | ||
install_environment(learnware_folder, None, conda_prefix=env_path) | ||
system_execute( | ||
args=[ | ||
"conda", | ||
"run", | ||
"--prefix", | ||
env_path, | ||
"--no-capture-output", | ||
"python", | ||
"-m", | ||
"pip", | ||
"install", | ||
"torch", | ||
] | ||
) | ||
|
||
result, message = kubernetes_utils.run_check(env_path, learnware_folder, "EasyStatChecker") | ||
os.system(f"conda env remove --prefix {env_path}") | ||
self.assertTrue(result) | ||
|
||
pass | ||
|
||
def test_verify_invalid_learnware(self): | ||
pass | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.