def listmodel(key=None): global base_repo global model_repo_host printmsg("Getting model list...") try: mmAuth = mmAuthorization.mmAuthorization("myAuth") authToken = mmAuth.getAuthToken(model_repo_host) headers = { mmAuthorization.AUTHORIZATION_HEADER: mmAuthorization.AUTHORIZATION_TOKEN + authToken } except: raise RuntimeError("ERROR! Failed to auth token") models_url = model_repo_host + "/modelRepository/models?limit=999&start=0" try: response = requests.get(models_url, headers=headers) jsondata = response.json() models = jsondata['items'] if len(models) > 0: for model in models: #print(model) model_name = model['name'] model_name = model_name.lower() model_id = model['id'] model_version = model['modelVersionName'] if key != None: key = key.lower() # ignore if there's partial key and the model name doesn't have the key (case insensitive) if key != None and key != 'all' and key not in model_name: continue print("Model name", model_name) print("Model UUID", model_id) print("Model version", model_version) if 'projectName' in model.keys( ) and model['projectName'] != None: print("Project name", model['projectName']) if 'scoreCodeType' in model.keys(): print("Score Code Type", model['scoreCodeType']) else: print('Warning! No score code type defined!') model_name = slugify(model_name) tagname = model_name + '_' + model_id repo = base_repo + tagname + ":latest" # TODO compare the model version with the image version print("Image URL (not verified):", repo) print("==========================") printmsg("Guides: > python mm_docker_cli.py publish <uuid>") printmsg("Guides: > python mm_docker_cli.py launch <image url>") printmsg( "Guides: > python mm_docker_cli.py score <image url> <input file>") except: raise RuntimeError("ERROR! Failed to get model list")
def download_model_content(self, model_id): print("Downloading model", model_id, "from model repository...") # images folder under the current directory data_path = os.path.join(self.cur_path, 'images') if not os.path.exists(data_path): os.makedirs(data_path) self.print_msg("Images folder:", data_path) filename = "model-"+model_id+".zip" # remove extension dirname = os.path.splitext(filename)[0] # must be lowercase dirname = dirname.lower() subfolder = os.path.join(data_path, dirname) if not os.path.exists(subfolder): os.makedirs(subfolder) model_file_full_path = os.path.join(subfolder, filename) try: mm_auth = mmAuthorization.mmAuthorization("myAuth") auth_token = mm_auth.get_auth_token(self.model_repo_host) headers = { mmAuthorization.AUTHORIZATION_HEADER: mmAuthorization.AUTHORIZATION_TOKEN + auth_token } except: raise RuntimeError("ERROR! Failed to auth token") model_url = self.model_repo_host + "/modelRepository/models/"+model_id try: # http://<host>/modelRepository/models/d00bb4e3-0672-4e9a-a877-39249d2a98ab?format=zip result_url = model_url+"?format=zip" r = requests.get(result_url, allow_redirects=True, headers=headers) # print(r.status_code) if r.status_code == 404: raise RuntimeError("ERROR! Failed to get model file") open(model_file_full_path, 'wb').write(r.content) self.print_msg("Model zip file has been downloaded at", model_file_full_path) except: raise RuntimeError("ERROR! Failed to get model file") # copy astore file if it is an astore model self.copy_astore(subfolder, model_file_full_path, model_id) model_name, version_id, code_type = self.retrieve_model_info(model_url, headers) return model_file_full_path, model_name, version_id, code_type
def download_model_astore(self, model_id, astore_name): try: mm_auth = mmAuthorization.mmAuthorization("myAuth") auth_token = mm_auth.get_auth_token(self.model_repo_host) headers = { "Accept": "application/vnd.sas.model.analytic.store+json", mmAuthorization.AUTHORIZATION_HEADER: mmAuthorization.AUTHORIZATION_TOKEN + auth_token } except: raise RuntimeError("ERROR! Failed to auth token") request_url = self.model_repo_host + f"/modelRepository/models/{model_id}/analyticStore/{astore_name}" try: r = requests.put(request_url, headers=headers) # print(r.status_code) if r.status_code != 202: raise RuntimeError("ERROR! Failed to generate astore file") except: raise RuntimeError("ERROR! Failed to generate astore file") return
# Copyright (c) 2020, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 import mmAuthorization import requests import json viya_host = "localhost" port = ":8080" host_url="http://" + viya_host + port destination_url = host_url + "/modelPublish/destinations/" mm_auth = mmAuthorization.mmAuthorization("myAuth") # admin user id and password admin_userId = "SAS_USER_ADMIN_ID" user_passwd = "SAS_USER_PASSWD" # the domain which the SAS Credential Service stores AWS credentials DOMAIN_NAME = "Domain Name" # the kubernetes cluster name K8S_NAME = "K8s Name" # destination name dest_name = "MY_AWS_DEST_NAME" # AWS region AWS_REGION = "us-east-1" # the docker daemon is running on tcp socket
def publish(model_id): """ * Get model by model_id and always getting the latest version. * Get model by name, project, version, repository, etc * Retrieve model zip file from model respository, such as modelxxxxxx.zip * Get astore by scp temporarily until the other method is ready to pull astore file from the SAS server * create subfolder <tag>, and store zip file and template files in subfolder * return image url if succeed """ global model_repo_host if model_id is None: raise RuntimeError('Error! Model UUID is empty') print("Downloading model", model_id, "from model repository...") # images folder under the current directory data_path = os.path.join(cur_path, 'images') if not os.path.exists(data_path): os.makedirs(data_path) printmsg("Images folder:", data_path) filename = "model-" + model_id + ".zip" # remove extension tmpname = os.path.splitext(filename)[0] # must be lowercase tmpname = tmpname.lower() subfolder = os.path.join(data_path, tmpname) if not os.path.exists(subfolder): os.makedirs(subfolder) model_file_full_path = os.path.join(subfolder, filename) try: mmAuth = mmAuthorization.mmAuthorization("myAuth") authToken = mmAuth.getAuthToken(model_repo_host) headers = { mmAuthorization.AUTHORIZATION_HEADER: mmAuthorization.AUTHORIZATION_TOKEN + authToken } except: raise RuntimeError("ERROR! Failed to auth token") model_url = model_repo_host + "/modelRepository/models/" + model_id try: #http://<host>/modelRepository/models/d00bb4e3-0672-4e9a-a877-39249d2a98ab?format=zip result_url = model_url + "?format=zip" r = requests.get(result_url, allow_redirects=True, headers=headers) #print(r.status_code) if r.status_code == 404: raise RuntimeError("ERROR! Failed to get model file") open(model_file_full_path, 'wb').write(r.content) printmsg("Model zip file has been downloaded at", model_file_full_path) except: raise RuntimeError("ERROR! Failed to get model file") # get model_name, version_id, code_type too model_name, version_id, code_type = retrieve_model_info(model_url, headers) # verify meta data if model_name == None or version_id == None: raise RuntimeError('Unable to retrieve model name or current version!') model_name = slugify(model_name) printmsg("The name has been normalized to", model_name) if code_type == 'python' or code_type == 'Python': template_folder_name = 'template-py' # pyml-base elif code_type == 'R' or code_type == 'r': template_folder_name = 'template-r' # r-base else: template_folder_name = 'template' # maspy-base template_folder = os.path.join(cur_path, template_folder_name) if not os.path.exists(template_folder): raise RuntimeError("Template folder not existed!") dockerfile = os.path.join(template_folder, 'Dockerfile') # make sure that one of files is named after Dockerfile if not os.path.isfile(dockerfile): raiseError("There's no Dockerfile under template folder") printmsg("Template folder:", template_folder) # copy template files into subfolder src_files = os.listdir(template_folder) for file_name in src_files: full_file_name = os.path.join(template_folder, file_name) if (os.path.isfile(full_file_name)): shutil.copy(full_file_name, subfolder) # download astore file if available copy_astore(subfolder, model_file_full_path) # read requirements.json from zip file if available # and include the dependency lines in Dockerfile handle_dependencies(subfolder, model_file_full_path) tagname = model_name + '_' + model_id local_tag = tagname + ':' + version_id local_tag_latest = tagname + ':latest' # build local image with docker daemon client = docker.from_env() print("Building image...") printmsg(local_tag) myimage, _ = client.images.build(path=subfolder, tag=local_tag, nocache=True) # tag it as latest version too printmsg(local_tag_latest) # myimage.tag(local_tag_latest) myimage.tag(tagname, "latest") printmsg("Tag the image into a repository", myimage.short_id) remote_version_latest = push_to_repo(myimage, tagname, version_id) printmsg("==========================") printmsg("Guides: > python mm_docker_cli.py launch", remote_version_latest) printmsg("Guides: > python mm_docker_cli.py score", remote_version_latest, "<input file>") log('publish', model_id, version_id, remote_version_latest) return (remote_version_latest)