From 95686bbc69ded243c346f94dceb0bee567572fb7 Mon Sep 17 00:00:00 2001 From: beierlm Date: Tue, 23 Mar 2021 16:26:45 -0400 Subject: [PATCH] Standardize Formatting Nothing but whitespace change. Reformatted using Black. Change-Id: I1afd579ede0dd49f2d104d4f4bc470a4ac8cbba8 Signed-off-by: beierlm --- osmclient/client.py | 25 +- osmclient/common/http.py | 46 +- osmclient/common/package_tool.py | 609 ++-- osmclient/common/test/test_utils.py | 21 +- osmclient/common/utils.py | 23 +- osmclient/common/wait.py | 57 +- osmclient/scripts/osm.py | 4687 ++++++++++++++++----------- osmclient/sol005/client.py | 80 +- osmclient/sol005/http.py | 155 +- osmclient/sol005/k8scluster.py | 105 +- osmclient/sol005/ns.py | 391 ++- osmclient/sol005/nsd.py | 120 +- osmclient/sol005/nsi.py | 310 +- osmclient/sol005/nst.py | 166 +- osmclient/sol005/osmrepo.py | 425 ++- osmclient/sol005/package.py | 67 +- osmclient/sol005/pdud.py | 82 +- osmclient/sol005/project.py | 107 +- osmclient/sol005/repo.py | 85 +- osmclient/sol005/role.py | 117 +- osmclient/sol005/sdncontroller.py | 109 +- osmclient/sol005/user.py | 129 +- osmclient/sol005/vim.py | 178 +- osmclient/sol005/vnf.py | 45 +- osmclient/sol005/vnfd.py | 227 +- osmclient/sol005/wim.py | 168 +- osmclient/v1/client.py | 97 +- osmclient/v1/key.py | 7 +- osmclient/v1/ns.py | 176 +- osmclient/v1/nsd.py | 28 +- osmclient/v1/package.py | 19 +- osmclient/v1/tests/test_ns.py | 25 +- osmclient/v1/tests/test_nsd.py | 16 +- osmclient/v1/tests/test_package.py | 21 +- osmclient/v1/tests/test_vnf.py | 29 +- osmclient/v1/tests/test_vnfd.py | 16 +- osmclient/v1/utils.py | 4 +- osmclient/v1/vca.py | 48 +- osmclient/v1/vim.py | 279 +- osmclient/v1/vnf.py | 19 +- osmclient/v1/vnfd.py | 29 +- setup.py | 40 +- 42 files changed, 5537 insertions(+), 3850 deletions(-) diff --git a/osmclient/client.py b/osmclient/client.py index 56570b4..fe64f1c 100644 --- a/osmclient/client.py +++ b/osmclient/client.py @@ -23,29 +23,34 @@ from osmclient.v1 import client as client from osmclient.sol005 import client as sol005client import logging import verboselogs + verboselogs.install() def Client(version=1, host=None, sol005=True, *args, **kwargs): log_format_simple = "%(levelname)s %(message)s" log_format_complete = "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)s %(funcName)s(): %(message)s" - log_formatter_simple = logging.Formatter(log_format_simple, datefmt='%Y-%m-%dT%H:%M:%S') + log_formatter_simple = logging.Formatter( + log_format_simple, datefmt="%Y-%m-%dT%H:%M:%S" + ) handler = logging.StreamHandler() handler.setFormatter(log_formatter_simple) - logger = logging.getLogger('osmclient') + logger = logging.getLogger("osmclient") logger.setLevel(level=logging.WARNING) logger.addHandler(handler) - verbose = kwargs.get('verbose',0) - if verbose>0: - log_formatter = logging.Formatter(log_format_complete, datefmt='%Y-%m-%dT%H:%M:%S') - #handler = logging.StreamHandler() + verbose = kwargs.get("verbose", 0) + if verbose > 0: + log_formatter = logging.Formatter( + log_format_complete, datefmt="%Y-%m-%dT%H:%M:%S" + ) + # handler = logging.StreamHandler() handler.setFormatter(log_formatter) - #logger.addHandler(handler) - if verbose==1: + # logger.addHandler(handler) + if verbose == 1: logger.setLevel(level=logging.INFO) - elif verbose==2: + elif verbose == 2: logger.setLevel(level=logging.VERBOSE) - elif verbose>2: + elif verbose > 2: logger.setLevel(level=logging.DEBUG) if not sol005: if version == 1: diff --git a/osmclient/common/http.py b/osmclient/common/http.py index b67b594..fa5eae7 100644 --- a/osmclient/common/http.py +++ b/osmclient/common/http.py @@ -20,8 +20,7 @@ import json class Http(object): - - def __init__(self, url, user='admin', password='admin'): + def __init__(self, url, user="admin", password="admin"): self._url = url self._user = user self._password = password @@ -35,11 +34,7 @@ class Http(object): curl_cmd.setopt(pycurl.URL, self._url + endpoint) curl_cmd.setopt(pycurl.SSL_VERIFYPEER, 0) curl_cmd.setopt(pycurl.SSL_VERIFYHOST, 0) - curl_cmd.setopt( - pycurl.USERPWD, - '{}:{}'.format( - self._user, - self._password)) + curl_cmd.setopt(pycurl.USERPWD, "{}:{}".format(self._user, self._password)) if self._http_header: curl_cmd.setopt(pycurl.HTTPHEADER, self._http_header) return curl_cmd @@ -50,13 +45,17 @@ class Http(object): curl_cmd = self._get_curl_cmd(endpoint) curl_cmd.setopt(pycurl.HTTPGET, 1) curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write) - self._logger.info("Request METHOD: {} URL: {}".format("GET",self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("GET", self._url + endpoint) + ) curl_cmd.perform() http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) self._logger.info("Response HTTPCODE: {}".format(http_code)) curl_cmd.close() if data.getvalue(): - self._logger.debug("Response DATA: {}".format(json.loads(data.getvalue().decode()))) + self._logger.debug( + "Response DATA: {}".format(json.loads(data.getvalue().decode())) + ) return json.loads(data.getvalue().decode()) return None @@ -65,17 +64,26 @@ class Http(object): curl_cmd = self._get_curl_cmd(endpoint) curl_cmd.setopt(pycurl.CUSTOMREQUEST, "DELETE") curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write) - self._logger.info("Request METHOD: {} URL: {}".format("DELETE",self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("DELETE", self._url + endpoint) + ) curl_cmd.perform() http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) self._logger.info("Response HTTPCODE: {}".format(http_code)) curl_cmd.close() if data.getvalue(): - self._logger.debug("Response DATA: {}".format(json.loads(data.getvalue().decode()))) + self._logger.debug( + "Response DATA: {}".format(json.loads(data.getvalue().decode())) + ) return json.loads(data.getvalue().decode()) return None - def post_cmd(self, endpoint='', postfields_dict=None, formfile=None, ): + def post_cmd( + self, + endpoint="", + postfields_dict=None, + formfile=None, + ): data = BytesIO() curl_cmd = self._get_curl_cmd(endpoint) curl_cmd.setopt(pycurl.POST, 1) @@ -87,17 +95,19 @@ class Http(object): if formfile is not None: curl_cmd.setopt( - pycurl.HTTPPOST, - [((formfile[0], - (pycurl.FORM_FILE, - formfile[1])))]) + pycurl.HTTPPOST, [((formfile[0], (pycurl.FORM_FILE, formfile[1])))] + ) - self._logger.info("Request METHOD: {} URL: {}".format("POST",self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("POST", self._url + endpoint) + ) curl_cmd.perform() http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) self._logger.info("Response HTTPCODE: {}".format(http_code)) curl_cmd.close() if data.getvalue(): - self._logger.debug("Response DATA: {}".format(json.loads(data.getvalue().decode()))) + self._logger.debug( + "Response DATA: {}".format(json.loads(data.getvalue().decode())) + ) return json.loads(data.getvalue().decode()) return None diff --git a/osmclient/common/package_tool.py b/osmclient/common/package_tool.py index 473ff3d..e3dbd1a 100644 --- a/osmclient/common/package_tool.py +++ b/osmclient/common/package_tool.py @@ -35,54 +35,95 @@ import yaml class PackageTool(object): def __init__(self, client=None): self._client = client - self._logger = logging.getLogger('osmclient') + self._logger = logging.getLogger("osmclient") self._validator = validation_im() - def create(self, package_type, base_directory, package_name, override, image, vdus, vcpu, memory, storage, - interfaces, vendor, detailed, netslice_subnets, netslice_vlds): - """ - **Create a package descriptor** - - :params: - - package_type: [vnf, ns, nst] - - base directory: path of destination folder - - package_name: is the name of the package to be created - - image: specify the image of the vdu - - vcpu: number of virtual cpus of the vdu - - memory: amount of memory in MB pf the vdu - - storage: amount of storage in GB of the vdu - - interfaces: number of interfaces besides management interface - - vendor: vendor name of the vnf/ns - - detailed: include all possible values for NSD, VNFD, NST - - netslice_subnets: number of netslice_subnets for the NST - - netslice_vlds: number of virtual link descriptors for the NST - - :return: status + def create( + self, + package_type, + base_directory, + package_name, + override, + image, + vdus, + vcpu, + memory, + storage, + interfaces, + vendor, + detailed, + netslice_subnets, + netslice_vlds, + ): + """ + **Create a package descriptor** + + :params: + - package_type: [vnf, ns, nst] + - base directory: path of destination folder + - package_name: is the name of the package to be created + - image: specify the image of the vdu + - vcpu: number of virtual cpus of the vdu + - memory: amount of memory in MB pf the vdu + - storage: amount of storage in GB of the vdu + - interfaces: number of interfaces besides management interface + - vendor: vendor name of the vnf/ns + - detailed: include all possible values for NSD, VNFD, NST + - netslice_subnets: number of netslice_subnets for the NST + - netslice_vlds: number of virtual link descriptors for the NST + + :return: status """ self._logger.debug("") # print("location: {}".format(osmclient.__path__)) file_loader = PackageLoader("osmclient") env = Environment(loader=file_loader) - if package_type == 'ns': - template = env.get_template('nsd.yaml.j2') - content = {"name": package_name, "vendor": vendor, "vdus": vdus, "clean": False, "interfaces": interfaces, - "detailed": detailed} - elif package_type == 'vnf': - template = env.get_template('vnfd.yaml.j2') - content = {"name": package_name, "vendor": vendor, "vdus": vdus, "clean": False, "interfaces": interfaces, - "image": image, "vcpu": vcpu, "memory": memory, "storage": storage, "detailed": detailed} - elif package_type == 'nst': - template = env.get_template('nst.yaml.j2') - content = {"name": package_name, "vendor": vendor, "interfaces": interfaces, - "netslice_subnets": netslice_subnets, "netslice_vlds": netslice_vlds, "detailed": detailed} + if package_type == "ns": + template = env.get_template("nsd.yaml.j2") + content = { + "name": package_name, + "vendor": vendor, + "vdus": vdus, + "clean": False, + "interfaces": interfaces, + "detailed": detailed, + } + elif package_type == "vnf": + template = env.get_template("vnfd.yaml.j2") + content = { + "name": package_name, + "vendor": vendor, + "vdus": vdus, + "clean": False, + "interfaces": interfaces, + "image": image, + "vcpu": vcpu, + "memory": memory, + "storage": storage, + "detailed": detailed, + } + elif package_type == "nst": + template = env.get_template("nst.yaml.j2") + content = { + "name": package_name, + "vendor": vendor, + "interfaces": interfaces, + "netslice_subnets": netslice_subnets, + "netslice_vlds": netslice_vlds, + "detailed": detailed, + } else: - raise ClientException("Wrong descriptor type {}. Options: ns, vnf, nst".format(package_type)) + raise ClientException( + "Wrong descriptor type {}. Options: ns, vnf, nst".format(package_type) + ) # print("To be rendered: {}".format(content)) output = template.render(content) # print(output) - structure = self.discover_folder_structure(base_directory, package_name, override) + structure = self.discover_folder_structure( + base_directory, package_name, override + ) if structure.get("folders"): self.create_folders(structure["folders"], package_type) if structure.get("files"): @@ -91,19 +132,23 @@ class PackageTool(object): def validate(self, base_directory, recursive=True, old_format=False): """ - **Validate OSM Descriptors given a path** + **Validate OSM Descriptors given a path** - :params: - - base_directory is the root path for all descriptors + :params: + - base_directory is the root path for all descriptors - :return: List of dict of validated descriptors. keys: type, path, valid, error + :return: List of dict of validated descriptors. keys: type, path, valid, error """ self._logger.debug("") table = [] if recursive: - descriptors_paths = [f for f in glob.glob(base_directory + "/**/*.yaml", recursive=recursive)] + descriptors_paths = [ + f for f in glob.glob(base_directory + "/**/*.yaml", recursive=recursive) + ] else: - descriptors_paths = [f for f in glob.glob(base_directory + "/*.yaml", recursive=recursive)] + descriptors_paths = [ + f for f in glob.glob(base_directory + "/*.yaml", recursive=recursive) + ] print("Base directory: {}".format(base_directory)) print("{} Descriptors found to validate".format(len(descriptors_paths))) for desc_path in descriptors_paths: @@ -111,34 +156,57 @@ class PackageTool(object): descriptor_data = descriptor_file.read() desc_type = "-" try: - desc_type, descriptor_data = validation_im.yaml_validation(self, descriptor_data) + desc_type, descriptor_data = validation_im.yaml_validation( + self, descriptor_data + ) if not old_format: - if ( desc_type=="vnfd" or desc_type=="nsd" ): - print("OSM descriptor '{}' written in an unsupported format. Please update to ETSI SOL006 format".format(desc_path)) - print("Package validation skipped. It can still be done with 'osm package-validate --old'") - print("Package build can still be done with 'osm package-build --skip-validation'") + if desc_type == "vnfd" or desc_type == "nsd": + print( + "OSM descriptor '{}' written in an unsupported format. Please update to ETSI SOL006 format".format( + desc_path + ) + ) + print( + "Package validation skipped. It can still be done with 'osm package-validate --old'" + ) + print( + "Package build can still be done with 'osm package-build --skip-validation'" + ) raise Exception("Not SOL006 format") validation_im.pyangbind_validation(self, desc_type, descriptor_data) - table.append({"type": desc_type, "path": desc_path, "valid": "OK", "error": "-"}) + table.append( + {"type": desc_type, "path": desc_path, "valid": "OK", "error": "-"} + ) except Exception as e: - table.append({"type": desc_type, "path": desc_path, "valid": "ERROR", "error": str(e)}) + table.append( + { + "type": desc_type, + "path": desc_path, + "valid": "ERROR", + "error": str(e), + } + ) return table def translate(self, base_directory, recursive=True, dryrun=False): """ - **Translate OSM Packages given a path** + **Translate OSM Packages given a path** - :params: - - base_directory is the root path for all packages + :params: + - base_directory is the root path for all packages - :return: List of dict of translated packages. keys: current type, new type, path, valid, translated, error + :return: List of dict of translated packages. keys: current type, new type, path, valid, translated, error """ self._logger.debug("") table = [] if recursive: - descriptors_paths = [f for f in glob.glob(base_directory + "/**/*.yaml", recursive=recursive)] + descriptors_paths = [ + f for f in glob.glob(base_directory + "/**/*.yaml", recursive=recursive) + ] else: - descriptors_paths = [f for f in glob.glob(base_directory + "/*.yaml", recursive=recursive)] + descriptors_paths = [ + f for f in glob.glob(base_directory + "/*.yaml", recursive=recursive) + ] print("Base directory: {}".format(base_directory)) print("{} Descriptors found to validate".format(len(descriptors_paths))) for desc_path in descriptors_paths: @@ -146,85 +214,163 @@ class PackageTool(object): descriptor_data = descriptor_file.read() desc_type = "-" try: - desc_type, descriptor_data = validation_im.yaml_validation(self, descriptor_data) + desc_type, descriptor_data = validation_im.yaml_validation( + self, descriptor_data + ) self._logger.debug("desc_type: {}".format(desc_type)) self._logger.debug("descriptor_data:\n{}".format(descriptor_data)) self._validator.pyangbind_validation(desc_type, descriptor_data) - if not ( desc_type=="vnfd" or desc_type=="nsd" ): - table.append({"current type": desc_type, "new type": desc_type, "path": desc_path, "valid": "OK", "translated": "N/A", "error": "-"}) + if not (desc_type == "vnfd" or desc_type == "nsd"): + table.append( + { + "current type": desc_type, + "new type": desc_type, + "path": desc_path, + "valid": "OK", + "translated": "N/A", + "error": "-", + } + ) else: new_desc_type = desc_type try: - sol006_model = yaml.safe_dump(im_translation.translate_im_model_to_sol006(descriptor_data), indent=4, default_flow_style=False) - new_desc_type, new_descriptor_data = self._validator.yaml_validation(sol006_model) - self._validator.pyangbind_validation(new_desc_type, new_descriptor_data) + sol006_model = yaml.safe_dump( + im_translation.translate_im_model_to_sol006( + descriptor_data + ), + indent=4, + default_flow_style=False, + ) + ( + new_desc_type, + new_descriptor_data, + ) = self._validator.yaml_validation(sol006_model) + self._validator.pyangbind_validation( + new_desc_type, new_descriptor_data + ) if not dryrun: - with open(desc_path, 'w') as descriptor_file: + with open(desc_path, "w") as descriptor_file: descriptor_file.write(sol006_model) - table.append({"current type": desc_type, "new type": new_desc_type, "path": desc_path, "valid": "OK", "translated": "OK", "error": "-"}) + table.append( + { + "current type": desc_type, + "new type": new_desc_type, + "path": desc_path, + "valid": "OK", + "translated": "OK", + "error": "-", + } + ) except ValidationException as ve2: - table.append({"current type": desc_type, "new type": new_desc_type, "path": desc_path, "valid": "OK", "translated": "ERROR", "error": "Error in the post-validation: {}".format(str(ve2))}) + table.append( + { + "current type": desc_type, + "new type": new_desc_type, + "path": desc_path, + "valid": "OK", + "translated": "ERROR", + "error": "Error in the post-validation: {}".format( + str(ve2) + ), + } + ) except Exception as e2: - table.append({"current type": desc_type, "new type": new_desc_type, "path": desc_path, "valid": "OK", "translated": "ERROR", "error": "Error in the translation: {}".format(str(e2))}) + table.append( + { + "current type": desc_type, + "new type": new_desc_type, + "path": desc_path, + "valid": "OK", + "translated": "ERROR", + "error": "Error in the translation: {}".format(str(e2)), + } + ) except ValidationException as ve: - table.append({"current type": desc_type, "new type": "N/A", "path": desc_path, "valid": "ERROR", "translated": "N/A", "error": "Error in the pre-validation: {}".format(str(ve))}) + table.append( + { + "current type": desc_type, + "new type": "N/A", + "path": desc_path, + "valid": "ERROR", + "translated": "N/A", + "error": "Error in the pre-validation: {}".format(str(ve)), + } + ) except Exception as e: - table.append({"current type": desc_type, "new type": "N/A", "path": desc_path, "valid": "ERROR", "translated": "N/A", "error": str(e)}) + table.append( + { + "current type": desc_type, + "new type": "N/A", + "path": desc_path, + "valid": "ERROR", + "translated": "N/A", + "error": str(e), + } + ) return table def descriptor_translate(self, descriptor_file): """ - **Translate input descriptor file from Rel EIGHT OSM to SOL006** + **Translate input descriptor file from Rel EIGHT OSM to SOL006** - :params: - - base_directory is the root path for all packages + :params: + - base_directory is the root path for all packages - :return: YAML descriptor in the new format + :return: YAML descriptor in the new format """ self._logger.debug("") - with open(descriptor_file, 'r') as df: + with open(descriptor_file, "r") as df: im_model = yaml.safe_load(df.read()) sol006_model = im_translation.translate_im_model_to_sol006(im_model) return yaml.safe_dump(sol006_model, indent=4, default_flow_style=False) def build(self, package_folder, skip_validation=False, skip_charm_build=False): """ - **Creates a .tar.gz file given a package_folder** + **Creates a .tar.gz file given a package_folder** - :params: - - package_folder: is the name of the folder to be packaged - - skip_validation: is the flag to validate or not the descriptors on the folder before build + :params: + - package_folder: is the name of the folder to be packaged + - skip_validation: is the flag to validate or not the descriptors on the folder before build - :returns: message result for the build process + :returns: message result for the build process """ self._logger.debug("") - package_folder = package_folder.rstrip('/') + package_folder = package_folder.rstrip("/") if not os.path.exists("{}".format(package_folder)): return "Fail, package is not in the specified path" if not skip_validation: - print('Validating package {}'.format(package_folder)) + print("Validating package {}".format(package_folder)) results = self.validate(package_folder, recursive=False) if results: for result in results: if result["valid"] != "OK": - raise ClientException("There was an error validating the file {} with error: {}" - .format(result["path"], result["error"])) - print('Validation OK') + raise ClientException( + "There was an error validating the file {} with error: {}".format( + result["path"], result["error"] + ) + ) + print("Validation OK") else: - raise ClientException("No descriptor file found in: {}".format(package_folder)) + raise ClientException( + "No descriptor file found in: {}".format(package_folder) + ) charm_list = self.build_all_charms(package_folder, skip_charm_build) return self.build_tarfile(package_folder, charm_list) def calculate_checksum(self, package_folder): """ - **Function to calculate the checksum given a folder** + **Function to calculate the checksum given a folder** - :params: - - package_folder: is the folder where we have the files to calculate the checksum - :returns: None + :params: + - package_folder: is the folder where we have the files to calculate the checksum + :returns: None """ self._logger.debug("") - files = [f for f in glob.glob(package_folder + "/**/*.*", recursive=True) if os.path.isfile(f)] + files = [ + f + for f in glob.glob(package_folder + "/**/*.*", recursive=True) + if os.path.isfile(f) + ] with open("{}/checksums.txt".format(package_folder), "w+") as checksum: for file_item in files: if "checksums.txt" in file_item: @@ -239,12 +385,12 @@ class PackageTool(object): def create_folders(self, folders, package_type): """ - **Create folder given a list of folders** + **Create folder given a list of folders** - :params: - - folders: [List] list of folders paths to be created - - package_type: is the type of package to be created - :return: None + :params: + - folders: [List] list of folders paths to be created + - package_type: is the type of package to be created + :return: None """ self._logger.debug("") for folder in folders: @@ -258,12 +404,12 @@ class PackageTool(object): def save_file(self, file_name, file_body): """ - **Create a file given a name and the content** + **Create a file given a name and the content** - :params: - - file_name: is the name of the file with the relative route - - file_body: is the content of the file - :return: None + :params: + - file_name: is the name of the file with the relative route + - file_body: is the content of the file + :return: None """ self._logger.debug("") print("Creating file: \t{}".format(file_name)) @@ -275,33 +421,34 @@ class PackageTool(object): def generate_readme(self): """ - **Creates the README content** + **Creates the README content** - :returns: readme content + :returns: readme content """ self._logger.debug("") return """# Descriptor created by OSM descriptor package generated\n\n**Created on {} **""".format( - time.strftime("%m/%d/%Y, %H:%M:%S", time.localtime())) + time.strftime("%m/%d/%Y, %H:%M:%S", time.localtime()) + ) def generate_cloud_init(self): """ - **Creates the cloud-init content** + **Creates the cloud-init content** - :returns: cloud-init content + :returns: cloud-init content """ self._logger.debug("") return "---\n#cloud-config" def create_files(self, files, file_content, package_type): """ - **Creates the files given the file list and type** + **Creates the files given the file list and type** - :params: - - files: is the list of files structure - - file_content: is the content of the descriptor rendered by the template - - package_type: is the type of package to filter the creation structure + :params: + - files: is the list of files structure + - file_content: is the content of the descriptor rendered by the template + - package_type: is the type of package to filter the creation structure - :return: None + :return: None """ self._logger.debug("") for file_item, file_package, file_type in files: @@ -315,13 +462,13 @@ class PackageTool(object): def check_files_folders(self, path_list, override): """ - **Find files and folders missing given a directory structure {"folders": [], "files": []}** + **Find files and folders missing given a directory structure {"folders": [], "files": []}** - :params: - - path_list: is the list of files and folders to be created - - override: is the flag used to indicate the creation of the list even if the file exist to override it + :params: + - path_list: is the list of files and folders to be created + - override: is the flag used to indicate the creation of the list even if the file exist to override it - :return: Missing paths Dict + :return: Missing paths Dict """ self._logger.debug("") missing_paths = {} @@ -341,75 +488,99 @@ class PackageTool(object): def build_all_charms(self, package_folder, skip_charm_build): """ - **Read the descriptor file, check that the charms referenced are in the folder and compiles them** + **Read the descriptor file, check that the charms referenced are in the folder and compiles them** - :params: - - packet_folder: is the location of the package - :return: Files and Folders not found. In case of override, it will return all file list + :params: + - packet_folder: is the location of the package + :return: Files and Folders not found. In case of override, it will return all file list """ self._logger.debug("") listCharms = [] descriptor_file = False descriptors_paths = [f for f in glob.glob(package_folder + "/*.yaml")] for file in descriptors_paths: - if file.endswith('nfd.yaml'): + if file.endswith("nfd.yaml"): descriptor_file = True - listCharms = self.charms_search(file, 'vnf') - if file.endswith('nsd.yaml'): + listCharms = self.charms_search(file, "vnf") + if file.endswith("nsd.yaml"): descriptor_file = True - listCharms = self.charms_search(file, 'ns') + listCharms = self.charms_search(file, "ns") print("List of charms in the descriptor: {}".format(listCharms)) if not descriptor_file: - raise ClientException('Descriptor filename is not correct in: {}. It should end with "nfd.yaml" or "nsd.yaml"'.format(package_folder)) + raise ClientException( + 'Descriptor filename is not correct in: {}. It should end with "nfd.yaml" or "nsd.yaml"'.format( + package_folder + ) + ) if listCharms and not skip_charm_build: for charmName in listCharms: - if os.path.isdir('{}/charms/layers/{}'.format(package_folder, charmName)): - print('Building charm {}/charms/layers/{}'.format(package_folder, charmName)) + if os.path.isdir( + "{}/charms/layers/{}".format(package_folder, charmName) + ): + print( + "Building charm {}/charms/layers/{}".format( + package_folder, charmName + ) + ) self.charm_build(package_folder, charmName) - print('Charm built: {}'.format(charmName)) - elif os.path.isdir('{}/charms/ops/{}'.format(package_folder, charmName)): + print("Charm built: {}".format(charmName)) + elif os.path.isdir( + "{}/charms/ops/{}".format(package_folder, charmName) + ): self.charmcraft_build(package_folder, charmName) else: - if not os.path.isdir('{}/charms/{}'.format(package_folder, charmName)): - raise ClientException('The charm: {} referenced in the descriptor file ' - 'is not present either in {}/charms or in {}/charms/layers'. - format(charmName, package_folder, package_folder)) + if not os.path.isdir( + "{}/charms/{}".format(package_folder, charmName) + ): + raise ClientException( + "The charm: {} referenced in the descriptor file " + "is not present either in {}/charms or in {}/charms/layers".format( + charmName, package_folder, package_folder + ) + ) self._logger.debug("Return list of charms: {}".format(listCharms)) return listCharms def discover_folder_structure(self, base_directory, name, override): """ - **Discover files and folders structure for OSM descriptors given a base_directory and name** + **Discover files and folders structure for OSM descriptors given a base_directory and name** - :params: - - base_directory: is the location of the package to be created - - name: is the name of the package - - override: is the flag used to indicate the creation of the list even if the file exist to override it - :return: Files and Folders not found. In case of override, it will return all file list + :params: + - base_directory: is the location of the package to be created + - name: is the name of the package + - override: is the flag used to indicate the creation of the list even if the file exist to override it + :return: Files and Folders not found. In case of override, it will return all file list """ self._logger.debug("") prefix = "{}/{}".format(base_directory, name) - files_folders = {"folders": [("{}_ns".format(prefix), "ns"), - ("{}_ns/icons".format(prefix), "ns"), - ("{}_ns/charms".format(prefix), "ns"), - ("{}_vnf".format(name), "vnf"), - ("{}_vnf/charms".format(prefix), "vnf"), - ("{}_vnf/cloud_init".format(prefix), "vnf"), - ("{}_vnf/images".format(prefix), "vnf"), - ("{}_vnf/icons".format(prefix), "vnf"), - ("{}_vnf/scripts".format(prefix), "vnf"), - ("{}_nst".format(prefix), "nst"), - ("{}_nst/icons".format(prefix), "nst") - ], - "files": [("{}_ns/{}_nsd.yaml".format(prefix, name), "ns", "descriptor"), - ("{}_ns/README.md".format(prefix), "ns", "readme"), - ("{}_vnf/{}_vnfd.yaml".format(prefix, name), "vnf", "descriptor"), - ("{}_vnf/cloud_init/cloud-config.txt".format(prefix), "vnf", "cloud_init"), - ("{}_vnf/README.md".format(prefix), "vnf", "readme"), - ("{}_nst/{}_nst.yaml".format(prefix, name), "nst", "descriptor"), - ("{}_nst/README.md".format(prefix), "nst", "readme") - ] - } + files_folders = { + "folders": [ + ("{}_ns".format(prefix), "ns"), + ("{}_ns/icons".format(prefix), "ns"), + ("{}_ns/charms".format(prefix), "ns"), + ("{}_vnf".format(name), "vnf"), + ("{}_vnf/charms".format(prefix), "vnf"), + ("{}_vnf/cloud_init".format(prefix), "vnf"), + ("{}_vnf/images".format(prefix), "vnf"), + ("{}_vnf/icons".format(prefix), "vnf"), + ("{}_vnf/scripts".format(prefix), "vnf"), + ("{}_nst".format(prefix), "nst"), + ("{}_nst/icons".format(prefix), "nst"), + ], + "files": [ + ("{}_ns/{}_nsd.yaml".format(prefix, name), "ns", "descriptor"), + ("{}_ns/README.md".format(prefix), "ns", "readme"), + ("{}_vnf/{}_vnfd.yaml".format(prefix, name), "vnf", "descriptor"), + ( + "{}_vnf/cloud_init/cloud-config.txt".format(prefix), + "vnf", + "cloud_init", + ), + ("{}_vnf/README.md".format(prefix), "vnf", "readme"), + ("{}_nst/{}_nst.yaml".format(prefix, name), "nst", "descriptor"), + ("{}_nst/README.md".format(prefix), "nst", "readme"), + ], + } missing_files_folders = self.check_files_folders(files_folders, override) # print("Missing files and folders: {}".format(missing_files_folders)) return missing_files_folders @@ -421,13 +592,17 @@ class PackageTool(object): build_name is the name of the layer or interface """ self._logger.debug("") - os.environ['JUJU_REPOSITORY'] = "{}/charms".format(charms_folder) - os.environ['CHARM_LAYERS_DIR'] = "{}/layers".format(os.environ['JUJU_REPOSITORY']) - os.environ['CHARM_INTERFACES_DIR'] = "{}/interfaces".format(os.environ['JUJU_REPOSITORY']) - os.environ['CHARM_BUILD_DIR'] = "{}/charms/builds".format(charms_folder) - if not os.path.exists(os.environ['CHARM_BUILD_DIR']): - os.makedirs(os.environ['CHARM_BUILD_DIR']) - src_folder = '{}/{}'.format(os.environ['CHARM_LAYERS_DIR'], build_name) + os.environ["JUJU_REPOSITORY"] = "{}/charms".format(charms_folder) + os.environ["CHARM_LAYERS_DIR"] = "{}/layers".format( + os.environ["JUJU_REPOSITORY"] + ) + os.environ["CHARM_INTERFACES_DIR"] = "{}/interfaces".format( + os.environ["JUJU_REPOSITORY"] + ) + os.environ["CHARM_BUILD_DIR"] = "{}/charms/builds".format(charms_folder) + if not os.path.exists(os.environ["CHARM_BUILD_DIR"]): + os.makedirs(os.environ["CHARM_BUILD_DIR"]) + src_folder = "{}/{}".format(os.environ["CHARM_LAYERS_DIR"], build_name) result = subprocess.run(["charm", "build", "{}".format(src_folder)]) if result.returncode == 1: raise ClientException("failed to build the charm: {}".format(src_folder)) @@ -446,7 +621,9 @@ class PackageTool(object): try: result = subprocess.run(["charmcraft", "build"]) if result.returncode == 1: - raise ClientException("failed to build the charm: {}".format(src_folder)) + raise ClientException( + "failed to build the charm: {}".format(src_folder) + ) subprocess.run(["rm", "-rf", f"../../{charm_name}"]) subprocess.run(["mv", "build", f"../../{charm_name}"]) self._logger.verbose("charm {} built".format(src_folder)) @@ -462,27 +639,36 @@ class PackageTool(object): self._logger.debug("") cwd = None try: - directory_name, package_name = self.create_temp_dir(package_folder, charm_list) + directory_name, package_name = self.create_temp_dir( + package_folder, charm_list + ) cwd = os.getcwd() os.chdir(directory_name) self.calculate_checksum(package_name) - with tarfile.open("{}.tar.gz".format(package_name), mode='w:gz') as archive: + with tarfile.open("{}.tar.gz".format(package_name), mode="w:gz") as archive: print("Adding File: {}".format(package_name)) - archive.add('{}'.format(package_name), recursive=True) + archive.add("{}".format(package_name), recursive=True) # return "Created {}.tar.gz".format(package_folder) # self.build("{}".format(os.path.basename(package_folder))) os.chdir(cwd) cwd = None - created_package = "{}/{}.tar.gz".format(os.path.dirname(package_folder) or '.', package_name) - os.rename("{}/{}.tar.gz".format(directory_name, package_name), - created_package) - os.rename("{}/{}/checksums.txt".format(directory_name, package_name), - "{}/checksums.txt".format(package_folder)) + created_package = "{}/{}.tar.gz".format( + os.path.dirname(package_folder) or ".", package_name + ) + os.rename( + "{}/{}.tar.gz".format(directory_name, package_name), created_package + ) + os.rename( + "{}/{}/checksums.txt".format(directory_name, package_name), + "{}/checksums.txt".format(package_folder), + ) print("Package created: {}".format(created_package)) return created_package except Exception as exc: - raise ClientException('failure during build of targz file (create temp dir, calculate checksum, ' - 'tar.gz file): {}'.format(exc)) + raise ClientException( + "failure during build of targz file (create temp dir, calculate checksum, " + "tar.gz file): {}".format(exc) + ) finally: if cwd: os.chdir(cwd) @@ -493,7 +679,7 @@ class PackageTool(object): Method to create a temporary folder where we can move the files in package_folder """ self._logger.debug("") - ignore_patterns = ('.gitignore') + ignore_patterns = ".gitignore" ignore = shutil.ignore_patterns(ignore_patterns) directory_name = os.path.abspath(package_folder) package_name = os.path.basename(directory_name) @@ -516,12 +702,19 @@ class PackageTool(object): elif charm in os.listdir(s_builds): s_charm = os.path.join(s_builds, charm) else: - raise ClientException('The charm {} referenced in the descriptor file ' - 'could not be found in {}/charms or in {}/charms/builds'. - format(charm, package_folder, package_folder)) + raise ClientException( + "The charm {} referenced in the descriptor file " + "could not be found in {}/charms or in {}/charms/builds".format( + charm, package_folder, package_folder + ) + ) d_temp = os.path.join(d, charm) - self._logger.debug("Copying tree: {} -> {}".format(s_charm, d_temp)) - shutil.copytree(s_charm, d_temp, symlinks=True, ignore=ignore) + self._logger.debug( + "Copying tree: {} -> {}".format(s_charm, d_temp) + ) + shutil.copytree( + s_charm, d_temp, symlinks=True, ignore=ignore + ) self._logger.debug("DONE") else: self._logger.debug("Copying tree: {} -> {}".format(s, d)) @@ -536,15 +729,29 @@ class PackageTool(object): return directory_name, package_name def charms_search(self, descriptor_file, desc_type): - self._logger.debug("descriptor_file: {}, desc_type: {}".format(descriptor_file, - desc_type)) + self._logger.debug( + "descriptor_file: {}, desc_type: {}".format(descriptor_file, desc_type) + ) with open("{}".format(descriptor_file)) as yaml_desc: descriptor_dict = yaml.safe_load(yaml_desc) - #self._logger.debug("\n"+yaml.safe_dump(descriptor_dict, indent=4, default_flow_style=False)) - - if ( (desc_type=="vnf" and ("vnfd:vnfd-catalog" in descriptor_dict or "vnfd-catalog" in descriptor_dict)) or - (desc_type=="ns" and ( "nsd:nsd-catalog" in descriptor_dict or "nsd-catalog" in descriptor_dict)) ): - charms_list = self._charms_search_on_osm_im_dict(descriptor_dict, desc_type) + # self._logger.debug("\n"+yaml.safe_dump(descriptor_dict, indent=4, default_flow_style=False)) + + if ( + desc_type == "vnf" + and ( + "vnfd:vnfd-catalog" in descriptor_dict + or "vnfd-catalog" in descriptor_dict + ) + ) or ( + desc_type == "ns" + and ( + "nsd:nsd-catalog" in descriptor_dict + or "nsd-catalog" in descriptor_dict + ) + ): + charms_list = self._charms_search_on_osm_im_dict( + descriptor_dict, desc_type + ) else: if desc_type == "ns": get_charm_list = self._charms_search_on_nsd_sol006_dict @@ -561,18 +768,18 @@ class PackageTool(object): for k1, v1 in osm_im_dict.items(): for k2, v2 in v1.items(): for entry in v2: - if '{}-configuration'.format(desc_type) in entry: - vnf_config = entry['{}-configuration'.format(desc_type)] + if "{}-configuration".format(desc_type) in entry: + vnf_config = entry["{}-configuration".format(desc_type)] for k3, v3 in vnf_config.items(): - if 'charm' in v3: - charms_list.append((v3['charm'])) - if 'vdu' in entry: - vdus = entry['vdu'] + if "charm" in v3: + charms_list.append((v3["charm"])) + if "vdu" in entry: + vdus = entry["vdu"] for vdu in vdus: - if 'vdu-configuration' in vdu: - for k4, v4 in vdu['vdu-configuration'].items(): - if 'charm' in v4: - charms_list.append((v4['charm'])) + if "vdu-configuration" in vdu: + for k4, v4 in vdu["vdu-configuration"].items(): + if "charm" in v4: + charms_list.append((v4["charm"])) return charms_list def _charms_search_on_vnfd_sol006_dict(self, sol006_dict): @@ -580,7 +787,11 @@ class PackageTool(object): charms_list = [] dfs = sol006_dict.get("vnfd", {}).get("df", []) for df in dfs: - day_1_2s = df.get("lcm-operations-configuration", {}).get("operate-vnf-op-config", {}).get("day1-2") + day_1_2s = ( + df.get("lcm-operations-configuration", {}) + .get("operate-vnf-op-config", {}) + .get("day1-2") + ) for day_1_2 in day_1_2s: exec_env_list = day_1_2.get("execution-environment-list", []) for exec_env in exec_env_list: diff --git a/osmclient/common/test/test_utils.py b/osmclient/common/test/test_utils.py index 7134662..5ba03f4 100644 --- a/osmclient/common/test/test_utils.py +++ b/osmclient/common/test/test_utils.py @@ -20,20 +20,22 @@ from osmclient.common import utils class TestUtil(unittest.TestCase): - def test_wait_for_method_basic(self): def foobar(): return True + assert utils.wait_for_value(lambda: foobar()) def test_wait_for_method_timeout(self): def foobar(): return False + assert not utils.wait_for_value(lambda: foobar(), wait_time=0) def test_wait_for_method_paramter(self): def foobar(input): return input + assert not utils.wait_for_value(lambda: foobar(False), wait_time=0) assert utils.wait_for_value(lambda: foobar(True), wait_time=0) @@ -43,25 +45,26 @@ class TestUtil(unittest.TestCase): return True foobar.counter -= 1 return False + foobar.counter = 1 assert utils.wait_for_value(lambda: foobar(), wait_time=1) def test_wait_for_method_exception(self): def foobar(): - raise Exception('send exception') + raise Exception("send exception") + assert not utils.wait_for_value( - lambda: foobar(), - wait_time=0, - catch_exception=Exception) + lambda: foobar(), wait_time=0, catch_exception=Exception + ) def test_wait_for_method_first_exception(self): def foobar(): if foobar.counter == 0: return True foobar.counter -= 1 - raise Exception('send exception') + raise Exception("send exception") + foobar.counter = 1 assert utils.wait_for_value( - lambda: foobar(), - wait_time=1, - catch_exception=Exception) + lambda: foobar(), wait_time=1, catch_exception=Exception + ) diff --git a/osmclient/common/utils.py b/osmclient/common/utils.py index 94bd72f..aed7d29 100644 --- a/osmclient/common/utils.py +++ b/osmclient/common/utils.py @@ -59,8 +59,7 @@ def get_key_val_from_pkg(descriptor_file): tar = tarfile.open(descriptor_file) yamlfile = None for member in tar.getmembers(): - if (re.match('.*.yaml', member.name) and - len(member.name.split('/')) == 2): + if re.match(".*.yaml", member.name) and len(member.name.split("/")) == 2: yamlfile = member.name break if yamlfile is None: @@ -69,25 +68,25 @@ def get_key_val_from_pkg(descriptor_file): dict = yaml.safe_load(tar.extractfile(yamlfile)) result = {} for k in dict: - if 'nsd' in k: - result['type'] = 'nsd' + if "nsd" in k: + result["type"] = "nsd" else: - result['type'] = 'vnfd' - if 'type' not in result: + result["type"] = "vnfd" + if "type" not in result: for k1, v1 in list(dict.items()): - if not k1.endswith('-catalog'): + if not k1.endswith("-catalog"): continue for k2, v2 in v1.items(): - if not k2.endswith('nsd') and not k2.endswith('vnfd'): + if not k2.endswith("nsd") and not k2.endswith("vnfd"): continue - if 'nsd' in k2: - result['type'] = 'nsd' + if "nsd" in k2: + result["type"] = "nsd" else: - result['type'] = 'vnfd' + result["type"] = "vnfd" for entry in v2: for k3, v3 in list(entry.items()): # strip off preceeding chars before : - key_name = k3.split(':').pop() + key_name = k3.split(":").pop() result[key_name] = v3 tar.close() diff --git a/osmclient/common/wait.py b/osmclient/common/wait.py index bb9a82a..d3f673c 100644 --- a/osmclient/common/wait.py +++ b/osmclient/common/wait.py @@ -56,10 +56,10 @@ def _get_finished_states(entity): :param entity: can be NS, NSI, or other :return: two tuples with status completed strings, status failed string """ - if entity == 'NS' or entity == 'NSI': - return ('COMPLETED', 'PARTIALLY_COMPLETED'), ('FAILED_TEMP', 'FAILED') + if entity == "NS" or entity == "NSI": + return ("COMPLETED", "PARTIALLY_COMPLETED"), ("FAILED_TEMP", "FAILED") else: - return ('ENABLED', ), ('ERROR', ) + return ("ENABLED",), ("ERROR",) def _get_operational_state(resp, entity): @@ -72,10 +72,10 @@ def _get_operational_state(resp, entity): :param entity: can be NS, NSI, or other :return: status of the operation """ - if entity == 'NS' or entity == 'NSI': - return resp.get('operationState') + if entity == "NS" or entity == "NSI": + return resp.get("operationState") else: - return resp.get('_admin', {}).get('operationalState') + return resp.get("_admin", {}).get("operationalState") def _op_has_finished(resp, entity): @@ -95,9 +95,11 @@ def _op_has_finished(resp, entity): if op_state in finished_states_ok: return True elif op_state in finished_states_error: - raise ClientException("Operation failed with status '{}'".format(op_state)) + raise ClientException( + "Operation failed with status '{}'".format(op_state) + ) return False - raise ClientException('Unexpected response from server: {} '.format(resp)) + raise ClientException("Unexpected response from server: {} ".format(resp)) def _get_detailed_status(resp, entity): @@ -109,28 +111,39 @@ def _get_detailed_status(resp, entity): :param entity: can be NS, NSI, or other :return: """ - if entity in ('NS', 'NSI'): + if entity in ("NS", "NSI"): # For NS and NSI, 'detailed-status' is a JSON "root" member: - return resp.get('detailed-status') + return resp.get("detailed-status") else: - ops = resp.get('_admin', {}).get('operations') - current_op = resp.get('_admin', {}).get('current_operation') + ops = resp.get("_admin", {}).get("operations") + current_op = resp.get("_admin", {}).get("current_operation") if ops and current_op is not None: # Operations are supported, verify operation index if isinstance(ops, dict) and current_op in ops: return ops[current_op].get("detailed-status") - elif isinstance(ops, list) and isinstance(current_op, int) or current_op.isdigit(): + elif ( + isinstance(ops, list) + and isinstance(current_op, int) + or current_op.isdigit() + ): current_op = int(current_op) - if current_op >= 0 and current_op < len(ops) and ops[current_op] and ops[current_op]["detailed-status"]: + if ( + current_op >= 0 + and current_op < len(ops) + and ops[current_op] + and ops[current_op]["detailed-status"] + ): return ops[current_op]["detailed-status"] # operation index is either non-numeric or out-of-range - return 'Unexpected error when getting detailed-status!' + return "Unexpected error when getting detailed-status!" else: # Operations are NOT supported - return resp.get('_admin', {}).get('detailed-status') + return resp.get("_admin", {}).get("detailed-status") -def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, deleteFlag=False): +def wait_for_status( + entity_label, entity_id, timeout, apiUrlStatus, http_cmd, deleteFlag=False +): """ Wait until operation ends, making polling every 5s. Prints detailed status when it changes :param entity_label: String describing the entities using '--wait': 'NS', 'NSI', 'SDNC', 'VIM', 'WIM' @@ -149,11 +162,11 @@ def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, de max_retries = 1 while True: try: - http_code, resp_unicode = http_cmd('{}/{}'.format(apiUrlStatus, entity_id)) + http_code, resp_unicode = http_cmd("{}/{}".format(apiUrlStatus, entity_id)) retries = 0 except NotFound: if deleteFlag: - _show_detailed_status(detailed_status, 'Deleted') + _show_detailed_status(detailed_status, "Deleted") return raise except ClientException: @@ -163,14 +176,14 @@ def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, de sleep(POLLING_TIME_INTERVAL) continue - resp = '' + resp = "" if resp_unicode: resp = json.loads(resp_unicode) new_detailed_status = _get_detailed_status(resp, entity_label) # print('DETAILED-STATUS: {}'.format(new_detailed_status)) if not new_detailed_status: - new_detailed_status = 'In progress' + new_detailed_status = "In progress" detailed_status = _show_detailed_status(detailed_status, new_detailed_status) # Get operation status @@ -179,5 +192,5 @@ def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, de if time() >= time_to_finish: # There was a timeout, so raise an exception - raise ClientException('operation timeout after {} seconds'.format(timeout)) + raise ClientException("operation timeout after {} seconds".format(timeout)) sleep(POLLING_TIME_INTERVAL) diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py index c434fe8..603d373 100755 --- a/osmclient/scripts/osm.py +++ b/osmclient/scripts/osm.py @@ -40,13 +40,13 @@ def wrap_text(text, width): def trunc_text(text, length): - if len(text) > length: - return text[:(length - 3)] + '...' - else: - return text + if len(text) > length: + return text[: (length - 3)] + "..." + else: + return text -def check_client_version(obj, what, version='sol005'): +def check_client_version(obj, what, version="sol005"): """ Checks the version of the client object and raises error if it not the expected. @@ -57,98 +57,118 @@ def check_client_version(obj, what, version='sol005'): """ logger.debug("") fullclassname = obj.__module__ + "." + obj.__class__.__name__ - message = 'The following commands or options are only supported with the option "--sol005": {}'.format(what) - if version == 'v1': - message = 'The following commands or options are not supported when using option "--sol005": {}'.format(what) - if fullclassname != 'osmclient.{}.client.Client'.format(version): + message = 'The following commands or options are only supported with the option "--sol005": {}'.format( + what + ) + if version == "v1": + message = 'The following commands or options are not supported when using option "--sol005": {}'.format( + what + ) + if fullclassname != "osmclient.{}.client.Client".format(version): raise ClientException(message) return def get_project(project_list, item): # project_list = ctx.obj.project.list() - item_project_list = item.get('_admin', {}).get('projects_read') - project_id = 'None' - project_name = 'None' + item_project_list = item.get("_admin", {}).get("projects_read") + project_id = "None" + project_name = "None" if item_project_list: for p1 in item_project_list: project_id = p1 for p2 in project_list: - if p2['_id'] == project_id: - project_name = p2['name'] + if p2["_id"] == project_id: + project_name = p2["name"] return project_id, project_name return project_id, project_name def get_vim_name(vim_list, vim_id): - vim_name = '-' + vim_name = "-" for v in vim_list: - if v['uuid'] == vim_id: - vim_name = v['name'] + if v["uuid"] == vim_id: + vim_name = v["name"] break return vim_name -@click.group(context_settings=dict(help_option_names=['-h', '--help'], max_content_width=160)) -@click.option('--hostname', - default="127.0.0.1", - envvar='OSM_HOSTNAME', - help='hostname of server. ' + - 'Also can set OSM_HOSTNAME in environment') -#@click.option('--sol005/--no-sol005', +@click.group( + context_settings=dict(help_option_names=["-h", "--help"], max_content_width=160) +) +@click.option( + "--hostname", + default="127.0.0.1", + envvar="OSM_HOSTNAME", + help="hostname of server. " + "Also can set OSM_HOSTNAME in environment", +) +# @click.option('--sol005/--no-sol005', # default=True, # envvar='OSM_SOL005', # help='Use ETSI NFV SOL005 API (default) or the previous SO API. ' + # 'Also can set OSM_SOL005 in environment') -@click.option('--user', - default=None, - envvar='OSM_USER', - help='user (defaults to admin). ' + - 'Also can set OSM_USER in environment') -@click.option('--password', - default=None, - envvar='OSM_PASSWORD', - help='password (defaults to admin). ' + - 'Also can set OSM_PASSWORD in environment') -@click.option('--project', - default=None, - envvar='OSM_PROJECT', - help='project (defaults to admin). ' + - 'Also can set OSM_PROJECT in environment') -@click.option('-v', '--verbose', count=True, - help='increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)') -@click.option('--all-projects', - default=None, - is_flag=True, - help='include all projects') -@click.option('--public/--no-public', default=None, - help='flag for public items (packages, instances, VIM accounts, etc.)') -@click.option('--project-domain-name', 'project_domain_name', - default=None, - envvar='OSM_PROJECT_DOMAIN_NAME', - help='project domain name for keystone authentication (default to None). ' + - 'Also can set OSM_PROJECT_DOMAIN_NAME in environment') -@click.option('--user-domain-name', 'user_domain_name', - default=None, - envvar='OSM_USER_DOMAIN_NAME', - help='user domain name for keystone authentication (default to None). ' + - 'Also can set OSM_USER_DOMAIN_NAME in environment') -#@click.option('--so-port', +@click.option( + "--user", + default=None, + envvar="OSM_USER", + help="user (defaults to admin). " + "Also can set OSM_USER in environment", +) +@click.option( + "--password", + default=None, + envvar="OSM_PASSWORD", + help="password (defaults to admin). " + "Also can set OSM_PASSWORD in environment", +) +@click.option( + "--project", + default=None, + envvar="OSM_PROJECT", + help="project (defaults to admin). " + "Also can set OSM_PROJECT in environment", +) +@click.option( + "-v", + "--verbose", + count=True, + help="increase verbosity (-v INFO, -vv VERBOSE, -vvv DEBUG)", +) +@click.option("--all-projects", default=None, is_flag=True, help="include all projects") +@click.option( + "--public/--no-public", + default=None, + help="flag for public items (packages, instances, VIM accounts, etc.)", +) +@click.option( + "--project-domain-name", + "project_domain_name", + default=None, + envvar="OSM_PROJECT_DOMAIN_NAME", + help="project domain name for keystone authentication (default to None). " + + "Also can set OSM_PROJECT_DOMAIN_NAME in environment", +) +@click.option( + "--user-domain-name", + "user_domain_name", + default=None, + envvar="OSM_USER_DOMAIN_NAME", + help="user domain name for keystone authentication (default to None). " + + "Also can set OSM_USER_DOMAIN_NAME in environment", +) +# @click.option('--so-port', # default=None, # envvar='OSM_SO_PORT', # help='hostname of server. ' + # 'Also can set OSM_SO_PORT in environment') -#@click.option('--so-project', +# @click.option('--so-project', # default=None, # envvar='OSM_SO_PROJECT', # help='Project Name in SO. ' + # 'Also can set OSM_SO_PROJECT in environment') -#@click.option('--ro-hostname', +# @click.option('--ro-hostname', # default=None, # envvar='OSM_RO_HOSTNAME', # help='hostname of RO server. ' + # 'Also can set OSM_RO_HOSTNAME in environment') -#@click.option('--ro-port', +# @click.option('--ro-port', # default=None, # envvar='OSM_RO_PORT', # help='hostname of RO server. ' + @@ -158,44 +178,55 @@ def cli_osm(ctx, **kwargs): global logger hostname = kwargs.pop("hostname", None) if hostname is None: - print(( - "either hostname option or OSM_HOSTNAME " + - "environment variable needs to be specified")) + print( + ( + "either hostname option or OSM_HOSTNAME " + + "environment variable needs to be specified" + ) + ) exit(1) # Remove None values kwargs = {k: v for k, v in kwargs.items() if v is not None} -# if so_port is not None: -# kwargs['so_port']=so_port -# if so_project is not None: -# kwargs['so_project']=so_project -# if ro_hostname is not None: -# kwargs['ro_host']=ro_hostname -# if ro_port is not None: -# kwargs['ro_port']=ro_port - sol005 = os.getenv('OSM_SOL005', True) -# if user is not None: -# kwargs['user']=user -# if password is not None: -# kwargs['password']=password -# if project is not None: -# kwargs['project']=project -# if all_projects: -# kwargs['all_projects']=all_projects -# if public is not None: -# kwargs['public']=public + # if so_port is not None: + # kwargs['so_port']=so_port + # if so_project is not None: + # kwargs['so_project']=so_project + # if ro_hostname is not None: + # kwargs['ro_host']=ro_hostname + # if ro_port is not None: + # kwargs['ro_port']=ro_port + sol005 = os.getenv("OSM_SOL005", True) + # if user is not None: + # kwargs['user']=user + # if password is not None: + # kwargs['password']=password + # if project is not None: + # kwargs['project']=project + # if all_projects: + # kwargs['all_projects']=all_projects + # if public is not None: + # kwargs['public']=public ctx.obj = client.Client(host=hostname, sol005=sol005, **kwargs) - logger = logging.getLogger('osmclient') + logger = logging.getLogger("osmclient") #################### # LIST operations #################### -@cli_osm.command(name='ns-list', short_help='list all NS instances') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NS instances matching the filter.') -@click.option('--long', is_flag=True, - help='get more details of the NS (project, vim, deployment status, configuration status.') + +@cli_osm.command(name="ns-list", short_help="list all NS instances") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NS instances matching the filter.", +) +@click.option( + "--long", + is_flag=True, + help="get more details of the NS (project, vim, deployment status, configuration status.", +) @click.pass_context def ns_list(ctx, filter, long): """list all NS instances @@ -245,60 +276,61 @@ def ns_list(ctx, filter, long): --filter nsd.vendor=&nsd-ref= --filter nsd.constituent-vnfd.vnfd-id-ref= """ + def summarize_deployment_status(status_dict): - #Nets + # Nets summary = "" if not status_dict: return summary n_nets = 0 status_nets = {} - net_list = status_dict.get('nets',[]) + net_list = status_dict.get("nets", []) for net in net_list: n_nets += 1 - if net['status'] not in status_nets: - status_nets[net['status']] = 1 + if net["status"] not in status_nets: + status_nets[net["status"]] = 1 else: - status_nets[net['status']] +=1 + status_nets[net["status"]] += 1 message = "Nets: " - for k,v in status_nets.items(): - message += "{}:{},".format(k,v) + for k, v in status_nets.items(): + message += "{}:{},".format(k, v) message += "TOTAL:{}".format(n_nets) summary += "{}".format(message) - #VMs and VNFs + # VMs and VNFs n_vms = 0 status_vms = {} status_vnfs = {} - vnf_list = status_dict['vnfs'] + vnf_list = status_dict["vnfs"] for vnf in vnf_list: - member_vnf_index = vnf['member_vnf_index'] + member_vnf_index = vnf["member_vnf_index"] if member_vnf_index not in status_vnfs: status_vnfs[member_vnf_index] = {} - for vm in vnf['vms']: + for vm in vnf["vms"]: n_vms += 1 - if vm['status'] not in status_vms: - status_vms[vm['status']] = 1 + if vm["status"] not in status_vms: + status_vms[vm["status"]] = 1 else: - status_vms[vm['status']] +=1 - if vm['status'] not in status_vnfs[member_vnf_index]: - status_vnfs[member_vnf_index][vm['status']] = 1 + status_vms[vm["status"]] += 1 + if vm["status"] not in status_vnfs[member_vnf_index]: + status_vnfs[member_vnf_index][vm["status"]] = 1 else: - status_vnfs[member_vnf_index][vm['status']] += 1 + status_vnfs[member_vnf_index][vm["status"]] += 1 message = "VMs: " - for k,v in status_vms.items(): - message += "{}:{},".format(k,v) + for k, v in status_vms.items(): + message += "{}:{},".format(k, v) message += "TOTAL:{}".format(n_vms) summary += "\n{}".format(message) summary += "\nNFs:" - for k,v in status_vnfs.items(): + for k, v in status_vnfs.items(): total = 0 message = "\n {} VMs: ".format(k) - for k2,v2 in v.items(): - message += "{}:{},".format(k2,v2) + for k2, v2 in v.items(): + message += "{}:{},".format(k2, v2) total += v2 message += "TOTAL:{}".format(total) summary += message return summary - + def summarize_config_status(ee_list): summary = "" if not ee_list: @@ -307,20 +339,20 @@ def ns_list(ctx, filter, long): status_ee = {} for ee in ee_list: n_ee += 1 - if ee['elementType'] not in status_ee: - status_ee[ee['elementType']] = {} - status_ee[ee['elementType']][ee['status']] = 1 + if ee["elementType"] not in status_ee: + status_ee[ee["elementType"]] = {} + status_ee[ee["elementType"]][ee["status"]] = 1 continue - if ee['status'] in status_ee[ee['elementType']]: - status_ee[ee['elementType']][ee['status']] += 1 + if ee["status"] in status_ee[ee["elementType"]]: + status_ee[ee["elementType"]][ee["status"]] += 1 else: - status_ee[ee['elementType']][ee['status']] = 1 + status_ee[ee["elementType"]][ee["status"]] = 1 for elementType in ["KDU", "VDU", "PDU", "VNF", "NS"]: if elementType in status_ee: message = "" total = 0 - for k,v in status_ee[elementType].items(): - message += "{}:{},".format(k,v) + for k, v in status_ee[elementType].items(): + message += "{}:{},".format(k, v) total += v message += "TOTAL:{}\n".format(total) summary += "{}: {}".format(elementType, message) @@ -329,23 +361,26 @@ def ns_list(ctx, filter, long): logger.debug("") if filter: - check_client_version(ctx.obj, '--filter') - filter='&'.join(filter) + check_client_version(ctx.obj, "--filter") + filter = "&".join(filter) resp = ctx.obj.ns.list(filter) else: resp = ctx.obj.ns.list() if long: table = PrettyTable( - ['ns instance name', - 'id', - 'date', - 'ns state', - 'current operation', - 'error details', - 'project', - 'vim (inst param)', - 'deployment status', - 'configuration status']) + [ + "ns instance name", + "id", + "date", + "ns state", + "current operation", + "error details", + "project", + "vim (inst param)", + "deployment status", + "configuration status", + ] + ) project_list = ctx.obj.project.list() try: vim_list = ctx.obj.vim.list() @@ -353,119 +388,176 @@ def ns_list(ctx, filter, long): vim_list = [] else: table = PrettyTable( - ['ns instance name', - 'id', - 'date', - 'ns state', - 'current operation', - 'error details']) + [ + "ns instance name", + "id", + "date", + "ns state", + "current operation", + "error details", + ] + ) for ns in resp: fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname == 'osmclient.sol005.client.Client': + if fullclassname == "osmclient.sol005.client.Client": nsr = ns - logger.debug('NS info: {}'.format(nsr)) - nsr_name = nsr['name'] - nsr_id = nsr['_id'] - date = datetime.fromtimestamp(nsr['create-time']).strftime("%Y-%m-%dT%H:%M:%S") - ns_state = nsr.get('nsState', nsr['_admin']['nsState']) + logger.debug("NS info: {}".format(nsr)) + nsr_name = nsr["name"] + nsr_id = nsr["_id"] + date = datetime.fromtimestamp(nsr["create-time"]).strftime( + "%Y-%m-%dT%H:%M:%S" + ) + ns_state = nsr.get("nsState", nsr["_admin"]["nsState"]) if long: - deployment_status = summarize_deployment_status(nsr.get('deploymentStatus')) - config_status = summarize_config_status(nsr.get('configurationStatus')) + deployment_status = summarize_deployment_status( + nsr.get("deploymentStatus") + ) + config_status = summarize_config_status(nsr.get("configurationStatus")) project_id, project_name = get_project(project_list, nsr) - #project = '{} ({})'.format(project_name, project_id) + # project = '{} ({})'.format(project_name, project_id) project = project_name - vim_id = nsr.get('datacenter') + vim_id = nsr.get("datacenter") vim_name = get_vim_name(vim_list, vim_id) - #vim = '{} ({})'.format(vim_name, vim_id) + # vim = '{} ({})'.format(vim_name, vim_id) vim = vim_name - if 'currentOperation' in nsr: - current_operation = "{} ({})".format(nsr['currentOperation'],nsr['currentOperationID']) + if "currentOperation" in nsr: + current_operation = "{} ({})".format( + nsr["currentOperation"], nsr["currentOperationID"] + ) else: - current_operation = "{} ({})".format(nsr['_admin'].get('current-operation','-'), nsr['_admin']['nslcmop']) + current_operation = "{} ({})".format( + nsr["_admin"].get("current-operation", "-"), + nsr["_admin"]["nslcmop"], + ) error_details = "N/A" - if ns_state == "BROKEN" or ns_state == "DEGRADED" or \ - ('currentOperation' not in nsr and nsr.get('errorDescription')): - error_details = "{}\nDetail: {}".format(nsr['errorDescription'], nsr['errorDetail']) + if ( + ns_state == "BROKEN" + or ns_state == "DEGRADED" + or ("currentOperation" not in nsr and nsr.get("errorDescription")) + ): + error_details = "{}\nDetail: {}".format( + nsr["errorDescription"], nsr["errorDetail"] + ) else: - nsopdata = ctx.obj.ns.get_opdata(ns['id']) - nsr = nsopdata['nsr:nsr'] - nsr_name = nsr['name-ref'] - nsr_id = nsr['ns-instance-config-ref'] - date = '-' - project = '-' - deployment_status = nsr['operational-status'] if 'operational-status' in nsr else 'Not found' + nsopdata = ctx.obj.ns.get_opdata(ns["id"]) + nsr = nsopdata["nsr:nsr"] + nsr_name = nsr["name-ref"] + nsr_id = nsr["ns-instance-config-ref"] + date = "-" + project = "-" + deployment_status = ( + nsr["operational-status"] + if "operational-status" in nsr + else "Not found" + ) ns_state = deployment_status - config_status = nsr.get('config-status', 'Not found') + config_status = nsr.get("config-status", "Not found") current_operation = "Unknown" - error_details = nsr.get('detailed-status', 'Not found') + error_details = nsr.get("detailed-status", "Not found") if config_status == "config_not_needed": config_status = "configured (no charms)" if long: table.add_row( - [nsr_name, - nsr_id, - date, - ns_state, - current_operation, - wrap_text(text=error_details,width=40), - project, - vim, - deployment_status, - config_status]) + [ + nsr_name, + nsr_id, + date, + ns_state, + current_operation, + wrap_text(text=error_details, width=40), + project, + vim, + deployment_status, + config_status, + ] + ) else: table.add_row( - [nsr_name, - nsr_id, - date, - ns_state, - current_operation, - wrap_text(text=error_details,width=40)]) - table.align = 'l' + [ + nsr_name, + nsr_id, + date, + ns_state, + current_operation, + wrap_text(text=error_details, width=40), + ] + ) + table.align = "l" print(table) print('To get the history of all operations over a NS, run "osm ns-op-list NS_ID"') - print('For more details on the current operation, run "osm ns-op-show OPERATION_ID"') + print( + 'For more details on the current operation, run "osm ns-op-show OPERATION_ID"' + ) + def nsd_list(ctx, filter, long): logger.debug("") if filter: - check_client_version(ctx.obj, '--filter') - filter='&'.join(filter) + check_client_version(ctx.obj, "--filter") + filter = "&".join(filter) resp = ctx.obj.nsd.list(filter) else: resp = ctx.obj.nsd.list() # print(yaml.safe_dump(resp)) fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname == 'osmclient.sol005.client.Client': + if fullclassname == "osmclient.sol005.client.Client": if long: - table = PrettyTable(['nsd name', 'id', 'onboarding state', 'operational state', - 'usage state', 'date', 'last update']) + table = PrettyTable( + [ + "nsd name", + "id", + "onboarding state", + "operational state", + "usage state", + "date", + "last update", + ] + ) else: - table = PrettyTable(['nsd name', 'id']) + table = PrettyTable(["nsd name", "id"]) for nsd in resp: - name = nsd.get('id', '-') + name = nsd.get("id", "-") if long: - onb_state = nsd['_admin'].get('onboardingState','-') - op_state = nsd['_admin'].get('operationalState','-') - usage_state = nsd['_admin'].get('usageState','-') - date = datetime.fromtimestamp(nsd['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S") - last_update = datetime.fromtimestamp(nsd['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S") - table.add_row([name, nsd['_id'], onb_state, op_state, usage_state, date, last_update]) + onb_state = nsd["_admin"].get("onboardingState", "-") + op_state = nsd["_admin"].get("operationalState", "-") + usage_state = nsd["_admin"].get("usageState", "-") + date = datetime.fromtimestamp(nsd["_admin"]["created"]).strftime( + "%Y-%m-%dT%H:%M:%S" + ) + last_update = datetime.fromtimestamp( + nsd["_admin"]["modified"] + ).strftime("%Y-%m-%dT%H:%M:%S") + table.add_row( + [ + name, + nsd["_id"], + onb_state, + op_state, + usage_state, + date, + last_update, + ] + ) else: - table.add_row([name, nsd['_id']]) + table.add_row([name, nsd["_id"]]) else: - table = PrettyTable(['nsd name', 'id']) + table = PrettyTable(["nsd name", "id"]) for nsd in resp: - table.add_row([nsd['name'], nsd['id']]) - table.align = 'l' + table.add_row([nsd["name"], nsd["id"]]) + table.align = "l" print(table) -@cli_osm.command(name='nsd-list', short_help='list all NS packages') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NSD/NSpkg matching the filter') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="nsd-list", short_help="list all NS packages") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NSD/NSpkg matching the filter", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nsd_list1(ctx, filter, long): """list all NSD/NS pkg in the system""" @@ -473,10 +565,14 @@ def nsd_list1(ctx, filter, long): nsd_list(ctx, filter, long) -@cli_osm.command(name='nspkg-list', short_help='list all NS packages') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NSD/NSpkg matching the filter') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="nspkg-list", short_help="list all NS packages") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NSD/NSpkg matching the filter", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nsd_list2(ctx, filter, long): """list all NS packages""" @@ -487,31 +583,34 @@ def nsd_list2(ctx, filter, long): def pkg_repo_list(ctx, pkgtype, filter, repo, long): resp = ctx.obj.osmrepo.pkg_list(pkgtype, filter, repo) if long: - table = PrettyTable(['nfpkg name', 'vendor', 'version', 'latest', 'description', 'repository']) + table = PrettyTable( + ["nfpkg name", "vendor", "version", "latest", "description", "repository"] + ) else: - table = PrettyTable(['nfpkg name', 'repository']) + table = PrettyTable(["nfpkg name", "repository"]) for vnfd in resp: - name = vnfd.get('id', vnfd.get('name','-')) - repository = vnfd.get('repository') + name = vnfd.get("id", vnfd.get("name", "-")) + repository = vnfd.get("repository") if long: - vendor = vnfd.get('provider', vnfd.get('vendor')) - version = vnfd.get('version') - description = vnfd.get('description') - latest = vnfd.get('latest') + vendor = vnfd.get("provider", vnfd.get("vendor")) + version = vnfd.get("version") + description = vnfd.get("description") + latest = vnfd.get("latest") table.add_row([name, vendor, version, latest, description, repository]) else: table.add_row([name, repository]) - table.align = 'l' + table.align = "l" print(table) + def vnfd_list(ctx, nf_type, filter, long): logger.debug("") if nf_type: - check_client_version(ctx.obj, '--nf_type') + check_client_version(ctx.obj, "--nf_type") elif filter: - check_client_version(ctx.obj, '--filter') + check_client_version(ctx.obj, "--filter") if filter: - filter='&'.join(filter) + filter = "&".join(filter) if nf_type: if nf_type == "vnf": nf_filter = "_admin.type=vnfd" @@ -520,9 +619,11 @@ def vnfd_list(ctx, nf_type, filter, long): elif nf_type == "hnf": nf_filter = "_admin.type=hnfd" else: - raise ClientException('wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf') + raise ClientException( + 'wrong value for "--nf_type" option, allowed values: vnf, pnf, hnf' + ) if filter: - filter = '{}&{}'.format(nf_filter, filter) + filter = "{}&{}".format(nf_filter, filter) else: filter = nf_filter if filter: @@ -531,39 +632,72 @@ def vnfd_list(ctx, nf_type, filter, long): resp = ctx.obj.vnfd.list() # print(yaml.safe_dump(resp)) fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname == 'osmclient.sol005.client.Client': + if fullclassname == "osmclient.sol005.client.Client": if long: - table = PrettyTable(['nfpkg name', 'id', 'desc type', 'vendor', 'version', 'onboarding state', 'operational state', - 'usage state', 'date', 'last update']) + table = PrettyTable( + [ + "nfpkg name", + "id", + "desc type", + "vendor", + "version", + "onboarding state", + "operational state", + "usage state", + "date", + "last update", + ] + ) else: - table = PrettyTable(['nfpkg name', 'id', 'desc type']) + table = PrettyTable(["nfpkg name", "id", "desc type"]) for vnfd in resp: - name = vnfd.get('id', vnfd.get('name','-')) - descriptor_type = 'sol006' if 'product-name' in vnfd else 'rel8' + name = vnfd.get("id", vnfd.get("name", "-")) + descriptor_type = "sol006" if "product-name" in vnfd else "rel8" if long: - onb_state = vnfd['_admin'].get('onboardingState','-') - op_state = vnfd['_admin'].get('operationalState','-') - vendor = vnfd.get('provider', vnfd.get('vendor')) - version = vnfd.get('version') - usage_state = vnfd['_admin'].get('usageState','-') - date = datetime.fromtimestamp(vnfd['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S") - last_update = datetime.fromtimestamp(vnfd['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S") - table.add_row([name, vnfd['_id'], descriptor_type, vendor, version, onb_state, op_state, usage_state, date, last_update]) + onb_state = vnfd["_admin"].get("onboardingState", "-") + op_state = vnfd["_admin"].get("operationalState", "-") + vendor = vnfd.get("provider", vnfd.get("vendor")) + version = vnfd.get("version") + usage_state = vnfd["_admin"].get("usageState", "-") + date = datetime.fromtimestamp(vnfd["_admin"]["created"]).strftime( + "%Y-%m-%dT%H:%M:%S" + ) + last_update = datetime.fromtimestamp( + vnfd["_admin"]["modified"] + ).strftime("%Y-%m-%dT%H:%M:%S") + table.add_row( + [ + name, + vnfd["_id"], + descriptor_type, + vendor, + version, + onb_state, + op_state, + usage_state, + date, + last_update, + ] + ) else: - table.add_row([name, vnfd['_id'], descriptor_type]) + table.add_row([name, vnfd["_id"], descriptor_type]) else: - table = PrettyTable(['nfpkg name', 'id']) + table = PrettyTable(["nfpkg name", "id"]) for vnfd in resp: - table.add_row([vnfd['name'], vnfd['id']]) - table.align = 'l' + table.add_row([vnfd["name"], vnfd["id"]]) + table.align = "l" print(table) -@cli_osm.command(name='vnfd-list', short_help='list all xNF packages (VNF, HNF, PNF)') -@click.option('--nf_type', help='type of NF (vnf, pnf, hnf)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NF pkg matching the filter') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="vnfd-list", short_help="list all xNF packages (VNF, HNF, PNF)") +@click.option("--nf_type", help="type of NF (vnf, pnf, hnf)") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NF pkg matching the filter", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def vnfd_list1(ctx, nf_type, filter, long): """list all xNF packages (VNF, HNF, PNF)""" @@ -571,11 +705,15 @@ def vnfd_list1(ctx, nf_type, filter, long): vnfd_list(ctx, nf_type, filter, long) -@cli_osm.command(name='vnfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)') -@click.option('--nf_type', help='type of NF (vnf, pnf, hnf)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NFpkg matching the filter') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="vnfpkg-list", short_help="list all xNF packages (VNF, HNF, PNF)") +@click.option("--nf_type", help="type of NF (vnf, pnf, hnf)") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NFpkg matching the filter", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def vnfd_list2(ctx, nf_type, filter, long): """list all xNF packages (VNF, HNF, PNF)""" @@ -583,11 +721,15 @@ def vnfd_list2(ctx, nf_type, filter, long): vnfd_list(ctx, nf_type, filter, long) -@cli_osm.command(name='nfpkg-list', short_help='list all xNF packages (VNF, HNF, PNF)') -@click.option('--nf_type', help='type of NF (vnf, pnf, hnf)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NFpkg matching the filter') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="nfpkg-list", short_help="list all xNF packages (VNF, HNF, PNF)") +@click.option("--nf_type", help="type of NF (vnf, pnf, hnf)") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NFpkg matching the filter", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nfpkg_list(ctx, nf_type, filter, long): """list all xNF packages (VNF, HNF, PNF)""" @@ -600,28 +742,43 @@ def nfpkg_list(ctx, nf_type, filter, long): # exit(1) -@cli_osm.command(name='vnfpkg-repo-list', short_help='list all xNF from OSM repositories') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NFpkg matching the filter') -@click.option('--repo', default=None, - help='restricts the list to a particular OSM repository') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command( + name="vnfpkg-repo-list", short_help="list all xNF from OSM repositories" +) +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NFpkg matching the filter", +) +@click.option( + "--repo", default=None, help="restricts the list to a particular OSM repository" +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nfpkg_repo_list1(ctx, filter, repo, long): """list xNF packages from OSM repositories""" - pkgtype = 'vnf' + pkgtype = "vnf" pkg_repo_list(ctx, pkgtype, filter, repo, long) -@cli_osm.command(name='nfpkg-repo-list', short_help='list all xNF from OSM repositories') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NFpkg matching the filter') -@click.option('--repo', default=None, - help='restricts the list to a particular OSM repository') -@click.option('--long', is_flag=True, help='get more details') + +@cli_osm.command( + name="nfpkg-repo-list", short_help="list all xNF from OSM repositories" +) +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NFpkg matching the filter", +) +@click.option( + "--repo", default=None, help="restricts the list to a particular OSM repository" +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nfpkg_repo_list2(ctx, filter, repo, long): """list xNF packages from OSM repositories""" - pkgtype = 'vnf' + pkgtype = "vnf" pkg_repo_list(ctx, pkgtype, filter, repo, long) @@ -629,10 +786,10 @@ def vnf_list(ctx, ns, filter, long): # try: if ns or filter: if ns: - check_client_version(ctx.obj, '--ns') + check_client_version(ctx.obj, "--ns") if filter: - filter='&'.join(filter) - check_client_version(ctx.obj, '--filter') + filter = "&".join(filter) + check_client_version(ctx.obj, "--filter") resp = ctx.obj.vnf.list(ns, filter) else: resp = ctx.obj.vnf.list() @@ -640,83 +797,132 @@ def vnf_list(ctx, ns, filter, long): # print(str(e)) # exit(1) fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname == 'osmclient.sol005.client.Client': - field_names = ['vnf id', 'name', 'ns id', 'vnf member index', - 'vnfd name', 'vim account id', 'ip address'] + if fullclassname == "osmclient.sol005.client.Client": + field_names = [ + "vnf id", + "name", + "ns id", + "vnf member index", + "vnfd name", + "vim account id", + "ip address", + ] if long: - field_names = ['vnf id', 'name', 'ns id', 'vnf member index', - 'vnfd name', 'vim account id', 'ip address', - 'date', 'last update'] + field_names = [ + "vnf id", + "name", + "ns id", + "vnf member index", + "vnfd name", + "vim account id", + "ip address", + "date", + "last update", + ] table = PrettyTable(field_names) for vnfr in resp: - name = vnfr['name'] if 'name' in vnfr else '-' - new_row = [vnfr['_id'], name, vnfr['nsr-id-ref'], - vnfr['member-vnf-index-ref'], vnfr['vnfd-ref'], - vnfr['vim-account-id'], vnfr['ip-address']] + name = vnfr["name"] if "name" in vnfr else "-" + new_row = [ + vnfr["_id"], + name, + vnfr["nsr-id-ref"], + vnfr["member-vnf-index-ref"], + vnfr["vnfd-ref"], + vnfr["vim-account-id"], + vnfr["ip-address"], + ] if long: - date = datetime.fromtimestamp(vnfr['_admin']['created']).strftime("%Y-%m-%dT%H:%M:%S") - last_update = datetime.fromtimestamp(vnfr['_admin']['modified']).strftime("%Y-%m-%dT%H:%M:%S") + date = datetime.fromtimestamp(vnfr["_admin"]["created"]).strftime( + "%Y-%m-%dT%H:%M:%S" + ) + last_update = datetime.fromtimestamp( + vnfr["_admin"]["modified"] + ).strftime("%Y-%m-%dT%H:%M:%S") new_row.extend([date, last_update]) table.add_row(new_row) else: - table = PrettyTable( - ['vnf name', - 'id', - 'operational status', - 'config status']) + table = PrettyTable(["vnf name", "id", "operational status", "config status"]) for vnfr in resp: - if 'mgmt-interface' not in vnfr: - vnfr['mgmt-interface'] = {} - vnfr['mgmt-interface']['ip-address'] = None + if "mgmt-interface" not in vnfr: + vnfr["mgmt-interface"] = {} + vnfr["mgmt-interface"]["ip-address"] = None table.add_row( - [vnfr['name'], - vnfr['id'], - vnfr['operational-status'], - vnfr['config-status']]) - table.align = 'l' + [ + vnfr["name"], + vnfr["id"], + vnfr["operational-status"], + vnfr["config-status"], + ] + ) + table.align = "l" print(table) -@cli_osm.command(name='vnf-list', short_help='list all NF instances') -@click.option('--ns', default=None, help='NS instance id or name to restrict the NF list') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NF instances matching the filter.') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="vnf-list", short_help="list all NF instances") +@click.option( + "--ns", default=None, help="NS instance id or name to restrict the NF list" +) +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NF instances matching the filter.", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def vnf_list1(ctx, ns, filter, long): """list all NF instances""" logger.debug("") vnf_list(ctx, ns, filter, long) -@cli_osm.command(name='nsd-repo-list', short_help='list all NS from OSM repositories') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NS matching the filter') -@click.option('--repo', default=None, - help='restricts the list to a particular OSM repository') -@click.option('--long', is_flag=True, help='get more details') + +@cli_osm.command(name="nsd-repo-list", short_help="list all NS from OSM repositories") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NS matching the filter", +) +@click.option( + "--repo", default=None, help="restricts the list to a particular OSM repository" +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nspkg_repo_list(ctx, filter, repo, long): """list xNF packages from OSM repositories""" - pkgtype = 'ns' + pkgtype = "ns" pkg_repo_list(ctx, pkgtype, filter, repo, long) -@cli_osm.command(name='nspkg-repo-list', short_help='list all NS from OSM repositories') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NS matching the filter') -@click.option('--repo', default=None, - help='restricts the list to a particular OSM repository') -@click.option('--long', is_flag=True, help='get more details') + +@cli_osm.command(name="nspkg-repo-list", short_help="list all NS from OSM repositories") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NS matching the filter", +) +@click.option( + "--repo", default=None, help="restricts the list to a particular OSM repository" +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nspkg_repo_list2(ctx, filter, repo, long): """list xNF packages from OSM repositories""" - pkgtype = 'ns' + pkgtype = "ns" pkg_repo_list(ctx, pkgtype, filter, repo, long) -@cli_osm.command(name='nf-list', short_help='list all NF instances') -@click.option('--ns', default=None, help='NS instance id or name to restrict the NF list') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NF instances matching the filter.') -@click.option('--long', is_flag=True, help='get more details') + +@cli_osm.command(name="nf-list", short_help="list all NF instances") +@click.option( + "--ns", default=None, help="NS instance id or name to restrict the NF list" +) +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NF instances matching the filter.", +) +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def nf_list(ctx, ns, filter, long): """list all NF instances @@ -770,26 +976,30 @@ def nf_list(ctx, ns, filter, long): vnf_list(ctx, ns, filter, long) -@cli_osm.command(name='ns-op-list', short_help='shows the history of operations over a NS instance') -@click.argument('name') -@click.option('--long', is_flag=True, - help='get more details of the NS operation (date, ).') +@cli_osm.command( + name="ns-op-list", short_help="shows the history of operations over a NS instance" +) +@click.argument("name") +@click.option( + "--long", is_flag=True, help="get more details of the NS operation (date, )." +) @click.pass_context def ns_op_list(ctx, name, long): """shows the history of operations over a NS instance NAME: name or ID of the NS instance """ + def formatParams(params): - if params['lcmOperationType']=='instantiate': - params.pop('nsDescription') - params.pop('nsName') - params.pop('nsdId') - params.pop('nsr_id') - elif params['lcmOperationType']=='action': - params.pop('primitive') - params.pop('lcmOperationType') - params.pop('nsInstanceId') + if params["lcmOperationType"] == "instantiate": + params.pop("nsDescription") + params.pop("nsName") + params.pop("nsdId") + params.pop("nsr_id") + elif params["lcmOperationType"] == "action": + params.pop("primitive") + params.pop("lcmOperationType") + params.pop("nsInstanceId") return params logger.debug("") @@ -801,39 +1011,69 @@ def ns_op_list(ctx, name, long): # exit(1) if long: - table = PrettyTable(['id', 'operation', 'action_name', 'operation_params', 'status', 'date', 'last update', 'detail']) + table = PrettyTable( + [ + "id", + "operation", + "action_name", + "operation_params", + "status", + "date", + "last update", + "detail", + ] + ) else: - table = PrettyTable(['id', 'operation', 'action_name', 'status', 'date', 'detail']) + table = PrettyTable( + ["id", "operation", "action_name", "status", "date", "detail"] + ) - #print(yaml.safe_dump(resp)) + # print(yaml.safe_dump(resp)) for op in resp: action_name = "N/A" - if op['lcmOperationType']=='action': - action_name = op['operationParams']['primitive'] + if op["lcmOperationType"] == "action": + action_name = op["operationParams"]["primitive"] detail = "-" - if op['operationState'] == 'PROCESSING': - if op['queuePosition'] is not None and op['queuePosition'] > 0: - detail = "In queue. Current position: {}".format(op['queuePosition']) - elif op['lcmOperationType'] in ('instantiate', 'terminate'): - if op['stage']: - detail = op['stage'] - elif op['operationState'] in ('FAILED', 'FAILED_TEMP'): - detail = op.get('errorMessage','-') - date = datetime.fromtimestamp(op['startTime']).strftime("%Y-%m-%dT%H:%M:%S") - last_update = datetime.fromtimestamp(op['statusEnteredTime']).strftime("%Y-%m-%dT%H:%M:%S") + if op["operationState"] == "PROCESSING": + if op["queuePosition"] is not None and op["queuePosition"] > 0: + detail = "In queue. Current position: {}".format(op["queuePosition"]) + elif op["lcmOperationType"] in ("instantiate", "terminate"): + if op["stage"]: + detail = op["stage"] + elif op["operationState"] in ("FAILED", "FAILED_TEMP"): + detail = op.get("errorMessage", "-") + date = datetime.fromtimestamp(op["startTime"]).strftime("%Y-%m-%dT%H:%M:%S") + last_update = datetime.fromtimestamp(op["statusEnteredTime"]).strftime( + "%Y-%m-%dT%H:%M:%S" + ) if long: - table.add_row([op['id'], - op['lcmOperationType'], - action_name, - wrap_text(text=json.dumps(formatParams(op['operationParams']),indent=2),width=50), - op['operationState'], - date, - last_update, - wrap_text(text=detail,width=50)]) + table.add_row( + [ + op["id"], + op["lcmOperationType"], + action_name, + wrap_text( + text=json.dumps(formatParams(op["operationParams"]), indent=2), + width=50, + ), + op["operationState"], + date, + last_update, + wrap_text(text=detail, width=50), + ] + ) else: - table.add_row([op['id'], op['lcmOperationType'], action_name, - op['operationState'], date, wrap_text(text=detail or "",width=50)]) - table.align = 'l' + table.add_row( + [ + op["id"], + op["lcmOperationType"], + action_name, + op["operationState"], + date, + wrap_text(text=detail or "", width=50), + ] + ) + table.align = "l" print(table) @@ -843,38 +1083,44 @@ def nsi_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.nsi.list(filter) # except ClientException as e: # print(str(e)) # exit(1) table = PrettyTable( - ['netslice instance name', - 'id', - 'operational status', - 'config status', - 'detailed status']) + [ + "netslice instance name", + "id", + "operational status", + "config status", + "detailed status", + ] + ) for nsi in resp: - nsi_name = nsi['name'] - nsi_id = nsi['_id'] - opstatus = nsi['operational-status'] if 'operational-status' in nsi else 'Not found' - configstatus = nsi['config-status'] if 'config-status' in nsi else 'Not found' - detailed_status = nsi['detailed-status'] if 'detailed-status' in nsi else 'Not found' + nsi_name = nsi["name"] + nsi_id = nsi["_id"] + opstatus = ( + nsi["operational-status"] if "operational-status" in nsi else "Not found" + ) + configstatus = nsi["config-status"] if "config-status" in nsi else "Not found" + detailed_status = ( + nsi["detailed-status"] if "detailed-status" in nsi else "Not found" + ) if configstatus == "config_not_needed": configstatus = "configured (no charms)" - table.add_row( - [nsi_name, - nsi_id, - opstatus, - configstatus, - detailed_status]) - table.align = 'l' + table.add_row([nsi_name, nsi_id, opstatus, configstatus, detailed_status]) + table.align = "l" print(table) -@cli_osm.command(name='nsi-list', short_help='list all Network Slice Instances (NSI)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the Network Slice Instances matching the filter') +@cli_osm.command(name="nsi-list", short_help="list all Network Slice Instances (NSI)") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the Network Slice Instances matching the filter", +) @click.pass_context def nsi_list1(ctx, filter): """list all Network Slice Instances (NSI)""" @@ -882,9 +1128,15 @@ def nsi_list1(ctx, filter): nsi_list(ctx, filter) -@cli_osm.command(name='netslice-instance-list', short_help='list all Network Slice Instances (NSI)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the Network Slice Instances matching the filter') +@cli_osm.command( + name="netslice-instance-list", short_help="list all Network Slice Instances (NSI)" +) +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the Network Slice Instances matching the filter", +) @click.pass_context def nsi_list2(ctx, filter): """list all Network Slice Instances (NSI)""" @@ -897,23 +1149,27 @@ def nst_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.nst.list(filter) # except ClientException as e: # print(str(e)) # exit(1) # print(yaml.safe_dump(resp)) - table = PrettyTable(['nst name', 'id']) + table = PrettyTable(["nst name", "id"]) for nst in resp: - name = nst['name'] if 'name' in nst else '-' - table.add_row([name, nst['_id']]) - table.align = 'l' + name = nst["name"] if "name" in nst else "-" + table.add_row([name, nst["_id"]]) + table.align = "l" print(table) -@cli_osm.command(name='nst-list', short_help='list all Network Slice Templates (NST)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NST matching the filter') +@cli_osm.command(name="nst-list", short_help="list all Network Slice Templates (NST)") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NST matching the filter", +) @click.pass_context def nst_list1(ctx, filter): """list all Network Slice Templates (NST) in the system""" @@ -921,9 +1177,15 @@ def nst_list1(ctx, filter): nst_list(ctx, filter) -@cli_osm.command(name='netslice-template-list', short_help='list all Network Slice Templates (NST)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the NST matching the filter') +@cli_osm.command( + name="netslice-template-list", short_help="list all Network Slice Templates (NST)" +) +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the NST matching the filter", +) @click.pass_context def nst_list2(ctx, filter): """list all Network Slice Templates (NST) in the system""" @@ -939,16 +1201,18 @@ def nsi_op_list(ctx, name): # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['id', 'operation', 'status']) + table = PrettyTable(["id", "operation", "status"]) for op in resp: - table.add_row([op['id'], op['lcmOperationType'], - op['operationState']]) - table.align = 'l' + table.add_row([op["id"], op["lcmOperationType"], op["operationState"]]) + table.align = "l" print(table) -@cli_osm.command(name='nsi-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)') -@click.argument('name') +@cli_osm.command( + name="nsi-op-list", + short_help="shows the history of operations over a Network Slice Instance (NSI)", +) +@click.argument("name") @click.pass_context def nsi_op_list1(ctx, name): """shows the history of operations over a Network Slice Instance (NSI) @@ -959,8 +1223,11 @@ def nsi_op_list1(ctx, name): nsi_op_list(ctx, name) -@cli_osm.command(name='netslice-instance-op-list', short_help='shows the history of operations over a Network Slice Instance (NSI)') -@click.argument('name') +@cli_osm.command( + name="netslice-instance-op-list", + short_help="shows the history of operations over a Network Slice Instance (NSI)", +) +@click.argument("name") @click.pass_context def nsi_op_list2(ctx, name): """shows the history of operations over a Network Slice Instance (NSI) @@ -971,9 +1238,13 @@ def nsi_op_list2(ctx, name): nsi_op_list(ctx, name) -@cli_osm.command(name='pdu-list', short_help='list all Physical Deployment Units (PDU)') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the Physical Deployment Units matching the filter') +@cli_osm.command(name="pdu-list", short_help="list all Physical Deployment Units (PDU)") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the Physical Deployment Units matching the filter", +) @click.pass_context def pdu_list(ctx, filter): """list all Physical Deployment Units (PDU)""" @@ -981,31 +1252,23 @@ def pdu_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.pdu.list(filter) # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable( - ['pdu name', - 'id', - 'type', - 'mgmt ip address']) + table = PrettyTable(["pdu name", "id", "type", "mgmt ip address"]) for pdu in resp: - pdu_name = pdu['name'] - pdu_id = pdu['_id'] - pdu_type = pdu['type'] + pdu_name = pdu["name"] + pdu_id = pdu["_id"] + pdu_type = pdu["type"] pdu_ipaddress = "None" - for iface in pdu['interfaces']: - if iface['mgmt']: - pdu_ipaddress = iface['ip-address'] + for iface in pdu["interfaces"]: + if iface["mgmt"]: + pdu_ipaddress = iface["ip-address"] break - table.add_row( - [pdu_name, - pdu_id, - pdu_type, - pdu_ipaddress]) - table.align = 'l' + table.add_row([pdu_name, pdu_id, pdu_type, pdu_ipaddress]) + table.align = "l" print(table) @@ -1013,6 +1276,7 @@ def pdu_list(ctx, filter): # SHOW operations #################### + def nsd_show(ctx, name, literal): logger.debug("") # try: @@ -1026,17 +1290,16 @@ def nsd_show(ctx, name, literal): print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(resp.items()): - table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)]) - table.align = 'l' + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) + table.align = "l" print(table) -@cli_osm.command(name='nsd-show', short_help='shows the details of a NS package') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command(name="nsd-show", short_help="shows the details of a NS package") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def nsd_show1(ctx, name, literal): """shows the content of a NSD @@ -1047,10 +1310,9 @@ def nsd_show1(ctx, name, literal): nsd_show(ctx, name, literal) -@cli_osm.command(name='nspkg-show', short_help='shows the details of a NS package') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command(name="nspkg-show", short_help="shows the details of a NS package") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def nsd_show2(ctx, name, literal): """shows the content of a NSD @@ -1074,42 +1336,41 @@ def vnfd_show(ctx, name, literal): print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(resp.items()): - table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)]) - table.align = 'l' + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) + table.align = "l" print(table) def pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal): logger.debug("") if filter: - filter='&'.join(filter) + filter = "&".join(filter) # try: resp = ctx.obj.osmrepo.pkg_get(pkgtype, name, repo, version, filter) if literal: print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - pkgtype += 'd' - catalog = pkgtype + '-catalog' - full_catalog = pkgtype + ':' + catalog + pkgtype += "d" + catalog = pkgtype + "-catalog" + full_catalog = pkgtype + ":" + catalog if resp.get(catalog): resp = resp.pop(catalog)[pkgtype][0] elif resp.get(full_catalog): resp = resp.pop(full_catalog)[pkgtype][0] - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(resp.items()): table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) - table.align = 'l' + table.align = "l" print(table) -@cli_osm.command(name='vnfd-show', short_help='shows the details of a NF package') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command(name="vnfd-show", short_help="shows the details of a NF package") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def vnfd_show1(ctx, name, literal): """shows the content of a VNFD @@ -1120,10 +1381,9 @@ def vnfd_show1(ctx, name, literal): vnfd_show(ctx, name, literal) -@cli_osm.command(name='vnfpkg-show', short_help='shows the details of a NF package') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command(name="vnfpkg-show", short_help="shows the details of a NF package") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def vnfd_show2(ctx, name, literal): """shows the content of a VNFD @@ -1133,75 +1393,67 @@ def vnfd_show2(ctx, name, literal): logger.debug("") vnfd_show(ctx, name, literal) -@cli_osm.command(name='vnfpkg-repo-show', short_help='shows the details of a NF package in an OSM repository') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--repo', - required=True, - help='Repository name') -@click.argument('name') -@click.option('--filter', default=None, multiple=True, - help='filter by fields') -@click.option('--version', - default='latest', - help='package version') + +@cli_osm.command( + name="vnfpkg-repo-show", + short_help="shows the details of a NF package in an OSM repository", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option("--repo", required=True, help="Repository name") +@click.argument("name") +@click.option("--filter", default=None, multiple=True, help="filter by fields") +@click.option("--version", default="latest", help="package version") @click.pass_context def vnfd_show3(ctx, name, repo, version, literal=None, filter=None): """shows the content of a VNFD in a repository NAME: name or ID of the VNFD/VNFpkg """ - pkgtype = 'vnf' + pkgtype = "vnf" pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) -@cli_osm.command(name='nsd-repo-show', short_help='shows the details of a NS package in an OSM repository') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--repo', - required=True, - help='Repository name') -@click.argument('name') -@click.option('--filter', default=None, multiple=True, - help='filter by fields') -@click.option('--version', - default='latest', - help='package version') +@cli_osm.command( + name="nsd-repo-show", + short_help="shows the details of a NS package in an OSM repository", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option("--repo", required=True, help="Repository name") +@click.argument("name") +@click.option("--filter", default=None, multiple=True, help="filter by fields") +@click.option("--version", default="latest", help="package version") @click.pass_context def nsd_repo_show(ctx, name, repo, version, literal=None, filter=None): """shows the content of a VNFD in a repository NAME: name or ID of the VNFD/VNFpkg """ - pkgtype = 'ns' + pkgtype = "ns" pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) -@cli_osm.command(name='nspkg-repo-show', short_help='shows the details of a NS package in an OSM repository') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--repo', - required=True, - help='Repository name') -@click.argument('name') -@click.option('--filter', default=None, multiple=True, - help='filter by fields') -@click.option('--version', - default='latest', - help='package version') + +@cli_osm.command( + name="nspkg-repo-show", + short_help="shows the details of a NS package in an OSM repository", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option("--repo", required=True, help="Repository name") +@click.argument("name") +@click.option("--filter", default=None, multiple=True, help="filter by fields") +@click.option("--version", default="latest", help="package version") @click.pass_context def nsd_repo_show2(ctx, name, repo, version, literal=None, filter=None): """shows the content of a VNFD in a repository NAME: name or ID of the VNFD/VNFpkg """ - pkgtype = 'ns' + pkgtype = "ns" pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) -@cli_osm.command(name='nfpkg-show', short_help='shows the details of a NF package') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command(name="nfpkg-show", short_help="shows the details of a NF package") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def nfpkg_show(ctx, name, literal): """shows the content of a NF Descriptor @@ -1212,34 +1464,33 @@ def nfpkg_show(ctx, name, literal): vnfd_show(ctx, name, literal) -@cli_osm.command(name='nfpkg-repo-show', short_help='shows the details of a NF package in an OSM repository') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--repo', - required=True, - help='Repository name') -@click.argument('name') -@click.option('--filter', default=None, multiple=True, - help='filter by fields') -@click.option('--version', - default='latest', - help='package version') +@cli_osm.command( + name="nfpkg-repo-show", + short_help="shows the details of a NF package in an OSM repository", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option("--repo", required=True, help="Repository name") +@click.argument("name") +@click.option("--filter", default=None, multiple=True, help="filter by fields") +@click.option("--version", default="latest", help="package version") @click.pass_context def vnfd_show4(ctx, name, repo, version, literal=None, filter=None): """shows the content of a VNFD in a repository NAME: name or ID of the VNFD/VNFpkg """ - pkgtype = 'vnf' + pkgtype = "vnf" pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal) -@cli_osm.command(name='ns-show', short_help='shows the info of a NS instance') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command(name="ns-show", short_help="shows the info of a NS instance") +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def ns_show(ctx, name, literal, filter): """shows the info of a NS instance @@ -1257,50 +1508,59 @@ def ns_show(ctx, name, literal, filter): print(yaml.safe_dump(ns, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(ns.items()): if not filter or k in filter: - table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)]) + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname != 'osmclient.sol005.client.Client': - nsopdata = ctx.obj.ns.get_opdata(ns['id']) - nsr_optdata = nsopdata['nsr:nsr'] + if fullclassname != "osmclient.sol005.client.Client": + nsopdata = ctx.obj.ns.get_opdata(ns["id"]) + nsr_optdata = nsopdata["nsr:nsr"] for k, v in list(nsr_optdata.items()): if not filter or k in filter: - table.add_row([k, wrap_text(json.dumps(v, indent=2),width=100)]) - table.align = 'l' + table.add_row([k, wrap_text(json.dumps(v, indent=2), width=100)]) + table.align = "l" print(table) -@cli_osm.command(name='vnf-show', short_help='shows the info of a VNF instance') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') -@click.option('--kdu', default=None, help='KDU name (whose status will be shown)') +@cli_osm.command(name="vnf-show", short_help="shows the info of a VNF instance") +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) +@click.option("--kdu", default=None, help="KDU name (whose status will be shown)") @click.pass_context def vnf_show(ctx, name, literal, filter, kdu): """shows the info of a VNF instance NAME: name or ID of the VNF instance """ + def print_kdu_status(op_info_status): - """print KDU status properly formatted - """ + """print KDU status properly formatted""" try: op_status = yaml.safe_load(op_info_status) - if "namespace" in op_status and "info" in op_status and \ - "last_deployed" in op_status["info"] and "status" in op_status["info"] and \ - "code" in op_status["info"]["status"] and "resources" in op_status["info"]["status"] and \ - "seconds" in op_status["info"]["last_deployed"]: - last_deployed_time = datetime.fromtimestamp(op_status["info"]["last_deployed"]["seconds"]).strftime("%a %b %d %I:%M:%S %Y") + if ( + "namespace" in op_status + and "info" in op_status + and "last_deployed" in op_status["info"] + and "status" in op_status["info"] + and "code" in op_status["info"]["status"] + and "resources" in op_status["info"]["status"] + and "seconds" in op_status["info"]["last_deployed"] + ): + last_deployed_time = datetime.fromtimestamp( + op_status["info"]["last_deployed"]["seconds"] + ).strftime("%a %b %d %I:%M:%S %Y") print("LAST DEPLOYED: {}".format(last_deployed_time)) print("NAMESPACE: {}".format(op_status["namespace"])) status_code = "UNKNOWN" - if op_status["info"]["status"]["code"]==1: + if op_status["info"]["status"]["code"] == 1: status_code = "DEPLOYED" print("STATUS: {}".format(status_code)) print() @@ -1317,52 +1577,56 @@ def vnf_show(ctx, name, literal, filter, kdu): logger.debug("") if kdu: if literal: - raise ClientException('"--literal" option is incompatible with "--kdu" option') + raise ClientException( + '"--literal" option is incompatible with "--kdu" option' + ) if filter: - raise ClientException('"--filter" option is incompatible with "--kdu" option') + raise ClientException( + '"--filter" option is incompatible with "--kdu" option' + ) # try: check_client_version(ctx.obj, ctx.command.name) resp = ctx.obj.vnf.get(name) if kdu: - ns_id = resp['nsr-id-ref'] - op_data={} - op_data['member_vnf_index'] = resp['member-vnf-index-ref'] - op_data['kdu_name'] = kdu - op_data['primitive'] = 'status' - op_data['primitive_params'] = {} - op_id = ctx.obj.ns.exec_op(ns_id, op_name='action', op_data=op_data, wait=False) + ns_id = resp["nsr-id-ref"] + op_data = {} + op_data["member_vnf_index"] = resp["member-vnf-index-ref"] + op_data["kdu_name"] = kdu + op_data["primitive"] = "status" + op_data["primitive_params"] = {} + op_id = ctx.obj.ns.exec_op(ns_id, op_name="action", op_data=op_data, wait=False) t = 0 - while t<30: + while t < 30: op_info = ctx.obj.ns.get_op(op_id) - if op_info['operationState'] == 'COMPLETED': - print_kdu_status(op_info['detailed-status']) + if op_info["operationState"] == "COMPLETED": + print_kdu_status(op_info["detailed-status"]) return time.sleep(5) t += 5 - print ("Could not determine KDU status") + print("Could not determine KDU status") return if literal: print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(resp.items()): if not filter or k in filter: - table.add_row([k, wrap_text(text=json.dumps(v,indent=2),width=100)]) - table.align = 'l' + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) + table.align = "l" print(table) # except ClientException as e: # print(str(e)) # exit(1) -#@cli_osm.command(name='vnf-monitoring-show') -#@click.argument('vnf_name') -#@click.pass_context -#def vnf_monitoring_show(ctx, vnf_name): +# @cli_osm.command(name='vnf-monitoring-show') +# @click.argument('vnf_name') +# @click.pass_context +# def vnf_monitoring_show(ctx, vnf_name): # try: # check_client_version(ctx.obj, ctx.command.name, 'v1') # resp = ctx.obj.vnf.get_monitoring(vnf_name) @@ -1382,10 +1646,10 @@ def vnf_show(ctx, name, literal, filter, kdu): # print(table) -#@cli_osm.command(name='ns-monitoring-show') -#@click.argument('ns_name') -#@click.pass_context -#def ns_monitoring_show(ctx, ns_name): +# @cli_osm.command(name='ns-monitoring-show') +# @click.argument('ns_name') +# @click.pass_context +# def ns_monitoring_show(ctx, ns_name): # try: # check_client_version(ctx.obj, ctx.command.name, 'v1') # resp = ctx.obj.ns.get_monitoring(ns_name) @@ -1405,12 +1669,14 @@ def vnf_show(ctx, name, literal, filter, kdu): # print(table) -@cli_osm.command(name='ns-op-show', short_help='shows the info of a NS operation') -@click.argument('id') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') +@cli_osm.command(name="ns-op-show", short_help="shows the info of a NS operation") +@click.argument("id") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") @click.pass_context def ns_op_show(ctx, id, filter, literal): """shows the detailed info of a NS operation @@ -1429,11 +1695,11 @@ def ns_op_show(ctx, id, filter, literal): print(yaml.safe_dump(op_info, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(op_info.items()): if not filter or k in filter: table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)]) - table.align = 'l' + table.align = "l" print(table) @@ -1442,7 +1708,7 @@ def nst_show(ctx, name, literal): # try: check_client_version(ctx.obj, ctx.command.name) resp = ctx.obj.nst.get(name) - #resp = ctx.obj.nst.get_individual(name) + # resp = ctx.obj.nst.get_individual(name) # except ClientException as e: # print(str(e)) # exit(1) @@ -1451,17 +1717,18 @@ def nst_show(ctx, name, literal): print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(resp.items()): table.add_row([k, wrap_text(json.dumps(v, indent=2), 100)]) - table.align = 'l' + table.align = "l" print(table) -@cli_osm.command(name='nst-show', short_help='shows the content of a Network Slice Template (NST)') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command( + name="nst-show", short_help="shows the content of a Network Slice Template (NST)" +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def nst_show1(ctx, name, literal): """shows the content of a Network Slice Template (NST) @@ -1472,10 +1739,12 @@ def nst_show1(ctx, name, literal): nst_show(ctx, name, literal) -@cli_osm.command(name='netslice-template-show', short_help='shows the content of a Network Slice Template (NST)') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.argument('name') +@cli_osm.command( + name="netslice-template-show", + short_help="shows the content of a Network Slice Template (NST)", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.argument("name") @click.pass_context def nst_show2(ctx, name, literal): """shows the content of a Network Slice Template (NST) @@ -1499,22 +1768,26 @@ def nsi_show(ctx, name, literal, filter): print(yaml.safe_dump(nsi, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(nsi.items()): if not filter or k in filter: table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) -@cli_osm.command(name='nsi-show', short_help='shows the content of a Network Slice Instance (NSI)') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command( + name="nsi-show", short_help="shows the content of a Network Slice Instance (NSI)" +) +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def nsi_show1(ctx, name, literal, filter): """shows the content of a Network Slice Instance (NSI) @@ -1525,12 +1798,17 @@ def nsi_show1(ctx, name, literal, filter): nsi_show(ctx, name, literal, filter) -@cli_osm.command(name='netslice-instance-show', short_help='shows the content of a Network Slice Instance (NSI)') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command( + name="netslice-instance-show", + short_help="shows the content of a Network Slice Instance (NSI)", +) +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def nsi_show2(ctx, name, literal, filter): """shows the content of a Network Slice Instance (NSI) @@ -1550,18 +1828,24 @@ def nsi_op_show(ctx, id, filter): # print(str(e)) # exit(1) - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(op_info.items()): if not filter or k in filter: table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) -@cli_osm.command(name='nsi-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)') -@click.argument('id') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command( + name="nsi-op-show", + short_help="shows the info of an operation over a Network Slice Instance(NSI)", +) +@click.argument("id") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def nsi_op_show1(ctx, id, filter): """shows the info of an operation over a Network Slice Instance(NSI) @@ -1572,10 +1856,16 @@ def nsi_op_show1(ctx, id, filter): nsi_op_show(ctx, id, filter) -@cli_osm.command(name='netslice-instance-op-show', short_help='shows the info of an operation over a Network Slice Instance(NSI)') -@click.argument('id') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command( + name="netslice-instance-op-show", + short_help="shows the info of an operation over a Network Slice Instance(NSI)", +) +@click.argument("id") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def nsi_op_show2(ctx, id, filter): """shows the info of an operation over a Network Slice Instance(NSI) @@ -1586,12 +1876,16 @@ def nsi_op_show2(ctx, id, filter): nsi_op_show(ctx, id, filter) -@cli_osm.command(name='pdu-show', short_help='shows the content of a Physical Deployment Unit (PDU)') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command( + name="pdu-show", short_help="shows the content of a Physical Deployment Unit (PDU)" +) +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def pdu_show(ctx, name, literal, filter): """shows the content of a Physical Deployment Unit (PDU) @@ -1610,13 +1904,13 @@ def pdu_show(ctx, name, literal, filter): print(yaml.safe_dump(pdu, indent=4, default_flow_style=False)) return - table = PrettyTable(['field', 'value']) + table = PrettyTable(["field", "value"]) for k, v in list(pdu.items()): if not filter or k in filter: table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) @@ -1624,33 +1918,47 @@ def pdu_show(ctx, name, literal, filter): # CREATE operations #################### + def nsd_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version): logger.debug("") # try: check_client_version(ctx.obj, ctx.command.name) if repo: - filename = ctx.obj.osmrepo.get_pkg('ns', filename, repo, vendor, version) + filename = ctx.obj.osmrepo.get_pkg("ns", filename, repo, vendor, version) ctx.obj.nsd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='nsd-create', short_help='creates a new NSD/NSpkg') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, # hidden=True, - help='Deprecated. Use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='The charm will not be compiled, it is assumed to already exist') -@click.option('--repo', default=None, - help='[repository]: Repository name') -@click.option('--vendor', default=None, - help='[repository]: filter by vendor]') -@click.option('--version', default='latest', - help='[repository]: filter by version. Default: latest') +@cli_osm.command(name="nsd-create", short_help="creates a new NSD/NSpkg") +@click.argument("filename") +@click.option( + "--overwrite", + "overwrite", + default=None, # hidden=True, + help="Deprecated. Use override", +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="The charm will not be compiled, it is assumed to already exist", +) +@click.option("--repo", default=None, help="[repository]: Repository name") +@click.option("--vendor", default=None, help="[repository]: filter by vendor]") +@click.option( + "--version", + default="latest", + help="[repository]: filter by version. Default: latest", +) @click.pass_context def nsd_create1(ctx, filename, overwrite, skip_charm_build, repo, vendor, version): """onboards a new NSpkg (alias of nspkg-create) (TO BE DEPRECATED) @@ -1661,25 +1969,45 @@ def nsd_create1(ctx, filename, overwrite, skip_charm_build, repo, vendor, versio If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, repo=repo, vendor=vendor, - version=version) - - -@cli_osm.command(name='nspkg-create', short_help='creates a new NSD/NSpkg') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, # hidden=True, - help='Deprecated. Use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='The charm will not be compiled, it is assumed to already exist') -@click.option('--repo', default=None, - help='[repository]: Repository name') -@click.option('--vendor', default=None, - help='[repository]: filter by vendor]') -@click.option('--version', default='latest', - help='[repository]: filter by version. Default: latest') + nsd_create( + ctx, + filename, + overwrite=overwrite, + skip_charm_build=skip_charm_build, + repo=repo, + vendor=vendor, + version=version, + ) + + +@cli_osm.command(name="nspkg-create", short_help="creates a new NSD/NSpkg") +@click.argument("filename") +@click.option( + "--overwrite", + "overwrite", + default=None, # hidden=True, + help="Deprecated. Use override", +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="The charm will not be compiled, it is assumed to already exist", +) +@click.option("--repo", default=None, help="[repository]: Repository name") +@click.option("--vendor", default=None, help="[repository]: filter by vendor]") +@click.option( + "--version", + default="latest", + help="[repository]: filter by version. Default: latest", +) @click.pass_context def nsd_pkg_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, version): """onboards a new NSpkg @@ -1689,49 +2017,106 @@ def nsd_pkg_create(ctx, filename, overwrite, skip_charm_build, repo, vendor, ver If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - nsd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, repo=repo, vendor=vendor, - version=version) - - -def vnfd_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, - repo, vendor, version): + nsd_create( + ctx, + filename, + overwrite=overwrite, + skip_charm_build=skip_charm_build, + repo=repo, + vendor=vendor, + version=version, + ) + + +def vnfd_create( + ctx, + filename, + overwrite, + skip_charm_build, + override_epa, + override_nonepa, + override_paravirt, + repo, + vendor, + version, +): logger.debug("") # try: check_client_version(ctx.obj, ctx.command.name) if repo: - filename = ctx.obj.osmrepo.get_pkg('vnf', filename, repo, vendor, version) - ctx.obj.vnfd.create(filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, - override_paravirt=override_paravirt) + filename = ctx.obj.osmrepo.get_pkg("vnf", filename, repo, vendor, version) + ctx.obj.vnfd.create( + filename, + overwrite=overwrite, + skip_charm_build=skip_charm_build, + override_epa=override_epa, + override_nonepa=override_nonepa, + override_paravirt=override_paravirt, + ) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='vnfd-create', short_help='creates a new VNFD/VNFpkg') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, - help='overwrite deprecated, use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='The charm will not be compiled, it is assumed to already exist') -@click.option('--override-epa', required=False, default=False, is_flag=True, - help='adds guest-epa parameters to all VDU') -@click.option('--override-nonepa', required=False, default=False, is_flag=True, - help='removes all guest-epa parameters from all VDU') -@click.option('--override-paravirt', required=False, default=False, is_flag=True, - help='overrides all VDU interfaces to PARAVIRT') -@click.option('--repo', default=None, - help='[repository]: Repository name') -@click.option('--vendor', default=None, - help='[repository]: filter by vendor]') -@click.option('--version', default='latest', - help='[repository]: filter by version. Default: latest') +@cli_osm.command(name="vnfd-create", short_help="creates a new VNFD/VNFpkg") +@click.argument("filename") +@click.option( + "--overwrite", "overwrite", default=None, help="overwrite deprecated, use override" +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="The charm will not be compiled, it is assumed to already exist", +) +@click.option( + "--override-epa", + required=False, + default=False, + is_flag=True, + help="adds guest-epa parameters to all VDU", +) +@click.option( + "--override-nonepa", + required=False, + default=False, + is_flag=True, + help="removes all guest-epa parameters from all VDU", +) +@click.option( + "--override-paravirt", + required=False, + default=False, + is_flag=True, + help="overrides all VDU interfaces to PARAVIRT", +) +@click.option("--repo", default=None, help="[repository]: Repository name") +@click.option("--vendor", default=None, help="[repository]: filter by vendor]") +@click.option( + "--version", + default="latest", + help="[repository]: filter by version. Default: latest", +) @click.pass_context -def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, - repo,vendor, version): +def vnfd_create1( + ctx, + filename, + overwrite, + skip_charm_build, + override_epa, + override_nonepa, + override_paravirt, + repo, + vendor, + version, +): """creates a new VNFD/VNFpkg \b FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder @@ -1739,35 +2124,82 @@ def vnfd_create1(ctx, filename, overwrite, skip_charm_build, override_epa, overr If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt, - repo=repo, vendor=vendor, version=version) - - -@cli_osm.command(name='vnfpkg-create', short_help='creates a new VNFD/VNFpkg') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, # hidden=True, - help='Deprecated. Use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='The charm will not be compiled, it is assumed to already exist') -@click.option('--override-epa', required=False, default=False, is_flag=True, - help='adds guest-epa parameters to all VDU') -@click.option('--override-nonepa', required=False, default=False, is_flag=True, - help='removes all guest-epa parameters from all VDU') -@click.option('--override-paravirt', required=False, default=False, is_flag=True, - help='overrides all VDU interfaces to PARAVIRT') -@click.option('--repo', default=None, - help='[repository]: Repository name') -@click.option('--vendor', default=None, - help='[repository]: filter by vendor]') -@click.option('--version', default='latest', - help='[repository]: filter by version. Default: latest') + vnfd_create( + ctx, + filename, + overwrite=overwrite, + skip_charm_build=skip_charm_build, + override_epa=override_epa, + override_nonepa=override_nonepa, + override_paravirt=override_paravirt, + repo=repo, + vendor=vendor, + version=version, + ) + + +@cli_osm.command(name="vnfpkg-create", short_help="creates a new VNFD/VNFpkg") +@click.argument("filename") +@click.option( + "--overwrite", + "overwrite", + default=None, # hidden=True, + help="Deprecated. Use override", +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="The charm will not be compiled, it is assumed to already exist", +) +@click.option( + "--override-epa", + required=False, + default=False, + is_flag=True, + help="adds guest-epa parameters to all VDU", +) +@click.option( + "--override-nonepa", + required=False, + default=False, + is_flag=True, + help="removes all guest-epa parameters from all VDU", +) +@click.option( + "--override-paravirt", + required=False, + default=False, + is_flag=True, + help="overrides all VDU interfaces to PARAVIRT", +) +@click.option("--repo", default=None, help="[repository]: Repository name") +@click.option("--vendor", default=None, help="[repository]: filter by vendor]") +@click.option( + "--version", + default="latest", + help="[repository]: filter by version. Default: latest", +) @click.pass_context -def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, - repo, vendor, version): +def vnfd_create2( + ctx, + filename, + overwrite, + skip_charm_build, + override_epa, + override_nonepa, + override_paravirt, + repo, + vendor, + version, +): """creates a new VNFD/VNFpkg \b FILENAME: NF Package tar.gz file, NF Descriptor YAML file or NF Package folder @@ -1775,34 +2207,82 @@ def vnfd_create2(ctx, filename, overwrite, skip_charm_build, override_epa, overr If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt, - repo=repo, vendor=vendor, version=version) - -@cli_osm.command(name='nfpkg-create', short_help='creates a new NFpkg') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, # hidden=True, - help='Deprecated. Use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='The charm will not be compiled, it is assumed to already exist') -@click.option('--override-epa', required=False, default=False, is_flag=True, - help='adds guest-epa parameters to all VDU') -@click.option('--override-nonepa', required=False, default=False, is_flag=True, - help='removes all guest-epa parameters from all VDU') -@click.option('--override-paravirt', required=False, default=False, is_flag=True, - help='overrides all VDU interfaces to PARAVIRT') -@click.option('--repo', default=None, - help='[repository]: Repository name') -@click.option('--vendor', default=None, - help='[repository]: filter by vendor]') -@click.option('--version', default='latest', - help='[repository]: filter by version. Default: latest') + vnfd_create( + ctx, + filename, + overwrite=overwrite, + skip_charm_build=skip_charm_build, + override_epa=override_epa, + override_nonepa=override_nonepa, + override_paravirt=override_paravirt, + repo=repo, + vendor=vendor, + version=version, + ) + + +@cli_osm.command(name="nfpkg-create", short_help="creates a new NFpkg") +@click.argument("filename") +@click.option( + "--overwrite", + "overwrite", + default=None, # hidden=True, + help="Deprecated. Use override", +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="The charm will not be compiled, it is assumed to already exist", +) +@click.option( + "--override-epa", + required=False, + default=False, + is_flag=True, + help="adds guest-epa parameters to all VDU", +) +@click.option( + "--override-nonepa", + required=False, + default=False, + is_flag=True, + help="removes all guest-epa parameters from all VDU", +) +@click.option( + "--override-paravirt", + required=False, + default=False, + is_flag=True, + help="overrides all VDU interfaces to PARAVIRT", +) +@click.option("--repo", default=None, help="[repository]: Repository name") +@click.option("--vendor", default=None, help="[repository]: filter by vendor]") +@click.option( + "--version", + default="latest", + help="[repository]: filter by version. Default: latest", +) @click.pass_context -def nfpkg_create(ctx, filename, overwrite, skip_charm_build, override_epa, override_nonepa, override_paravirt, - repo, vendor, version): +def nfpkg_create( + ctx, + filename, + overwrite, + skip_charm_build, + override_epa, + override_nonepa, + override_paravirt, + repo, + vendor, + version, +): """creates a new NFpkg \b @@ -1811,62 +2291,75 @@ def nfpkg_create(ctx, filename, overwrite, skip_charm_build, override_epa, overr If FILENAME is an NF Package folder, it is built and then onboarded. """ logger.debug("") - vnfd_create(ctx, filename, overwrite=overwrite, skip_charm_build=skip_charm_build, - override_epa=override_epa, override_nonepa=override_nonepa, override_paravirt=override_paravirt, - repo=repo, vendor=vendor, version=version) - - -@cli_osm.command(name='ns-create', short_help='creates a new Network Service instance') -@click.option('--ns_name', - prompt=True, help='name of the NS instance') -@click.option('--nsd_name', - prompt=True, help='name of the NS descriptor') -@click.option('--vim_account', - prompt=True, help='default VIM account id or name for the deployment') -@click.option('--admin_status', - default='ENABLED', - help='administration status') -@click.option('--ssh_keys', - default=None, - help='comma separated list of public key files to inject to vnfs') -@click.option('--config', - default=None, - help='ns specific yaml configuration') -@click.option('--config_file', - default=None, - help='ns specific yaml configuration file') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') + vnfd_create( + ctx, + filename, + overwrite=overwrite, + skip_charm_build=skip_charm_build, + override_epa=override_epa, + override_nonepa=override_nonepa, + override_paravirt=override_paravirt, + repo=repo, + vendor=vendor, + version=version, + ) + + +@cli_osm.command(name="ns-create", short_help="creates a new Network Service instance") +@click.option("--ns_name", prompt=True, help="name of the NS instance") +@click.option("--nsd_name", prompt=True, help="name of the NS descriptor") +@click.option( + "--vim_account", + prompt=True, + help="default VIM account id or name for the deployment", +) +@click.option("--admin_status", default="ENABLED", help="administration status") +@click.option( + "--ssh_keys", + default=None, + help="comma separated list of public key files to inject to vnfs", +) +@click.option("--config", default=None, help="ns specific yaml configuration") +@click.option("--config_file", default=None, help="ns specific yaml configuration file") +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def ns_create(ctx, - nsd_name, - ns_name, - vim_account, - admin_status, - ssh_keys, - config, - config_file, - wait): +def ns_create( + ctx, + nsd_name, + ns_name, + vim_account, + admin_status, + ssh_keys, + config, + config_file, + wait, +): """creates a new NS instance""" logger.debug("") # try: if config_file: - check_client_version(ctx.obj, '--config_file') + check_client_version(ctx.obj, "--config_file") if config: - raise ClientException('"--config" option is incompatible with "--config_file" option') - with open(config_file, 'r') as cf: - config=cf.read() + raise ClientException( + '"--config" option is incompatible with "--config_file" option' + ) + with open(config_file, "r") as cf: + config = cf.read() ctx.obj.ns.create( nsd_name, ns_name, config=config, ssh_keys=ssh_keys, account=vim_account, - wait=wait) + wait=wait, + ) # except ClientException as e: # print(str(e)) # exit(1) @@ -1882,13 +2375,23 @@ def nst_create(ctx, filename, overwrite): # exit(1) -@cli_osm.command(name='nst-create', short_help='creates a new Network Slice Template (NST)') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, # hidden=True, - help='Deprecated. Use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') +@cli_osm.command( + name="nst-create", short_help="creates a new Network Slice Template (NST)" +) +@click.argument("filename") +@click.option( + "--overwrite", + "overwrite", + default=None, # hidden=True, + help="Deprecated. Use override", +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) @click.pass_context def nst_create1(ctx, filename, overwrite): """creates a new Network Slice Template (NST) @@ -1899,13 +2402,24 @@ def nst_create1(ctx, filename, overwrite): nst_create(ctx, filename, overwrite) -@cli_osm.command(name='netslice-template-create', short_help='creates a new Network Slice Template (NST)') -@click.argument('filename') -@click.option('--overwrite', 'overwrite', default=None, # hidden=True, - help='Deprecated. Use override') -@click.option('--override', 'overwrite', default=None, - help='overrides fields in descriptor, format: ' - '"key1.key2...=value[;key3...=value;...]"') +@cli_osm.command( + name="netslice-template-create", + short_help="creates a new Network Slice Template (NST)", +) +@click.argument("filename") +@click.option( + "--overwrite", + "overwrite", + default=None, # hidden=True, + help="Deprecated. Use override", +) +@click.option( + "--override", + "overwrite", + default=None, + help="overrides fields in descriptor, format: " + '"key1.key2...=value[;key3...=value;...]"', +) @click.pass_context def nst_create2(ctx, filename, overwrite): """creates a new Network Slice Template (NST) @@ -1916,100 +2430,151 @@ def nst_create2(ctx, filename, overwrite): nst_create(ctx, filename, overwrite) -def nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait): +def nsi_create( + ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait +): """creates a new Network Slice Instance (NSI)""" logger.debug("") # try: check_client_version(ctx.obj, ctx.command.name) if config_file: if config: - raise ClientException('"--config" option is incompatible with "--config_file" option') - with open(config_file, 'r') as cf: - config=cf.read() - ctx.obj.nsi.create(nst_name, nsi_name, config=config, ssh_keys=ssh_keys, - account=vim_account, wait=wait) + raise ClientException( + '"--config" option is incompatible with "--config_file" option' + ) + with open(config_file, "r") as cf: + config = cf.read() + ctx.obj.nsi.create( + nst_name, + nsi_name, + config=config, + ssh_keys=ssh_keys, + account=vim_account, + wait=wait, + ) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='nsi-create', short_help='creates a new Network Slice Instance') -@click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance') -@click.option('--nst_name', prompt=True, help='name of the Network Slice Template') -@click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment') -@click.option('--ssh_keys', default=None, - help='comma separated list of keys to inject to vnfs') -@click.option('--config', default=None, - help='Netslice specific yaml configuration:\n' - 'netslice_subnet: [\n' - 'id: TEXT, vim_account: TEXT,\n' - 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n' - 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n' - 'additionalParamsForNsi: {param: value, ...}\n' - 'additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n' - '],\n' - 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]' - ) -@click.option('--config_file', - default=None, - help='nsi specific yaml configuration file') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') +@cli_osm.command(name="nsi-create", short_help="creates a new Network Slice Instance") +@click.option("--nsi_name", prompt=True, help="name of the Network Slice Instance") +@click.option("--nst_name", prompt=True, help="name of the Network Slice Template") +@click.option( + "--vim_account", + prompt=True, + help="default VIM account id or name for the deployment", +) +@click.option( + "--ssh_keys", default=None, help="comma separated list of keys to inject to vnfs" +) +@click.option( + "--config", + default=None, + help="Netslice specific yaml configuration:\n" + "netslice_subnet: [\n" + "id: TEXT, vim_account: TEXT,\n" + "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n" + "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]\n" + "additionalParamsForNsi: {param: value, ...}\n" + "additionalParamsForsubnet: [{id: SUBNET_ID, additionalParamsForNs: {}, additionalParamsForVnf: {}}]\n" + "],\n" + "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]", +) +@click.option( + "--config_file", default=None, help="nsi specific yaml configuration file" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def nsi_create1(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait): +def nsi_create1( + ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait +): """creates a new Network Slice Instance (NSI)""" logger.debug("") - nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait) - - -@cli_osm.command(name='netslice-instance-create', short_help='creates a new Network Slice Instance') -@click.option('--nsi_name', prompt=True, help='name of the Network Slice Instance') -@click.option('--nst_name', prompt=True, help='name of the Network Slice Template') -@click.option('--vim_account', prompt=True, help='default VIM account id or name for the deployment') -@click.option('--ssh_keys', default=None, - help='comma separated list of keys to inject to vnfs') -@click.option('--config', default=None, - help='Netslice specific yaml configuration:\n' - 'netslice_subnet: [\n' - 'id: TEXT, vim_account: TEXT,\n' - 'vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n' - 'vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]' - '],\n' - 'netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]' - ) -@click.option('--config_file', - default=None, - help='nsi specific yaml configuration file') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') + nsi_create( + ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait + ) + + +@cli_osm.command( + name="netslice-instance-create", short_help="creates a new Network Slice Instance" +) +@click.option("--nsi_name", prompt=True, help="name of the Network Slice Instance") +@click.option("--nst_name", prompt=True, help="name of the Network Slice Template") +@click.option( + "--vim_account", + prompt=True, + help="default VIM account id or name for the deployment", +) +@click.option( + "--ssh_keys", default=None, help="comma separated list of keys to inject to vnfs" +) +@click.option( + "--config", + default=None, + help="Netslice specific yaml configuration:\n" + "netslice_subnet: [\n" + "id: TEXT, vim_account: TEXT,\n" + "vnf: [member-vnf-index: TEXT, vim_account: TEXT]\n" + "vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]" + "],\n" + "netslice-vld: [name: TEXT, vim-network-name: TEXT or DICT with vim_account, vim_net entries]", +) +@click.option( + "--config_file", default=None, help="nsi specific yaml configuration file" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def nsi_create2(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait): +def nsi_create2( + ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait +): """creates a new Network Slice Instance (NSI)""" logger.debug("") - nsi_create(ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait) - - -@cli_osm.command(name='pdu-create', short_help='adds a new Physical Deployment Unit to the catalog') -@click.option('--name', help='name of the Physical Deployment Unit') -@click.option('--pdu_type', help='type of PDU (e.g. router, firewall, FW001)') -@click.option('--interface', - help='interface(s) of the PDU: name=,mgmt=,ip-address='+ - '[,type=][,mac-address=][,vim-network-name=]', - multiple=True) -@click.option('--description', help='human readable description') -@click.option('--vim_account', help='list of VIM accounts (in the same VIM) that can reach this PDU', multiple=True) -@click.option('--descriptor_file', default=None, - help='PDU descriptor file (as an alternative to using the other arguments') + nsi_create( + ctx, nst_name, nsi_name, vim_account, ssh_keys, config, config_file, wait=wait + ) + + +@cli_osm.command( + name="pdu-create", short_help="adds a new Physical Deployment Unit to the catalog" +) +@click.option("--name", help="name of the Physical Deployment Unit") +@click.option("--pdu_type", help="type of PDU (e.g. router, firewall, FW001)") +@click.option( + "--interface", + help="interface(s) of the PDU: name=,mgmt=,ip-address=" + + "[,type=][,mac-address=][,vim-network-name=]", + multiple=True, +) +@click.option("--description", help="human readable description") +@click.option( + "--vim_account", + help="list of VIM accounts (in the same VIM) that can reach this PDU", + multiple=True, +) +@click.option( + "--descriptor_file", + default=None, + help="PDU descriptor file (as an alternative to using the other arguments", +) @click.pass_context -def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descriptor_file): +def pdu_create( + ctx, name, pdu_type, interface, description, vim_account, descriptor_file +): """creates a new Physical Deployment Unit (PDU)""" logger.debug("") # try: @@ -2017,25 +2582,37 @@ def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descrip pdu = {} if not descriptor_file: if not name: - raise ClientException('in absence of descriptor file, option "--name" is mandatory') + raise ClientException( + 'in absence of descriptor file, option "--name" is mandatory' + ) if not pdu_type: - raise ClientException('in absence of descriptor file, option "--pdu_type" is mandatory') + raise ClientException( + 'in absence of descriptor file, option "--pdu_type" is mandatory' + ) if not interface: - raise ClientException('in absence of descriptor file, option "--interface" is mandatory (at least once)') + raise ClientException( + 'in absence of descriptor file, option "--interface" is mandatory (at least once)' + ) if not vim_account: - raise ClientException('in absence of descriptor file, option "--vim_account" is mandatory (at least once)') + raise ClientException( + 'in absence of descriptor file, option "--vim_account" is mandatory (at least once)' + ) else: - with open(descriptor_file, 'r') as df: + with open(descriptor_file, "r") as df: pdu = yaml.safe_load(df.read()) - if name: pdu["name"] = name - if pdu_type: pdu["type"] = pdu_type - if description: pdu["description"] = description - if vim_account: pdu["vim_accounts"] = vim_account + if name: + pdu["name"] = name + if pdu_type: + pdu["type"] = pdu_type + if description: + pdu["description"] = description + if vim_account: + pdu["vim_accounts"] = vim_account if interface: ifaces_list = [] for iface in interface: - new_iface={k:v for k,v in [i.split('=') for i in iface.split(',')]} - new_iface["mgmt"] = (new_iface.get("mgmt","false").lower() == "true") + new_iface = {k: v for k, v in [i.split("=") for i in iface.split(",")]} + new_iface["mgmt"] = new_iface.get("mgmt", "false").lower() == "true" ifaces_list.append(new_iface) pdu["interfaces"] = ifaces_list ctx.obj.pdu.create(pdu) @@ -2048,6 +2625,7 @@ def pdu_create(ctx, name, pdu_type, interface, description, vim_account, descrip # UPDATE operations #################### + def nsd_update(ctx, name, content): logger.debug("") # try: @@ -2058,10 +2636,13 @@ def nsd_update(ctx, name, content): # exit(1) -@cli_osm.command(name='nsd-update', short_help='updates a NSD/NSpkg') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the NSD/NSpkg replacing the current one') +@cli_osm.command(name="nsd-update", short_help="updates a NSD/NSpkg") +@click.argument("name") +@click.option( + "--content", + default=None, + help="filename with the NSD/NSpkg replacing the current one", +) @click.pass_context def nsd_update1(ctx, name, content): """updates a NSD/NSpkg @@ -2072,10 +2653,13 @@ def nsd_update1(ctx, name, content): nsd_update(ctx, name, content) -@cli_osm.command(name='nspkg-update', short_help='updates a NSD/NSpkg') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the NSD/NSpkg replacing the current one') +@cli_osm.command(name="nspkg-update", short_help="updates a NSD/NSpkg") +@click.argument("name") +@click.option( + "--content", + default=None, + help="filename with the NSD/NSpkg replacing the current one", +) @click.pass_context def nsd_update2(ctx, name, content): """updates a NSD/NSpkg @@ -2096,10 +2680,13 @@ def vnfd_update(ctx, name, content): # exit(1) -@cli_osm.command(name='vnfd-update', short_help='updates a new VNFD/VNFpkg') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the VNFD/VNFpkg replacing the current one') +@cli_osm.command(name="vnfd-update", short_help="updates a new VNFD/VNFpkg") +@click.argument("name") +@click.option( + "--content", + default=None, + help="filename with the VNFD/VNFpkg replacing the current one", +) @click.pass_context def vnfd_update1(ctx, name, content): """updates a VNFD/VNFpkg @@ -2110,10 +2697,13 @@ def vnfd_update1(ctx, name, content): vnfd_update(ctx, name, content) -@cli_osm.command(name='vnfpkg-update', short_help='updates a VNFD/VNFpkg') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the VNFD/VNFpkg replacing the current one') +@cli_osm.command(name="vnfpkg-update", short_help="updates a VNFD/VNFpkg") +@click.argument("name") +@click.option( + "--content", + default=None, + help="filename with the VNFD/VNFpkg replacing the current one", +) @click.pass_context def vnfd_update2(ctx, name, content): """updates a VNFD/VNFpkg @@ -2124,10 +2714,11 @@ def vnfd_update2(ctx, name, content): vnfd_update(ctx, name, content) -@cli_osm.command(name='nfpkg-update', short_help='updates a NFpkg') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the NFpkg replacing the current one') +@cli_osm.command(name="nfpkg-update", short_help="updates a NFpkg") +@click.argument("name") +@click.option( + "--content", default=None, help="filename with the NFpkg replacing the current one" +) @click.pass_context def nfpkg_update(ctx, name, content): """updates a NFpkg @@ -2148,10 +2739,13 @@ def nst_update(ctx, name, content): # exit(1) -@cli_osm.command(name='nst-update', short_help='updates a Network Slice Template (NST)') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the NST/NSTpkg replacing the current one') +@cli_osm.command(name="nst-update", short_help="updates a Network Slice Template (NST)") +@click.argument("name") +@click.option( + "--content", + default=None, + help="filename with the NST/NSTpkg replacing the current one", +) @click.pass_context def nst_update1(ctx, name, content): """updates a Network Slice Template (NST) @@ -2162,10 +2756,15 @@ def nst_update1(ctx, name, content): nst_update(ctx, name, content) -@cli_osm.command(name='netslice-template-update', short_help='updates a Network Slice Template (NST)') -@click.argument('name') -@click.option('--content', default=None, - help='filename with the NST/NSTpkg replacing the current one') +@cli_osm.command( + name="netslice-template-update", short_help="updates a Network Slice Template (NST)" +) +@click.argument("name") +@click.option( + "--content", + default=None, + help="filename with the NST/NSTpkg replacing the current one", +) @click.pass_context def nst_update2(ctx, name, content): """updates a Network Slice Template (NST) @@ -2180,22 +2779,25 @@ def nst_update2(ctx, name, content): # DELETE operations #################### + def nsd_delete(ctx, name, force): logger.debug("") # try: if not force: ctx.obj.nsd.delete(name) else: - check_client_version(ctx.obj, '--force') + check_client_version(ctx.obj, "--force") ctx.obj.nsd.delete(name, force) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='nsd-delete', short_help='deletes a NSD/NSpkg') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="nsd-delete", short_help="deletes a NSD/NSpkg") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def nsd_delete1(ctx, name, force): """deletes a NSD/NSpkg @@ -2206,9 +2808,11 @@ def nsd_delete1(ctx, name, force): nsd_delete(ctx, name, force) -@cli_osm.command(name='nspkg-delete', short_help='deletes a NSD/NSpkg') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="nspkg-delete", short_help="deletes a NSD/NSpkg") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def nsd_delete2(ctx, name, force): """deletes a NSD/NSpkg @@ -2225,16 +2829,18 @@ def vnfd_delete(ctx, name, force): if not force: ctx.obj.vnfd.delete(name) else: - check_client_version(ctx.obj, '--force') + check_client_version(ctx.obj, "--force") ctx.obj.vnfd.delete(name, force) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='vnfd-delete', short_help='deletes a VNFD/VNFpkg') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="vnfd-delete", short_help="deletes a VNFD/VNFpkg") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def vnfd_delete1(ctx, name, force): """deletes a VNFD/VNFpkg @@ -2245,9 +2851,11 @@ def vnfd_delete1(ctx, name, force): vnfd_delete(ctx, name, force) -@cli_osm.command(name='vnfpkg-delete', short_help='deletes a VNFD/VNFpkg') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="vnfpkg-delete", short_help="deletes a VNFD/VNFpkg") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def vnfd_delete2(ctx, name, force): """deletes a VNFD/VNFpkg @@ -2258,9 +2866,11 @@ def vnfd_delete2(ctx, name, force): vnfd_delete(ctx, name, force) -@cli_osm.command(name='nfpkg-delete', short_help='deletes a NFpkg') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="nfpkg-delete", short_help="deletes a NFpkg") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def nfpkg_delete(ctx, name, force): """deletes a NFpkg @@ -2271,18 +2881,25 @@ def nfpkg_delete(ctx, name, force): vnfd_delete(ctx, name, force) -@cli_osm.command(name='ns-delete', short_help='deletes a NS instance') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') -@click.option('--config', default=None, - help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: " - "600, skip_terminate_primitives: True}'") -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') +@cli_osm.command(name="ns-delete", short_help="deletes a NS instance") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) +@click.option( + "--config", + default=None, + help="specific yaml configuration for the termination, e.g. '{autoremove: False, timeout_ns_terminate: " + "600, skip_terminate_primitives: True}'", +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context def ns_delete(ctx, name, force, config, wait): """deletes a NS instance @@ -2294,7 +2911,7 @@ def ns_delete(ctx, name, force, config, wait): if not force: ctx.obj.ns.delete(name, config=config, wait=wait) else: - check_client_version(ctx.obj, '--force') + check_client_version(ctx.obj, "--force") ctx.obj.ns.delete(name, force, config=config, wait=wait) # except ClientException as e: # print(str(e)) @@ -2311,9 +2928,11 @@ def nst_delete(ctx, name, force): # exit(1) -@cli_osm.command(name='nst-delete', short_help='deletes a Network Slice Template (NST)') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="nst-delete", short_help="deletes a Network Slice Template (NST)") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def nst_delete1(ctx, name, force): """deletes a Network Slice Template (NST) @@ -2324,9 +2943,13 @@ def nst_delete1(ctx, name, force): nst_delete(ctx, name, force) -@cli_osm.command(name='netslice-template-delete', short_help='deletes a Network Slice Template (NST)') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command( + name="netslice-template-delete", short_help="deletes a Network Slice Template (NST)" +) +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def nst_delete2(ctx, name, force): """deletes a Network Slice Template (NST) @@ -2347,15 +2970,19 @@ def nsi_delete(ctx, name, force, wait): # exit(1) -@cli_osm.command(name='nsi-delete', short_help='deletes a Network Slice Instance (NSI)') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') +@cli_osm.command(name="nsi-delete", short_help="deletes a Network Slice Instance (NSI)") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context def nsi_delete1(ctx, name, force, wait): """deletes a Network Slice Instance (NSI) @@ -2366,9 +2993,13 @@ def nsi_delete1(ctx, name, force, wait): nsi_delete(ctx, name, force, wait=wait) -@cli_osm.command(name='netslice-instance-delete', short_help='deletes a Network Slice Instance (NSI)') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command( + name="netslice-instance-delete", short_help="deletes a Network Slice Instance (NSI)" +) +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def nsi_delete2(ctx, name, force, wait): """deletes a Network Slice Instance (NSI) @@ -2379,9 +3010,13 @@ def nsi_delete2(ctx, name, force, wait): nsi_delete(ctx, name, force, wait=wait) -@cli_osm.command(name='pdu-delete', short_help='deletes a Physical Deployment Unit (PDU)') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command( + name="pdu-delete", short_help="deletes a Physical Deployment Unit (PDU)" +) +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) @click.pass_context def pdu_delete(ctx, name, force): """deletes a Physical Deployment Unit (PDU) @@ -2401,69 +3036,70 @@ def pdu_delete(ctx, name, force): # VIM operations ################# -@cli_osm.command(name='vim-create', short_help='creates a new VIM account') -@click.option('--name', - prompt=True, - help='Name to create datacenter') -@click.option('--user', - prompt=True, - help='VIM username') -@click.option('--password', - prompt=True, - hide_input=True, - confirmation_prompt=True, - help='VIM password') -@click.option('--auth_url', - prompt=True, - help='VIM url') -@click.option('--tenant', - prompt=True, - help='VIM tenant name') -@click.option('--config', - default=None, - help='VIM specific config parameters') -@click.option('--account_type', - default='openstack', - help='VIM type') -@click.option('--description', - default=None, - help='human readable description') -@click.option('--sdn_controller', default=None, help='Name or id of the SDN controller associated to this VIM account') -@click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports") -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') + +@cli_osm.command(name="vim-create", short_help="creates a new VIM account") +@click.option("--name", prompt=True, help="Name to create datacenter") +@click.option("--user", prompt=True, help="VIM username") +@click.option( + "--password", + prompt=True, + hide_input=True, + confirmation_prompt=True, + help="VIM password", +) +@click.option("--auth_url", prompt=True, help="VIM url") +@click.option("--tenant", prompt=True, help="VIM tenant name") +@click.option("--config", default=None, help="VIM specific config parameters") +@click.option("--account_type", default="openstack", help="VIM type") +@click.option("--description", default=None, help="human readable description") +@click.option( + "--sdn_controller", + default=None, + help="Name or id of the SDN controller associated to this VIM account", +) +@click.option( + "--sdn_port_mapping", + default=None, + help="File describing the port mapping between compute nodes' ports and switch ports", +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def vim_create(ctx, - name, - user, - password, - auth_url, - tenant, - config, - account_type, - description, - sdn_controller, - sdn_port_mapping, - wait): +def vim_create( + ctx, + name, + user, + password, + auth_url, + tenant, + config, + account_type, + description, + sdn_controller, + sdn_port_mapping, + wait, +): """creates a new VIM account""" logger.debug("") # try: if sdn_controller: - check_client_version(ctx.obj, '--sdn_controller') + check_client_version(ctx.obj, "--sdn_controller") if sdn_port_mapping: - check_client_version(ctx.obj, '--sdn_port_mapping') + check_client_version(ctx.obj, "--sdn_port_mapping") vim = {} - vim['vim-username'] = user - vim['vim-password'] = password - vim['vim-url'] = auth_url - vim['vim-tenant-name'] = tenant - vim['vim-type'] = account_type - vim['description'] = description - vim['config'] = config + vim["vim-username"] = user + vim["vim-password"] = password + vim["vim-url"] = auth_url + vim["vim-tenant-name"] = tenant + vim["vim-type"] = account_type + vim["description"] = description + vim["config"] = config if sdn_controller or sdn_port_mapping: ctx.obj.vim.create(name, vim, sdn_controller, sdn_port_mapping, wait=wait) else: @@ -2473,39 +3109,51 @@ def vim_create(ctx, # exit(1) -@cli_osm.command(name='vim-update', short_help='updates a VIM account') -@click.argument('name') -@click.option('--newname', help='New name for the VIM account') -@click.option('--user', help='VIM username') -@click.option('--password', help='VIM password') -@click.option('--auth_url', help='VIM url') -@click.option('--tenant', help='VIM tenant name') -@click.option('--config', help='VIM specific config parameters') -@click.option('--account_type', help='VIM type') -@click.option('--description', help='human readable description') -@click.option('--sdn_controller', default=None, help='Name or id of the SDN controller to be associated with this VIM' - 'account. Use empty string to disassociate') -@click.option('--sdn_port_mapping', default=None, help="File describing the port mapping between compute nodes' ports and switch ports") -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') +@cli_osm.command(name="vim-update", short_help="updates a VIM account") +@click.argument("name") +@click.option("--newname", help="New name for the VIM account") +@click.option("--user", help="VIM username") +@click.option("--password", help="VIM password") +@click.option("--auth_url", help="VIM url") +@click.option("--tenant", help="VIM tenant name") +@click.option("--config", help="VIM specific config parameters") +@click.option("--account_type", help="VIM type") +@click.option("--description", help="human readable description") +@click.option( + "--sdn_controller", + default=None, + help="Name or id of the SDN controller to be associated with this VIM" + "account. Use empty string to disassociate", +) +@click.option( + "--sdn_port_mapping", + default=None, + help="File describing the port mapping between compute nodes' ports and switch ports", +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def vim_update(ctx, - name, - newname, - user, - password, - auth_url, - tenant, - config, - account_type, - description, - sdn_controller, - sdn_port_mapping, - wait): +def vim_update( + ctx, + name, + newname, + user, + password, + auth_url, + tenant, + config, + account_type, + description, + sdn_controller, + sdn_port_mapping, + wait, +): """updates a VIM account NAME: name or ID of the VIM account @@ -2514,29 +3162,41 @@ def vim_update(ctx, # try: check_client_version(ctx.obj, ctx.command.name) vim = {} - if newname: vim['name'] = newname - if user: vim['vim_user'] = user - if password: vim['vim_password'] = password - if auth_url: vim['vim_url'] = auth_url - if tenant: vim['vim-tenant-name'] = tenant - if account_type: vim['vim_type'] = account_type - if description: vim['description'] = description - if config: vim['config'] = config + if newname: + vim["name"] = newname + if user: + vim["vim_user"] = user + if password: + vim["vim_password"] = password + if auth_url: + vim["vim_url"] = auth_url + if tenant: + vim["vim-tenant-name"] = tenant + if account_type: + vim["vim_type"] = account_type + if description: + vim["description"] = description + if config: + vim["config"] = config ctx.obj.vim.update(name, vim, sdn_controller, sdn_port_mapping, wait=wait) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='vim-delete', short_help='deletes a VIM account') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') +@cli_osm.command(name="vim-delete", short_help="deletes a VIM account") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context def vim_delete(ctx, name, force, wait): """deletes a VIM account @@ -2548,64 +3208,85 @@ def vim_delete(ctx, name, force, wait): if not force: ctx.obj.vim.delete(name, wait=wait) else: - check_client_version(ctx.obj, '--force') + check_client_version(ctx.obj, "--force") ctx.obj.vim.delete(name, force, wait=wait) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='vim-list', short_help='list all VIM accounts') -#@click.option('--ro_update/--no_ro_update', +@cli_osm.command(name="vim-list", short_help="list all VIM accounts") +# @click.option('--ro_update/--no_ro_update', # default=False, # help='update list from RO') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the VIM accounts matching the filter') -@click.option('--long', is_flag=True, - help='get more details of the NS (project, vim, deployment status, configuration status.') +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the VIM accounts matching the filter", +) +@click.option( + "--long", + is_flag=True, + help="get more details of the NS (project, vim, deployment status, configuration status.", +) @click.pass_context def vim_list(ctx, filter, long): """list all VIM accounts""" logger.debug("") if filter: - filter='&'.join(filter) - check_client_version(ctx.obj, '--filter') -# if ro_update: -# check_client_version(ctx.obj, '--ro_update', 'v1') + filter = "&".join(filter) + check_client_version(ctx.obj, "--filter") + # if ro_update: + # check_client_version(ctx.obj, '--ro_update', 'v1') fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname == 'osmclient.sol005.client.Client': + if fullclassname == "osmclient.sol005.client.Client": resp = ctx.obj.vim.list(filter) -# else: -# resp = ctx.obj.vim.list(ro_update) + # else: + # resp = ctx.obj.vim.list(ro_update) if long: - table = PrettyTable(['vim name', 'uuid', 'project', 'operational state', 'error details']) + table = PrettyTable( + ["vim name", "uuid", "project", "operational state", "error details"] + ) project_list = ctx.obj.project.list() else: - table = PrettyTable(['vim name', 'uuid', 'operational state']) + table = PrettyTable(["vim name", "uuid", "operational state"]) for vim in resp: if long: - if 'vim_password' in vim: - vim['vim_password']='********' - logger.debug('VIM details: {}'.format(yaml.safe_dump(vim))) - vim_state = vim['_admin'].get('operationalState', '-') - error_details = 'N/A' - if vim_state == 'ERROR': - error_details = vim['_admin'].get('detailed-status', 'Not found') + if "vim_password" in vim: + vim["vim_password"] = "********" + logger.debug("VIM details: {}".format(yaml.safe_dump(vim))) + vim_state = vim["_admin"].get("operationalState", "-") + error_details = "N/A" + if vim_state == "ERROR": + error_details = vim["_admin"].get("detailed-status", "Not found") project_id, project_name = get_project(project_list, vim) - #project_info = '{} ({})'.format(project_name, project_id) + # project_info = '{} ({})'.format(project_name, project_id) project_info = project_name - table.add_row([vim['name'], vim['uuid'], project_info, - vim_state, wrap_text(text=error_details, width=80)]) + table.add_row( + [ + vim["name"], + vim["uuid"], + project_info, + vim_state, + wrap_text(text=error_details, width=80), + ] + ) else: - table.add_row([vim['name'], vim['uuid'], vim['_admin'].get('operationalState', '-')]) - table.align = 'l' + table.add_row( + [vim["name"], vim["uuid"], vim["_admin"].get("operationalState", "-")] + ) + table.align = "l" print(table) -@cli_osm.command(name='vim-show', short_help='shows the details of a VIM account') -@click.argument('name') -@click.option('--filter', multiple=True, - help='restricts the information to the fields in the filter') +@cli_osm.command(name="vim-show", short_help="shows the details of a VIM account") +@click.argument("name") +@click.option( + "--filter", + multiple=True, + help="restricts the information to the fields in the filter", +) @click.pass_context def vim_show(ctx, name, filter): """shows the details of a VIM account @@ -2615,17 +3296,17 @@ def vim_show(ctx, name, filter): logger.debug("") # try: resp = ctx.obj.vim.get(name) - if 'vim_password' in resp: - resp['vim_password']='********' + if "vim_password" in resp: + resp["vim_password"] = "********" # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in list(resp.items()): if not filter or k in filter: - table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)]) - table.align = 'l' + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) + table.align = "l" print(table) @@ -2633,48 +3314,45 @@ def vim_show(ctx, name, filter): # WIM operations #################### -@cli_osm.command(name='wim-create', short_help='creates a new WIM account') -@click.option('--name', - prompt=True, - help='Name for the WIM account') -@click.option('--user', - help='WIM username') -@click.option('--password', - help='WIM password') -@click.option('--url', - prompt=True, - help='WIM url') + +@cli_osm.command(name="wim-create", short_help="creates a new WIM account") +@click.option("--name", prompt=True, help="Name for the WIM account") +@click.option("--user", help="WIM username") +@click.option("--password", help="WIM password") +@click.option("--url", prompt=True, help="WIM url") # @click.option('--tenant', # help='wIM tenant name') -@click.option('--config', - default=None, - help='WIM specific config parameters') -@click.option('--wim_type', - help='WIM type') -@click.option('--description', - default=None, - help='human readable description') -@click.option('--wim_port_mapping', default=None, - help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge " - "(WAN service endpoint id and info)") -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it ' - 'until the operation is completed, or timeout') +@click.option("--config", default=None, help="WIM specific config parameters") +@click.option("--wim_type", help="WIM type") +@click.option("--description", default=None, help="human readable description") +@click.option( + "--wim_port_mapping", + default=None, + help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge " + "(WAN service endpoint id and info)", +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def wim_create(ctx, - name, - user, - password, - url, - # tenant, - config, - wim_type, - description, - wim_port_mapping, - wait): +def wim_create( + ctx, + name, + user, + password, + url, + # tenant, + config, + wim_type, + description, + wim_port_mapping, + wait, +): """creates a new WIM account""" logger.debug("") # try: @@ -2684,48 +3362,60 @@ def wim_create(ctx, # if sdn_port_mapping: # check_client_version(ctx.obj, '--sdn_port_mapping') wim = {} - if user: wim['user'] = user - if password: wim['password'] = password - if url: wim['wim_url'] = url + if user: + wim["user"] = user + if password: + wim["password"] = password + if url: + wim["wim_url"] = url # if tenant: wim['tenant'] = tenant - wim['wim_type'] = wim_type - if description: wim['description'] = description - if config: wim['config'] = config + wim["wim_type"] = wim_type + if description: + wim["description"] = description + if config: + wim["config"] = config ctx.obj.wim.create(name, wim, wim_port_mapping, wait=wait) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='wim-update', short_help='updates a WIM account') -@click.argument('name') -@click.option('--newname', help='New name for the WIM account') -@click.option('--user', help='WIM username') -@click.option('--password', help='WIM password') -@click.option('--url', help='WIM url') -@click.option('--config', help='WIM specific config parameters') -@click.option('--wim_type', help='WIM type') -@click.option('--description', help='human readable description') -@click.option('--wim_port_mapping', default=None, - help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge " - "(WAN service endpoint id and info)") -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it until the operation is completed, or timeout') +@cli_osm.command(name="wim-update", short_help="updates a WIM account") +@click.argument("name") +@click.option("--newname", help="New name for the WIM account") +@click.option("--user", help="WIM username") +@click.option("--password", help="WIM password") +@click.option("--url", help="WIM url") +@click.option("--config", help="WIM specific config parameters") +@click.option("--wim_type", help="WIM type") +@click.option("--description", help="human readable description") +@click.option( + "--wim_port_mapping", + default=None, + help="File describing the port mapping between DC edge (datacenters, switches, ports) and WAN edge " + "(WAN service endpoint id and info)", +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context -def wim_update(ctx, - name, - newname, - user, - password, - url, - config, - wim_type, - description, - wim_port_mapping, - wait): +def wim_update( + ctx, + name, + newname, + user, + password, + url, + config, + wim_type, + description, + wim_port_mapping, + wait, +): """updates a WIM account NAME: name or ID of the WIM account @@ -2734,28 +3424,39 @@ def wim_update(ctx, # try: check_client_version(ctx.obj, ctx.command.name) wim = {} - if newname: wim['name'] = newname - if user: wim['user'] = user - if password: wim['password'] = password - if url: wim['url'] = url + if newname: + wim["name"] = newname + if user: + wim["user"] = user + if password: + wim["password"] = password + if url: + wim["url"] = url # if tenant: wim['tenant'] = tenant - if wim_type: wim['wim_type'] = wim_type - if description: wim['description'] = description - if config: wim['config'] = config + if wim_type: + wim["wim_type"] = wim_type + if description: + wim["description"] = description + if config: + wim["config"] = config ctx.obj.wim.update(name, wim, wim_port_mapping, wait=wait) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='wim-delete', short_help='deletes a WIM account') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it until the operation is completed, or timeout') +@cli_osm.command(name="wim-delete", short_help="deletes a WIM account") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context def wim_delete(ctx, name, force, wait): """deletes a WIM account @@ -2771,9 +3472,13 @@ def wim_delete(ctx, name, force, wait): # exit(1) -@cli_osm.command(name='wim-list', short_help='list all WIM accounts') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the WIM accounts matching the filter') +@cli_osm.command(name="wim-list", short_help="list all WIM accounts") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the WIM accounts matching the filter", +) @click.pass_context def wim_list(ctx, filter): """list all WIM accounts""" @@ -2781,20 +3486,20 @@ def wim_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.wim.list(filter) - table = PrettyTable(['wim name', 'uuid']) + table = PrettyTable(["wim name", "uuid"]) for wim in resp: - table.add_row([wim['name'], wim['uuid']]) - table.align = 'l' + table.add_row([wim["name"], wim["uuid"]]) + table.align = "l" print(table) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='wim-show', short_help='shows the details of a WIM account') -@click.argument('name') +@cli_osm.command(name="wim-show", short_help="shows the details of a WIM account") +@click.argument("name") @click.pass_context def wim_show(ctx, name): """shows the details of a WIM account @@ -2805,16 +3510,16 @@ def wim_show(ctx, name): # try: check_client_version(ctx.obj, ctx.command.name) resp = ctx.obj.wim.get(name) - if 'password' in resp: - resp['wim_password']='********' + if "password" in resp: + resp["wim_password"] = "********" # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in list(resp.items()): table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) @@ -2822,44 +3527,49 @@ def wim_show(ctx, name): # SDN controller operations #################### -@cli_osm.command(name='sdnc-create', short_help='creates a new SDN controller') -@click.option('--name', - prompt=True, - help='Name to create sdn controller') -@click.option('--type', - prompt=True, - help='SDN controller type') -@click.option('--sdn_controller_version', # hidden=True, - help='Deprecated. Use --config {version: sdn_controller_version}') -@click.option('--url', - help='URL in format http[s]://HOST:IP/') -@click.option('--ip_address', # hidden=True, - help='Deprecated. Use --url') -@click.option('--port', # hidden=True, - help='Deprecated. Use --url') -@click.option('--switch_dpid', # hidden=True, - help='Deprecated. Use --config {switch_id: DPID}') -@click.option('--config', - help='Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: ' - 'Openflow Datapath ID), version: version}') -@click.option('--user', - help='SDN controller username') -@click.option('--password', - hide_input=True, - confirmation_prompt=True, - help='SDN controller password') -@click.option('--description', default=None, help='human readable description') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help="do not return the control immediately, but keep it until the operation is completed, or timeout") + +@cli_osm.command(name="sdnc-create", short_help="creates a new SDN controller") +@click.option("--name", prompt=True, help="Name to create sdn controller") +@click.option("--type", prompt=True, help="SDN controller type") +@click.option( + "--sdn_controller_version", # hidden=True, + help="Deprecated. Use --config {version: sdn_controller_version}", +) +@click.option("--url", help="URL in format http[s]://HOST:IP/") +@click.option("--ip_address", help="Deprecated. Use --url") # hidden=True, +@click.option("--port", help="Deprecated. Use --url") # hidden=True, +@click.option( + "--switch_dpid", help="Deprecated. Use --config {switch_id: DPID}" # hidden=True, +) +@click.option( + "--config", + help="Extra information for SDN in yaml format, as {switch_id: identity used for the plugin (e.g. DPID: " + "Openflow Datapath ID), version: version}", +) +@click.option("--user", help="SDN controller username") +@click.option( + "--password", + hide_input=True, + confirmation_prompt=True, + help="SDN controller password", +) +@click.option("--description", default=None, help="human readable description") +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context def sdnc_create(ctx, **kwargs): """creates a new SDN controller""" logger.debug("") - sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and - x not in ("wait", "ip_address", "port", "switch_dpid")} + sdncontroller = { + x: kwargs[x] + for x in kwargs + if kwargs[x] and x not in ("wait", "ip_address", "port", "switch_dpid") + } if kwargs.get("port"): print("option '--port' is deprecated, use '--url' instead") sdncontroller["port"] = int(kwargs["port"]) @@ -2867,11 +3577,15 @@ def sdnc_create(ctx, **kwargs): print("option '--ip_address' is deprecated, use '--url' instead") sdncontroller["ip"] = kwargs["ip_address"] if kwargs.get("switch_dpid"): - print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead") + print( + "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead" + ) sdncontroller["dpid"] = kwargs["switch_dpid"] if kwargs.get("sdn_controller_version"): - print("option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'" - " instead") + print( + "option '--sdn_controller_version' is deprecated, use '--config={version: SDN_CONTROLLER_VERSION}'" + " instead" + ) # try: check_client_version(ctx.obj, ctx.command.name) ctx.obj.sdnc.create(kwargs["name"], sdncontroller, wait=kwargs["wait"]) @@ -2879,23 +3593,36 @@ def sdnc_create(ctx, **kwargs): # print(str(e)) # exit(1) -@cli_osm.command(name='sdnc-update', short_help='updates an SDN controller') -@click.argument('name') -@click.option('--newname', help='New name for the SDN controller') -@click.option('--description', default=None, help='human readable description') -@click.option('--type', help='SDN controller type') -@click.option('--url', help='URL in format http[s]://HOST:IP/') -@click.option('--config', help='Extra information for SDN in yaml format, as ' - '{switch_id: identity used for the plugin (e.g. DPID: ' - 'Openflow Datapath ID), version: version}') -@click.option('--user', help='SDN controller username') -@click.option('--password', help='SDN controller password') -@click.option('--ip_address', help='Deprecated. Use --url') # hidden=True -@click.option('--port', help='Deprecated. Use --url') # hidden=True -@click.option('--switch_dpid', help='Deprecated. Use --config {switch_dpid: DPID}') # hidden=True -@click.option('--sdn_controller_version', help='Deprecated. Use --config {version: VERSION}') # hidden=True -@click.option('--wait', required=False, default=False, is_flag=True, - help='do not return the control immediately, but keep it until the operation is completed, or timeout') + +@cli_osm.command(name="sdnc-update", short_help="updates an SDN controller") +@click.argument("name") +@click.option("--newname", help="New name for the SDN controller") +@click.option("--description", default=None, help="human readable description") +@click.option("--type", help="SDN controller type") +@click.option("--url", help="URL in format http[s]://HOST:IP/") +@click.option( + "--config", + help="Extra information for SDN in yaml format, as " + "{switch_id: identity used for the plugin (e.g. DPID: " + "Openflow Datapath ID), version: version}", +) +@click.option("--user", help="SDN controller username") +@click.option("--password", help="SDN controller password") +@click.option("--ip_address", help="Deprecated. Use --url") # hidden=True +@click.option("--port", help="Deprecated. Use --url") # hidden=True +@click.option( + "--switch_dpid", help="Deprecated. Use --config {switch_dpid: DPID}" +) # hidden=True +@click.option( + "--sdn_controller_version", help="Deprecated. Use --config {version: VERSION}" +) # hidden=True +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context def sdnc_update(ctx, **kwargs): """updates an SDN controller @@ -2903,8 +3630,12 @@ def sdnc_update(ctx, **kwargs): NAME: name or ID of the SDN controller """ logger.debug("") - sdncontroller = {x: kwargs[x] for x in kwargs if kwargs[x] and - x not in ("wait", "ip_address", "port", "switch_dpid", "new_name")} + sdncontroller = { + x: kwargs[x] + for x in kwargs + if kwargs[x] + and x not in ("wait", "ip_address", "port", "switch_dpid", "new_name") + } if kwargs.get("newname"): sdncontroller["name"] = kwargs["newname"] if kwargs.get("port"): @@ -2914,11 +3645,15 @@ def sdnc_update(ctx, **kwargs): print("option '--ip_address' is deprecated, use '--url' instead") sdncontroller["ip"] = kwargs["ip_address"] if kwargs.get("switch_dpid"): - print("option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead") + print( + "option '--switch_dpid' is deprecated, use '--config={switch_id: id|DPID}' instead" + ) sdncontroller["dpid"] = kwargs["switch_dpid"] if kwargs.get("sdn_controller_version"): - print("option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'" - " instead") + print( + "option '--sdn_controller_version' is deprecated, use '---config={version: SDN_CONTROLLER_VERSION}'" + " instead" + ) # try: check_client_version(ctx.obj, ctx.command.name) @@ -2928,11 +3663,18 @@ def sdnc_update(ctx, **kwargs): # exit(1) -@cli_osm.command(name='sdnc-delete', short_help='deletes an SDN controller') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') -@click.option('--wait', required=False, default=False, is_flag=True, - help='do not return the control immediately, but keep it until the operation is completed, or timeout') +@cli_osm.command(name="sdnc-delete", short_help="deletes an SDN controller") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion bypassing pre-conditions" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context def sdnc_delete(ctx, name, force, wait): """deletes an SDN controller @@ -2948,9 +3690,13 @@ def sdnc_delete(ctx, name, force, wait): # exit(1) -@cli_osm.command(name='sdnc-list', short_help='list all SDN controllers') -@click.option('--filter', default=None, multiple=True, - help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'") +@cli_osm.command(name="sdnc-list", short_help="list all SDN controllers") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the SDN controllers matching the filter with format: 'k[.k..]=v[&k[.k]=v2]'", +) @click.pass_context def sdnc_list(ctx, filter): """list all SDN controllers""" @@ -2958,20 +3704,20 @@ def sdnc_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.sdnc.list(filter) # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['sdnc name', 'id']) + table = PrettyTable(["sdnc name", "id"]) for sdnc in resp: - table.add_row([sdnc['name'], sdnc['_id']]) - table.align = 'l' + table.add_row([sdnc["name"], sdnc["_id"]]) + table.align = "l" print(table) -@cli_osm.command(name='sdnc-show', short_help='shows the details of an SDN controller') -@click.argument('name') +@cli_osm.command(name="sdnc-show", short_help="shows the details of an SDN controller") +@click.argument("name") @click.pass_context def sdnc_show(ctx, name): """shows the details of an SDN controller @@ -2986,10 +3732,10 @@ def sdnc_show(ctx, name): # print(str(e)) # exit(1) - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in list(resp.items()): table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) @@ -2997,45 +3743,42 @@ def sdnc_show(ctx, name): # K8s cluster operations ########################### -@cli_osm.command(name='k8scluster-add', short_help='adds a K8s cluster to OSM') -@click.argument('name') -@click.option('--creds', - prompt=True, - help='credentials file, i.e. a valid `.kube/config` file') -@click.option('--version', - prompt=True, - help='Kubernetes version') -@click.option('--vim', - prompt=True, - help='VIM target, the VIM where the cluster resides') -@click.option('--k8s-nets', - prompt=True, - help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"') -@click.option('--description', - default=None, - help='human readable description') -@click.option('--namespace', - default='kube-system', - help='namespace to be used for its operation, defaults to `kube-system`') -@click.option('--cni', - default=None, - help='list of CNI plugins, in JSON inline format, used in the cluster') -#@click.option('--skip-init', + +@cli_osm.command(name="k8scluster-add", short_help="adds a K8s cluster to OSM") +@click.argument("name") +@click.option( + "--creds", prompt=True, help="credentials file, i.e. a valid `.kube/config` file" +) +@click.option("--version", prompt=True, help="Kubernetes version") +@click.option( + "--vim", prompt=True, help="VIM target, the VIM where the cluster resides" +) +@click.option( + "--k8s-nets", + prompt=True, + help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"', +) +@click.option("--description", default=None, help="human readable description") +@click.option( + "--namespace", + default="kube-system", + help="namespace to be used for its operation, defaults to `kube-system`", +) +@click.option( + "--cni", + default=None, + help="list of CNI plugins, in JSON inline format, used in the cluster", +) +# @click.option('--skip-init', # is_flag=True, # help='If set, K8s cluster is assumed to be ready for its use with OSM') -#@click.option('--wait', +# @click.option('--wait', # is_flag=True, # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context -def k8scluster_add(ctx, - name, - creds, - version, - vim, - k8s_nets, - description, - namespace, - cni): +def k8scluster_add( + ctx, name, creds, version, vim, k8s_nets, description, namespace, cni +): """adds a K8s cluster to OSM NAME: name of the K8s cluster @@ -3043,43 +3786,46 @@ def k8scluster_add(ctx, # try: check_client_version(ctx.obj, ctx.command.name) cluster = {} - cluster['name'] = name - with open(creds, 'r') as cf: - cluster['credentials'] = yaml.safe_load(cf.read()) - cluster['k8s_version'] = version - cluster['vim_account'] = vim - cluster['nets'] = yaml.safe_load(k8s_nets) + cluster["name"] = name + with open(creds, "r") as cf: + cluster["credentials"] = yaml.safe_load(cf.read()) + cluster["k8s_version"] = version + cluster["vim_account"] = vim + cluster["nets"] = yaml.safe_load(k8s_nets) if description: - cluster['description'] = description - if namespace: cluster['namespace'] = namespace - if cni: cluster['cni'] = yaml.safe_load(cni) + cluster["description"] = description + if namespace: + cluster["namespace"] = namespace + if cni: + cluster["cni"] = yaml.safe_load(cni) ctx.obj.k8scluster.create(name, cluster) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='k8scluster-update', short_help='updates a K8s cluster') -@click.argument('name') -@click.option('--newname', help='New name for the K8s cluster') -@click.option('--creds', help='credentials file, i.e. a valid `.kube/config` file') -@click.option('--version', help='Kubernetes version') -@click.option('--vim', help='VIM target, the VIM where the cluster resides') -@click.option('--k8s-nets', help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"') -@click.option('--description', help='human readable description') -@click.option('--namespace', help='namespace to be used for its operation, defaults to `kube-system`') -@click.option('--cni', help='list of CNI plugins, in JSON inline format, used in the cluster') +@cli_osm.command(name="k8scluster-update", short_help="updates a K8s cluster") +@click.argument("name") +@click.option("--newname", help="New name for the K8s cluster") +@click.option("--creds", help="credentials file, i.e. a valid `.kube/config` file") +@click.option("--version", help="Kubernetes version") +@click.option("--vim", help="VIM target, the VIM where the cluster resides") +@click.option( + "--k8s-nets", + help='list of VIM networks, in JSON inline format, where the cluster is accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"', +) +@click.option("--description", help="human readable description") +@click.option( + "--namespace", + help="namespace to be used for its operation, defaults to `kube-system`", +) +@click.option( + "--cni", help="list of CNI plugins, in JSON inline format, used in the cluster" +) @click.pass_context -def k8scluster_update(ctx, - name, - newname, - creds, - version, - vim, - k8s_nets, - description, - namespace, - cni): +def k8scluster_update( + ctx, name, newname, creds, version, vim, k8s_nets, description, namespace, cni +): """updates a K8s cluster NAME: name or ID of the K8s cluster @@ -3087,26 +3833,35 @@ def k8scluster_update(ctx, # try: check_client_version(ctx.obj, ctx.command.name) cluster = {} - if newname: cluster['name'] = newname + if newname: + cluster["name"] = newname if creds: - with open(creds, 'r') as cf: - cluster['credentials'] = yaml.safe_load(cf.read()) - if version: cluster['k8s_version'] = version - if vim: cluster['vim_account'] = vim - if k8s_nets: cluster['nets'] = yaml.safe_load(k8s_nets) - if description: cluster['description'] = description - if namespace: cluster['namespace'] = namespace - if cni: cluster['cni'] = yaml.safe_load(cni) + with open(creds, "r") as cf: + cluster["credentials"] = yaml.safe_load(cf.read()) + if version: + cluster["k8s_version"] = version + if vim: + cluster["vim_account"] = vim + if k8s_nets: + cluster["nets"] = yaml.safe_load(k8s_nets) + if description: + cluster["description"] = description + if namespace: + cluster["namespace"] = namespace + if cni: + cluster["cni"] = yaml.safe_load(cni) ctx.obj.k8scluster.update(name, cluster) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='k8scluster-delete', short_help='deletes a K8s cluster') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)') -#@click.option('--wait', +@cli_osm.command(name="k8scluster-delete", short_help="deletes a K8s cluster") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion from the DB (not recommended)" +) +# @click.option('--wait', # is_flag=True, # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context @@ -3123,65 +3878,100 @@ def k8scluster_delete(ctx, name, force): # exit(1) -@cli_osm.command(name='k8scluster-list') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the K8s clusters matching the filter') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') -@click.option('--long', is_flag=True, help='get more details') +@cli_osm.command(name="k8scluster-list") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the K8s clusters matching the filter", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") +@click.option("--long", is_flag=True, help="get more details") @click.pass_context def k8scluster_list(ctx, filter, literal, long): """list all K8s clusters""" # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.k8scluster.list(filter) if literal: print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return if long: - table = PrettyTable(['Name', 'Id', 'Project', 'Version', 'VIM', 'K8s-nets', - 'Operational State', 'Op. state (details)', 'Description', 'Detailed status']) + table = PrettyTable( + [ + "Name", + "Id", + "Project", + "Version", + "VIM", + "K8s-nets", + "Operational State", + "Op. state (details)", + "Description", + "Detailed status", + ] + ) project_list = ctx.obj.project.list() else: - table = PrettyTable(['Name', 'Id', 'VIM', 'Operational State', 'Op. state details']) + table = PrettyTable( + ["Name", "Id", "VIM", "Operational State", "Op. state details"] + ) try: vim_list = ctx.obj.vim.list() except: vim_list = [] for cluster in resp: - logger.debug('Cluster details: {}'.format(yaml.safe_dump(cluster))) - vim_name = get_vim_name(vim_list, cluster['vim_account']) - #vim_info = '{} ({})'.format(vim_name,cluster['vim_account']) + logger.debug("Cluster details: {}".format(yaml.safe_dump(cluster))) + vim_name = get_vim_name(vim_list, cluster["vim_account"]) + # vim_info = '{} ({})'.format(vim_name,cluster['vim_account']) vim_info = vim_name op_state_details = "Helm: {}\nJuju: {}".format( - cluster["_admin"].get("helm-chart", {}).get("operationalState", "-"), - cluster["_admin"].get("juju-bundle", {}).get("operationalState", "-")) + cluster["_admin"].get("helm-chart", {}).get("operationalState", "-"), + cluster["_admin"].get("juju-bundle", {}).get("operationalState", "-"), + ) if long: project_id, project_name = get_project(project_list, cluster) - #project_info = '{} ({})'.format(project_name, project_id) + # project_info = '{} ({})'.format(project_name, project_id) project_info = project_name - detailed_status = cluster["_admin"].get("detailed-status","-") - table.add_row([cluster['name'], cluster['_id'], project_info, - cluster['k8s_version'], vim_info, - json.dumps(cluster['nets']), cluster["_admin"]["operationalState"], - op_state_details, trunc_text(cluster.get('description') or '', 40), - wrap_text(text=detailed_status, width=40)]) + detailed_status = cluster["_admin"].get("detailed-status", "-") + table.add_row( + [ + cluster["name"], + cluster["_id"], + project_info, + cluster["k8s_version"], + vim_info, + json.dumps(cluster["nets"]), + cluster["_admin"]["operationalState"], + op_state_details, + trunc_text(cluster.get("description") or "", 40), + wrap_text(text=detailed_status, width=40), + ] + ) else: - table.add_row([cluster['name'], cluster['_id'], vim_info, - cluster["_admin"]["operationalState"], op_state_details]) - table.align = 'l' + table.add_row( + [ + cluster["name"], + cluster["_id"], + vim_info, + cluster["_admin"]["operationalState"], + op_state_details, + ] + ) + table.align = "l" print(table) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='k8scluster-show', short_help='shows the details of a K8s cluster') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') +@cli_osm.command( + name="k8scluster-show", short_help="shows the details of a K8s cluster" +) +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") @click.pass_context def k8scluster_show(ctx, name, literal): """shows the details of a K8s cluster @@ -3193,38 +3983,40 @@ def k8scluster_show(ctx, name, literal): if literal: print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in list(resp.items()): - table.add_row([k, wrap_text(text=json.dumps(v, indent=2),width=100)]) - table.align = 'l' + table.add_row([k, wrap_text(text=json.dumps(v, indent=2), width=100)]) + table.align = "l" print(table) # except ClientException as e: # print(str(e)) # exit(1) - ########################### # Repo operations ########################### -@cli_osm.command(name='repo-add', short_help='adds a repo to OSM') -@click.argument('name') -@click.argument('uri') -@click.option('--type', - type=click.Choice(['helm-chart', 'juju-bundle', 'osm']), - default='osm', - help='type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)') -@click.option('--description', - default=None, - help='human readable description') -@click.option('--user', - default=None, - help='OSM repository: The username of the OSM repository') -@click.option('--password', - default=None, - help='OSM repository: The password of the OSM repository') -#@click.option('--wait', + +@cli_osm.command(name="repo-add", short_help="adds a repo to OSM") +@click.argument("name") +@click.argument("uri") +@click.option( + "--type", + type=click.Choice(["helm-chart", "juju-bundle", "osm"]), + default="osm", + help="type of repo (helm-chart for Helm Charts, juju-bundle for Juju Bundles, osm for OSM Repositories)", +) +@click.option("--description", default=None, help="human readable description") +@click.option( + "--user", default=None, help="OSM repository: The username of the OSM repository" +) +@click.option( + "--password", + default=None, + help="OSM repository: The password of the OSM repository", +) +# @click.option('--wait', # is_flag=True, # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context @@ -3238,29 +4030,25 @@ def repo_add(ctx, **kwargs): kwargs = {k: v for k, v in kwargs.items() if v is not None} repo = kwargs repo["url"] = repo.pop("uri") - if repo["type"] in ['helm-chart', 'juju-bundle']: - ctx.obj.repo.create(repo['name'], repo) + if repo["type"] in ["helm-chart", "juju-bundle"]: + ctx.obj.repo.create(repo["name"], repo) else: - ctx.obj.osmrepo.create(repo['name'], repo) + ctx.obj.osmrepo.create(repo["name"], repo) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='repo-update', short_help='updates a repo in OSM') -@click.argument('name') -@click.option('--newname', help='New name for the repo') -@click.option('--uri', help='URI of the repo') -@click.option('--description', help='human readable description') -#@click.option('--wait', +@cli_osm.command(name="repo-update", short_help="updates a repo in OSM") +@click.argument("name") +@click.option("--newname", help="New name for the repo") +@click.option("--uri", help="URI of the repo") +@click.option("--description", help="human readable description") +# @click.option('--wait', # is_flag=True, # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context -def repo_update(ctx, - name, - newname, - uri, - description): +def repo_update(ctx, name, newname, uri, description): """updates a repo in OSM NAME: name of the repo @@ -3269,10 +4057,11 @@ def repo_update(ctx, check_client_version(ctx.obj, ctx.command.name) repo = {} if newname: - repo['name'] = newname + repo["name"] = newname if uri: - repo['uri'] = uri - if description: repo['description'] = description + repo["uri"] = uri + if description: + repo["description"] = description try: ctx.obj.repo.update(name, repo) except NotFound: @@ -3283,9 +4072,15 @@ def repo_update(ctx, # exit(1) -@cli_osm.command(name='repo-index', short_help='Index a repository from a folder with artifacts') -@click.option('--origin', default='.', help='origin path where the artifacts are located') -@click.option('--destination', default='.', help='destination path where the index is deployed') +@cli_osm.command( + name="repo-index", short_help="Index a repository from a folder with artifacts" +) +@click.option( + "--origin", default=".", help="origin path where the artifacts are located" +) +@click.option( + "--destination", default=".", help="destination path where the index is deployed" +) @click.pass_context def repo_index(ctx, origin, destination): """Index a repository @@ -3296,10 +4091,12 @@ def repo_index(ctx, origin, destination): ctx.obj.osmrepo.repo_index(origin, destination) -@cli_osm.command(name='repo-delete', short_help='deletes a repo') -@click.argument('name') -@click.option('--force', is_flag=True, help='forces the deletion from the DB (not recommended)') -#@click.option('--wait', +@cli_osm.command(name="repo-delete", short_help="deletes a repo") +@click.argument("name") +@click.option( + "--force", is_flag=True, help="forces the deletion from the DB (not recommended)" +) +# @click.option('--wait', # is_flag=True, # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context @@ -3318,11 +4115,14 @@ def repo_delete(ctx, name, force): # exit(1) -@cli_osm.command(name='repo-list') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the repos matching the filter') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') +@cli_osm.command(name="repo-list") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the repos matching the filter", +) +@click.option("--literal", is_flag=True, help="print literally, no pretty table") @click.pass_context def repo_list(ctx, filter, literal): """list all repos""" @@ -3330,17 +4130,25 @@ def repo_list(ctx, filter, literal): # K8s Repositories check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.repo.list(filter) resp += ctx.obj.osmrepo.list(filter) if literal: print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['Name', 'Id', 'Type', 'URI', 'Description']) + table = PrettyTable(["Name", "Id", "Type", "URI", "Description"]) for repo in resp: - #cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets'])) - table.add_row([repo['name'], repo['_id'], repo['type'], repo['url'], trunc_text(repo.get('description') or '',40)]) - table.align = 'l' + # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets'])) + table.add_row( + [ + repo["name"], + repo["_id"], + repo["type"], + repo["url"], + trunc_text(repo.get("description") or "", 40), + ] + ) + table.align = "l" print(table) # except ClientException as e: @@ -3348,10 +4156,9 @@ def repo_list(ctx, filter, literal): # exit(1) -@cli_osm.command(name='repo-show', short_help='shows the details of a repo') -@click.argument('name') -@click.option('--literal', is_flag=True, - help='print literally, no pretty table') +@cli_osm.command(name="repo-show", short_help="shows the details of a repo") +@click.argument("name") +@click.option("--literal", is_flag=True, help="print literally, no pretty table") @click.pass_context def repo_show(ctx, name, literal): """shows the details of a repo @@ -3367,34 +4174,37 @@ def repo_show(ctx, name, literal): if resp: print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) return - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) if resp: for k, v in list(resp.items()): table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) # except ClientException as e: # print(str(e)) # exit(1) - #################### # Project mgmt operations #################### -@cli_osm.command(name='project-create', short_help='creates a new project') -@click.argument('name') -#@click.option('--description', + +@cli_osm.command(name="project-create", short_help="creates a new project") +@click.argument("name") +# @click.option('--description', # default='no description', # help='human readable description') -@click.option('--domain-name', 'domain_name', - default=None, - help='assign to a domain') -@click.option('--quotas', 'quotas', multiple=True, default=None, - help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one " - "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos") +@click.option("--domain-name", "domain_name", default=None, help="assign to a domain") +@click.option( + "--quotas", + "quotas", + multiple=True, + default=None, + help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one " + "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos", +) @click.pass_context def project_create(ctx, name, domain_name, quotas): """Creates a new project @@ -3404,12 +4214,12 @@ def project_create(ctx, name, domain_name, quotas): QUOTAS: set quotas for the project """ logger.debug("") - project = {'name': name} + project = {"name": name} if domain_name: - project['domain_name'] = domain_name + project["domain_name"] = domain_name quotas_dict = _process_project_quotas(quotas) if quotas_dict: - project['quotas'] = quotas_dict + project["quotas"] = quotas_dict # try: check_client_version(ctx.obj, ctx.command.name) @@ -3427,15 +4237,17 @@ def _process_project_quotas(quota_list): for quota in quota_list: for single_quota in quota.split(","): k, v = single_quota.split("=") - quotas_dict[k] = None if v in ('None', 'null', '') else int(v) + quotas_dict[k] = None if v in ("None", "null", "") else int(v) except (ValueError, TypeError): - raise ClientException("invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null") + raise ClientException( + "invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null" + ) return quotas_dict -@cli_osm.command(name='project-delete', short_help='deletes a project') -@click.argument('name') -#@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="project-delete", short_help="deletes a project") +@click.argument("name") +# @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') @click.pass_context def project_delete(ctx, name): """deletes a project @@ -3451,9 +4263,13 @@ def project_delete(ctx, name): # exit(1) -@cli_osm.command(name='project-list', short_help='list all projects') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the projects matching the filter') +@cli_osm.command(name="project-list", short_help="list all projects") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the projects matching the filter", +) @click.pass_context def project_list(ctx, filter): """list all projects""" @@ -3461,20 +4277,20 @@ def project_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.project.list(filter) # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['name', 'id']) + table = PrettyTable(["name", "id"]) for proj in resp: - table.add_row([proj['name'], proj['_id']]) - table.align = 'l' + table.add_row([proj["name"], proj["_id"]]) + table.align = "l" print(table) -@cli_osm.command(name='project-show', short_help='shows the details of a project') -@click.argument('name') +@cli_osm.command(name="project-show", short_help="shows the details of a project") +@click.argument("name") @click.pass_context def project_show(ctx, name): """shows the details of a project @@ -3489,20 +4305,26 @@ def project_show(ctx, name): # print(str(e)) # exit(1) - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in resp.items(): table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) -@cli_osm.command(name='project-update', short_help='updates a project (only the name can be updated)') -@click.argument('project') -@click.option('--name', default=None, - help='new name for the project') -@click.option('--quotas', 'quotas', multiple=True, default=None, - help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' " - "(use empty to reset quota to default") +@cli_osm.command( + name="project-update", short_help="updates a project (only the name can be updated)" +) +@click.argument("project") +@click.option("--name", default=None, help="new name for the project") +@click.option( + "--quotas", + "quotas", + multiple=True, + default=None, + help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' " + "(use empty to reset quota to default", +) @click.pass_context def project_update(ctx, project, name, quotas): """ @@ -3517,10 +4339,10 @@ def project_update(ctx, project, name, quotas): logger.debug("") project_changes = {} if name: - project_changes['name'] = name + project_changes["name"] = name quotas_dict = _process_project_quotas(quotas) if quotas_dict: - project_changes['quotas'] = quotas_dict + project_changes["quotas"] = quotas_dict # try: check_client_version(ctx.obj, ctx.command.name) @@ -3533,24 +4355,33 @@ def project_update(ctx, project, name, quotas): # User mgmt operations #################### -@cli_osm.command(name='user-create', short_help='creates a new user') -@click.argument('username') -@click.option('--password', - prompt=True, - hide_input=True, - confirmation_prompt=True, - help='user password') -@click.option('--projects', - # prompt="Comma separate list of projects", - multiple=True, - callback=lambda ctx, param, value: ''.join(value).split(',') if all(len(x)==1 for x in value) else value, - help='list of project ids that the user belongs to') -@click.option('--project-role-mappings', 'project_role_mappings', - default=None, multiple=True, - help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'") -@click.option('--domain-name', 'domain_name', - default=None, - help='assign to a domain') + +@cli_osm.command(name="user-create", short_help="creates a new user") +@click.argument("username") +@click.option( + "--password", + prompt=True, + hide_input=True, + confirmation_prompt=True, + help="user password", +) +@click.option( + "--projects", + # prompt="Comma separate list of projects", + multiple=True, + callback=lambda ctx, param, value: "".join(value).split(",") + if all(len(x) == 1 for x in value) + else value, + help="list of project ids that the user belongs to", +) +@click.option( + "--project-role-mappings", + "project_role_mappings", + default=None, + multiple=True, + help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'", +) +@click.option("--domain-name", "domain_name", default=None, help="assign to a domain") @click.pass_context def user_create(ctx, username, password, projects, project_role_mappings, domain_name): """Creates a new user @@ -3564,12 +4395,12 @@ def user_create(ctx, username, password, projects, project_role_mappings, domain """ logger.debug("") user = {} - user['username'] = username - user['password'] = password - user['projects'] = projects - user['project_role_mappings'] = project_role_mappings + user["username"] = username + user["password"] = password + user["projects"] = projects + user["project_role_mappings"] = project_role_mappings if domain_name: - user['domain_name'] = domain_name + user["domain_name"] = domain_name # try: check_client_version(ctx.obj, ctx.command.name) @@ -3579,31 +4410,55 @@ def user_create(ctx, username, password, projects, project_role_mappings, domain # exit(1) -@cli_osm.command(name='user-update', short_help='updates user information') -@click.argument('username') -@click.option('--password', - # prompt=True, - # hide_input=True, - # confirmation_prompt=True, - help='user password') -@click.option('--set-username', 'set_username', - default=None, - help='change username') -@click.option('--set-project', 'set_project', - default=None, multiple=True, - help="create/replace the roles for this project: 'project,role1[,role2,...]'") -@click.option('--remove-project', 'remove_project', - default=None, multiple=True, - help="removes project from user: 'project'") -@click.option('--add-project-role', 'add_project_role', - default=None, multiple=True, - help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'") -@click.option('--remove-project-role', 'remove_project_role', - default=None, multiple=True, - help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'") +@cli_osm.command(name="user-update", short_help="updates user information") +@click.argument("username") +@click.option( + "--password", + # prompt=True, + # hide_input=True, + # confirmation_prompt=True, + help="user password", +) +@click.option("--set-username", "set_username", default=None, help="change username") +@click.option( + "--set-project", + "set_project", + default=None, + multiple=True, + help="create/replace the roles for this project: 'project,role1[,role2,...]'", +) +@click.option( + "--remove-project", + "remove_project", + default=None, + multiple=True, + help="removes project from user: 'project'", +) +@click.option( + "--add-project-role", + "add_project_role", + default=None, + multiple=True, + help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'", +) +@click.option( + "--remove-project-role", + "remove_project_role", + default=None, + multiple=True, + help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'", +) @click.pass_context -def user_update(ctx, username, password, set_username, set_project, remove_project, - add_project_role, remove_project_role): +def user_update( + ctx, + username, + password, + set_username, + set_project, + remove_project, + add_project_role, + remove_project_role, +): """Update a user information \b @@ -3617,13 +4472,13 @@ def user_update(ctx, username, password, set_username, set_project, remove_proje """ logger.debug("") user = {} - user['password'] = password - user['username'] = set_username - user['set-project'] = set_project - user['remove-project'] = remove_project - user['add-project-role'] = add_project_role - user['remove-project-role'] = remove_project_role - + user["password"] = password + user["username"] = set_username + user["set-project"] = set_project + user["remove-project"] = remove_project + user["add-project-role"] = add_project_role + user["remove-project-role"] = remove_project_role + # try: check_client_version(ctx.obj, ctx.command.name) ctx.obj.user.update(username, user) @@ -3632,9 +4487,9 @@ def user_update(ctx, username, password, set_username, set_project, remove_proje # exit(1) -@cli_osm.command(name='user-delete', short_help='deletes a user') -@click.argument('name') -#@click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') +@cli_osm.command(name="user-delete", short_help="deletes a user") +@click.argument("name") +# @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') @click.pass_context def user_delete(ctx, name): """deletes a user @@ -3651,29 +4506,33 @@ def user_delete(ctx, name): # exit(1) -@cli_osm.command(name='user-list', short_help='list all users') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the users matching the filter') +@cli_osm.command(name="user-list", short_help="list all users") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the users matching the filter", +) @click.pass_context def user_list(ctx, filter): """list all users""" # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.user.list(filter) # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['name', 'id']) + table = PrettyTable(["name", "id"]) for user in resp: - table.add_row([user['username'], user['_id']]) - table.align = 'l' + table.add_row([user["username"], user["_id"]]) + table.align = "l" print(table) -@cli_osm.command(name='user-show', short_help='shows the details of a user') -@click.argument('name') +@cli_osm.command(name="user-show", short_help="shows the details of a user") +@click.argument("name") @click.pass_context def user_show(ctx, name): """shows the details of a user @@ -3684,16 +4543,16 @@ def user_show(ctx, name): # try: check_client_version(ctx.obj, ctx.command.name) resp = ctx.obj.user.get(name) - if 'password' in resp: - resp['password']='********' + if "password" in resp: + resp["password"] = "********" # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in resp.items(): table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) @@ -3701,26 +4560,48 @@ def user_show(ctx, name): # Fault Management operations #################### -@cli_osm.command(name='ns-alarm-create') -@click.argument('name') -@click.option('--ns', prompt=True, help='NS instance id or name') -@click.option('--vnf', prompt=True, - help='VNF name (VNF member index as declared in the NSD)') -@click.option('--vdu', prompt=True, - help='VDU name (VDU name as declared in the VNFD)') -@click.option('--metric', prompt=True, - help='Name of the metric (e.g. cpu_utilization)') -@click.option('--severity', default='WARNING', - help='severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)') -@click.option('--threshold_value', prompt=True, - help='threshold value that, when crossed, an alarm is triggered') -@click.option('--threshold_operator', prompt=True, - help='threshold operator describing the comparison (GE, LE, GT, LT, EQ)') -@click.option('--statistic', default='AVERAGE', - help='statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)') + +@cli_osm.command(name="ns-alarm-create") +@click.argument("name") +@click.option("--ns", prompt=True, help="NS instance id or name") +@click.option( + "--vnf", prompt=True, help="VNF name (VNF member index as declared in the NSD)" +) +@click.option("--vdu", prompt=True, help="VDU name (VDU name as declared in the VNFD)") +@click.option("--metric", prompt=True, help="Name of the metric (e.g. cpu_utilization)") +@click.option( + "--severity", + default="WARNING", + help="severity of the alarm (WARNING, MINOR, MAJOR, CRITICAL, INDETERMINATE)", +) +@click.option( + "--threshold_value", + prompt=True, + help="threshold value that, when crossed, an alarm is triggered", +) +@click.option( + "--threshold_operator", + prompt=True, + help="threshold operator describing the comparison (GE, LE, GT, LT, EQ)", +) +@click.option( + "--statistic", + default="AVERAGE", + help="statistic (AVERAGE, MINIMUM, MAXIMUM, COUNT, SUM)", +) @click.pass_context -def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity, - threshold_value, threshold_operator, statistic): +def ns_alarm_create( + ctx, + name, + ns, + vnf, + vdu, + metric, + severity, + threshold_value, + threshold_operator, + statistic, +): """creates a new alarm for a NS instance""" # TODO: Check how to validate threshold_value. # Should it be an integer (1-100), percentage, or decimal (0.01-1.00)? @@ -3728,16 +4609,16 @@ def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity, # try: ns_instance = ctx.obj.ns.get(ns) alarm = {} - alarm['alarm_name'] = name - alarm['ns_id'] = ns_instance['_id'] - alarm['correlation_id'] = ns_instance['_id'] - alarm['vnf_member_index'] = vnf - alarm['vdu_name'] = vdu - alarm['metric_name'] = metric - alarm['severity'] = severity - alarm['threshold_value'] = int(threshold_value) - alarm['operation'] = threshold_operator - alarm['statistic'] = statistic + alarm["alarm_name"] = name + alarm["ns_id"] = ns_instance["_id"] + alarm["correlation_id"] = ns_instance["_id"] + alarm["vnf_member_index"] = vnf + alarm["vdu_name"] = vdu + alarm["metric_name"] = metric + alarm["severity"] = severity + alarm["threshold_value"] = int(threshold_value) + alarm["operation"] = threshold_operator + alarm["statistic"] = statistic check_client_version(ctx.obj, ctx.command.name) ctx.obj.ns.create_alarm(alarm) # except ClientException as e: @@ -3745,10 +4626,10 @@ def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity, # exit(1) -#@cli_osm.command(name='ns-alarm-delete') -#@click.argument('name') -#@click.pass_context -#def ns_alarm_delete(ctx, name): +# @cli_osm.command(name='ns-alarm-delete') +# @click.argument('name') +# @click.pass_context +# def ns_alarm_delete(ctx, name): # """deletes an alarm # # NAME: name of the alarm to be deleted @@ -3765,17 +4646,22 @@ def ns_alarm_create(ctx, name, ns, vnf, vdu, metric, severity, # Performance Management operations #################### -@cli_osm.command(name='ns-metric-export', short_help='exports a metric to the internal OSM bus, which can be read by other apps') -@click.option('--ns', prompt=True, help='NS instance id or name') -@click.option('--vnf', prompt=True, - help='VNF name (VNF member index as declared in the NSD)') -@click.option('--vdu', prompt=True, - help='VDU name (VDU name as declared in the VNFD)') -@click.option('--metric', prompt=True, - help='name of the metric (e.g. cpu_utilization)') -#@click.option('--period', default='1w', + +@cli_osm.command( + name="ns-metric-export", + short_help="exports a metric to the internal OSM bus, which can be read by other apps", +) +@click.option("--ns", prompt=True, help="NS instance id or name") +@click.option( + "--vnf", prompt=True, help="VNF name (VNF member index as declared in the NSD)" +) +@click.option("--vdu", prompt=True, help="VDU name (VDU name as declared in the VNFD)") +@click.option("--metric", prompt=True, help="name of the metric (e.g. cpu_utilization)") +# @click.option('--period', default='1w', # help='metric collection period (e.g. 20s, 30m, 2h, 3d, 1w)') -@click.option('--interval', help='periodic interval (seconds) to export metrics continuously') +@click.option( + "--interval", help="periodic interval (seconds) to export metrics continuously" +) @click.pass_context def ns_metric_export(ctx, ns, vnf, vdu, metric, interval): """exports a metric to the internal OSM bus, which can be read by other apps""" @@ -3785,22 +4671,22 @@ def ns_metric_export(ctx, ns, vnf, vdu, metric, interval): # try: ns_instance = ctx.obj.ns.get(ns) metric_data = {} - metric_data['ns_id'] = ns_instance['_id'] - metric_data['correlation_id'] = ns_instance['_id'] - metric_data['vnf_member_index'] = vnf - metric_data['vdu_name'] = vdu - metric_data['metric_name'] = metric - metric_data['collection_unit'] = 'WEEK' - metric_data['collection_period'] = 1 + metric_data["ns_id"] = ns_instance["_id"] + metric_data["correlation_id"] = ns_instance["_id"] + metric_data["vnf_member_index"] = vnf + metric_data["vdu_name"] = vdu + metric_data["metric_name"] = metric + metric_data["collection_unit"] = "WEEK" + metric_data["collection_period"] = 1 check_client_version(ctx.obj, ctx.command.name) if not interval: - print('{}'.format(ctx.obj.ns.export_metric(metric_data))) + print("{}".format(ctx.obj.ns.export_metric(metric_data))) else: i = 1 while True: - print('{} {}'.format(ctx.obj.ns.export_metric(metric_data),i)) + print("{} {}".format(ctx.obj.ns.export_metric(metric_data), i)) time.sleep(int(interval)) - i+=1 + i += 1 # except ClientException as e: # print(str(e)) # exit(1) @@ -3810,22 +4696,32 @@ def ns_metric_export(ctx, ns, vnf, vdu, metric, interval): # Other operations #################### -@cli_osm.command(name='version', short_help='shows client and server versions') + +@cli_osm.command(name="version", short_help="shows client and server versions") @click.pass_context def get_version(ctx): """shows client and server versions""" # try: check_client_version(ctx.obj, "version") - print ("Server version: {}".format(ctx.obj.get_version())) - print ("Client version: {}".format(pkg_resources.get_distribution("osmclient").version)) + print("Server version: {}".format(ctx.obj.get_version())) + print( + "Client version: {}".format(pkg_resources.get_distribution("osmclient").version) + ) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='upload-package', short_help='uploads a VNF package or NS package') -@click.argument('filename') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='the charm will not be compiled, it is assumed to already exist') + +@cli_osm.command( + name="upload-package", short_help="uploads a VNF package or NS package" +) +@click.argument("filename") +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="the charm will not be compiled, it is assumed to already exist", +) @click.pass_context def upload_package(ctx, filename, skip_charm_build): """uploads a vnf package or ns package @@ -3836,17 +4732,17 @@ def upload_package(ctx, filename, skip_charm_build): # try: ctx.obj.package.upload(filename, skip_charm_build=skip_charm_build) fullclassname = ctx.obj.__module__ + "." + ctx.obj.__class__.__name__ - if fullclassname != 'osmclient.sol005.client.Client': + if fullclassname != "osmclient.sol005.client.Client": ctx.obj.package.wait_for_upload(filename) # except ClientException as e: # print(str(e)) # exit(1) -#@cli_osm.command(name='ns-scaling-show') -#@click.argument('ns_name') -#@click.pass_context -#def show_ns_scaling(ctx, ns_name): +# @cli_osm.command(name='ns-scaling-show') +# @click.argument('ns_name') +# @click.pass_context +# def show_ns_scaling(ctx, ns_name): # """shows the status of a NS scaling operation # # NS_NAME: name of the NS instance being scaled @@ -3885,18 +4781,18 @@ def upload_package(ctx, filename, skip_charm_build): # print(table) -#@cli_osm.command(name='ns-scale') -#@click.argument('ns_name') -#@click.option('--ns_scale_group', prompt=True) -#@click.option('--index', prompt=True) -#@click.option('--wait', +# @cli_osm.command(name='ns-scale') +# @click.argument('ns_name') +# @click.option('--ns_scale_group', prompt=True) +# @click.option('--index', prompt=True) +# @click.option('--wait', # required=False, # default=False, # is_flag=True, # help='do not return the control immediately, but keep it \ # until the operation is completed, or timeout') -#@click.pass_context -#def ns_scale(ctx, ns_name, ns_scale_group, index, wait): +# @click.pass_context +# def ns_scale(ctx, ns_name, ns_scale_group, index, wait): # """scales NS # # NS_NAME: name of the NS instance to be scaled @@ -3909,9 +4805,9 @@ def upload_package(ctx, filename, skip_charm_build): # exit(1) -#@cli_osm.command(name='config-agent-list') -#@click.pass_context -#def config_agent_list(ctx): +# @cli_osm.command(name='config-agent-list') +# @click.pass_context +# def config_agent_list(ctx): # """list config agents""" # try: # check_client_version(ctx.obj, ctx.command.name, 'v1') @@ -3928,10 +4824,10 @@ def upload_package(ctx, filename, skip_charm_build): # print(table) -#@cli_osm.command(name='config-agent-delete') -#@click.argument('name') -#@click.pass_context -#def config_agent_delete(ctx, name): +# @cli_osm.command(name='config-agent-delete') +# @click.argument('name') +# @click.pass_context +# def config_agent_delete(ctx, name): # """deletes a config agent # # NAME: name of the config agent to be deleted @@ -3944,21 +4840,21 @@ def upload_package(ctx, filename, skip_charm_build): # exit(1) -#@cli_osm.command(name='config-agent-add') -#@click.option('--name', +# @cli_osm.command(name='config-agent-add') +# @click.option('--name', # prompt=True) -#@click.option('--account_type', +# @click.option('--account_type', # prompt=True) -#@click.option('--server', +# @click.option('--server', # prompt=True) -#@click.option('--user', +# @click.option('--user', # prompt=True) -#@click.option('--secret', +# @click.option('--secret', # prompt=True, # hide_input=True, # confirmation_prompt=True) -#@click.pass_context -#def config_agent_add(ctx, name, account_type, server, user, secret): +# @click.pass_context +# def config_agent_add(ctx, name, account_type, server, user, secret): # """adds a config agent""" # try: # check_client_version(ctx.obj, ctx.command.name, 'v1') @@ -3968,9 +4864,9 @@ def upload_package(ctx, filename, skip_charm_build): # exit(1) -#@cli_osm.command(name='ro-dump') -#@click.pass_context -#def ro_dump(ctx): +# @cli_osm.command(name='ro-dump') +# @click.pass_context +# def ro_dump(ctx): # """shows RO agent information""" # check_client_version(ctx.obj, ctx.command.name, 'v1') # resp = ctx.obj.vim.get_resource_orchestrator() @@ -3981,9 +4877,9 @@ def upload_package(ctx, filename, skip_charm_build): # print(table) -#@cli_osm.command(name='vcs-list') -#@click.pass_context -#def vcs_list(ctx): +# @cli_osm.command(name='vcs-list') +# @click.pass_context +# def vcs_list(ctx): # check_client_version(ctx.obj, ctx.command.name, 'v1') # resp = ctx.obj.utils.get_vcs_info() # table = PrettyTable(['component name', 'state']) @@ -3993,33 +4889,47 @@ def upload_package(ctx, filename, skip_charm_build): # print(table) -@cli_osm.command(name='ns-action', short_help='executes an action/primitive over a NS instance') -@click.argument('ns_name') -@click.option('--vnf_name', default=None, help='member-vnf-index if the target is a vnf instead of a ns)') -@click.option('--kdu_name', default=None, help='kdu-name if the target is a kdu)') -@click.option('--vdu_id', default=None, help='vdu-id if the target is a vdu') -@click.option('--vdu_count', default=None, type=int, help='number of vdu instance of this vdu_id') -@click.option('--action_name', prompt=True, help='action name') -@click.option('--params', default=None, help='action params in YAML/JSON inline string') -@click.option('--params_file', default=None, help='YAML/JSON file with action params') -@click.option('--timeout', required=False, default=None, type=int, help='timeout in seconds') -@click.option('--wait', - required=False, - default=False, - is_flag=True, - help='do not return the control immediately, but keep it until the operation is completed, or timeout') +@cli_osm.command( + name="ns-action", short_help="executes an action/primitive over a NS instance" +) +@click.argument("ns_name") +@click.option( + "--vnf_name", + default=None, + help="member-vnf-index if the target is a vnf instead of a ns)", +) +@click.option("--kdu_name", default=None, help="kdu-name if the target is a kdu)") +@click.option("--vdu_id", default=None, help="vdu-id if the target is a vdu") +@click.option( + "--vdu_count", default=None, type=int, help="number of vdu instance of this vdu_id" +) +@click.option("--action_name", prompt=True, help="action name") +@click.option("--params", default=None, help="action params in YAML/JSON inline string") +@click.option("--params_file", default=None, help="YAML/JSON file with action params") +@click.option( + "--timeout", required=False, default=None, type=int, help="timeout in seconds" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context -def ns_action(ctx, - ns_name, - vnf_name, - kdu_name, - vdu_id, - vdu_count, - action_name, - params, - params_file, - timeout, - wait): +def ns_action( + ctx, + ns_name, + vnf_name, + kdu_name, + vdu_id, + vdu_count, + action_name, + params, + params_file, + timeout, + wait, +): """executes an action/primitive over a NS instance NS_NAME: name or ID of the NS instance @@ -4029,48 +4939,61 @@ def ns_action(ctx, check_client_version(ctx.obj, ctx.command.name) op_data = {} if vnf_name: - op_data['member_vnf_index'] = vnf_name + op_data["member_vnf_index"] = vnf_name if kdu_name: - op_data['kdu_name'] = kdu_name + op_data["kdu_name"] = kdu_name if vdu_id: - op_data['vdu_id'] = vdu_id + op_data["vdu_id"] = vdu_id if vdu_count is not None: - op_data['vdu_count_index'] = vdu_count + op_data["vdu_count_index"] = vdu_count if timeout: - op_data['timeout_ns_action'] = timeout - op_data['primitive'] = action_name + op_data["timeout_ns_action"] = timeout + op_data["primitive"] = action_name if params_file: - with open(params_file, 'r') as pf: + with open(params_file, "r") as pf: params = pf.read() if params: - op_data['primitive_params'] = yaml.safe_load(params) + op_data["primitive_params"] = yaml.safe_load(params) else: - op_data['primitive_params'] = {} - print(ctx.obj.ns.exec_op(ns_name, op_name='action', op_data=op_data, wait=wait)) + op_data["primitive_params"] = {} + print(ctx.obj.ns.exec_op(ns_name, op_name="action", op_data=op_data, wait=wait)) # except ClientException as e: # print(str(e)) # exit(1) -@cli_osm.command(name='vnf-scale', short_help='executes a VNF scale (adding/removing VDUs)') -@click.argument('ns_name') -@click.argument('vnf_name') -@click.option('--scaling-group', prompt=True, help="scaling-group-descriptor name to use") -@click.option('--scale-in', default=False, is_flag=True, help="performs a scale in operation") -@click.option('--scale-out', default=False, is_flag=True, help="performs a scale out operation (by default)") -@click.option('--timeout', required=False, default=None, type=int, help='timeout in seconds') -@click.option('--wait', required=False, default=False, is_flag=True, - help='do not return the control immediately, but keep it until the operation is completed, or timeout') +@cli_osm.command( + name="vnf-scale", short_help="executes a VNF scale (adding/removing VDUs)" +) +@click.argument("ns_name") +@click.argument("vnf_name") +@click.option( + "--scaling-group", prompt=True, help="scaling-group-descriptor name to use" +) +@click.option( + "--scale-in", default=False, is_flag=True, help="performs a scale in operation" +) +@click.option( + "--scale-out", + default=False, + is_flag=True, + help="performs a scale out operation (by default)", +) +@click.option( + "--timeout", required=False, default=None, type=int, help="timeout in seconds" +) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it until the operation is completed, or timeout", +) @click.pass_context -def vnf_scale(ctx, - ns_name, - vnf_name, - scaling_group, - scale_in, - scale_out, - timeout, - wait): +def vnf_scale( + ctx, ns_name, vnf_name, scaling_group, scale_in, scale_out, timeout, wait +): """ Executes a VNF scale (adding/removing VDUs) @@ -4083,7 +5006,9 @@ def vnf_scale(ctx, check_client_version(ctx.obj, ctx.command.name) if not scale_in and not scale_out: scale_out = True - ctx.obj.ns.scale_vnf(ns_name, vnf_name, scaling_group, scale_in, scale_out, wait, timeout) + ctx.obj.ns.scale_vnf( + ns_name, vnf_name, scaling_group, scale_in, scale_out, wait, timeout + ) # except ClientException as e: # print(str(e)) # exit(1) @@ -4093,11 +5018,10 @@ def vnf_scale(ctx, # Role Management Operations # ############################## -@cli_osm.command(name='role-create', short_help='creates a new role') -@click.argument('name') -@click.option('--permissions', - default=None, - help='role permissions using a dictionary') + +@cli_osm.command(name="role-create", short_help="creates a new role") +@click.argument("name") +@click.option("--permissions", default=None, help="role permissions using a dictionary") @click.pass_context def role_create(ctx, name, permissions): """ @@ -4116,20 +5040,18 @@ def role_create(ctx, name, permissions): # exit(1) -@cli_osm.command(name='role-update', short_help='updates a role') -@click.argument('name') -@click.option('--set-name', - default=None, - help='change name of rle') +@cli_osm.command(name="role-update", short_help="updates a role") +@click.argument("name") +@click.option("--set-name", default=None, help="change name of rle") # @click.option('--permissions', # default=None, # help='provide a yaml format dictionary with incremental changes. Values can be bool or None to delete') -@click.option('--add', - default=None, - help='yaml format dictionary with permission: True/False to access grant/denial') -@click.option('--remove', - default=None, - help='yaml format list to remove a permission') +@click.option( + "--add", + default=None, + help="yaml format dictionary with permission: True/False to access grant/denial", +) +@click.option("--remove", default=None, help="yaml format list to remove a permission") @click.pass_context def role_update(ctx, name, set_name, add, remove): """ @@ -4150,8 +5072,8 @@ def role_update(ctx, name, set_name, add, remove): # exit(1) -@cli_osm.command(name='role-delete', short_help='deletes a role') -@click.argument('name') +@cli_osm.command(name="role-delete", short_help="deletes a role") +@click.argument("name") # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions') @click.pass_context def role_delete(ctx, name): @@ -4170,9 +5092,13 @@ def role_delete(ctx, name): # exit(1) -@cli_osm.command(name='role-list', short_help='list all roles') -@click.option('--filter', default=None, multiple=True, - help='restricts the list to the projects matching the filter') +@cli_osm.command(name="role-list", short_help="list all roles") +@click.option( + "--filter", + default=None, + multiple=True, + help="restricts the list to the projects matching the filter", +) @click.pass_context def role_list(ctx, filter): """ @@ -4182,20 +5108,20 @@ def role_list(ctx, filter): # try: check_client_version(ctx.obj, ctx.command.name) if filter: - filter='&'.join(filter) + filter = "&".join(filter) resp = ctx.obj.role.list(filter) # except ClientException as e: # print(str(e)) # exit(1) - table = PrettyTable(['name', 'id']) + table = PrettyTable(["name", "id"]) for role in resp: - table.add_row([role['name'], role['_id']]) - table.align = 'l' + table.add_row([role["name"], role["_id"]]) + table.align = "l" print(table) -@cli_osm.command(name='role-show', short_help='show specific role') -@click.argument('name') +@cli_osm.command(name="role-show", short_help="show specific role") +@click.argument("name") @click.pass_context def role_show(ctx, name): """ @@ -4212,71 +5138,84 @@ def role_show(ctx, name): # print(str(e)) # exit(1) - table = PrettyTable(['key', 'attribute']) + table = PrettyTable(["key", "attribute"]) for k, v in resp.items(): table.add_row([k, json.dumps(v, indent=2)]) - table.align = 'l' + table.align = "l" print(table) -@cli_osm.command(name='package-create', - short_help='Create empty NS package structure') -@click.argument('package-type') -@click.argument('package-name') -@click.option('--base-directory', - default='.', - help=('(NS/VNF/NST) Set the location for package creation. Default: "."')) -@click.option('--image', - default="image-name", - help='(VNF) Set the name of the vdu image. Default "image-name"') -@click.option('--vdus', - default=1, - help='(VNF) Set the number of vdus in a VNF. Default 1') -@click.option('--vcpu', - default=1, - help='(VNF) Set the number of virtual CPUs in a vdu. Default 1') -@click.option('--memory', - default=1024, - help='(VNF) Set the memory size (MB) of the vdu. Default 1024') -@click.option('--storage', - default=10, - help='(VNF) Set the disk size (GB) of the vdu. Default 10') -@click.option('--interfaces', - default=0, - help='(VNF) Set the number of additional interfaces apart from the management interface. Default 0') -@click.option('--vendor', - default="OSM", - help='(NS/VNF) Set the descriptor vendor. Default "OSM"') -@click.option('--override', - default=False, - is_flag=True, - help='(NS/VNF/NST) Flag for overriding the package if exists.') -@click.option('--detailed', - is_flag=True, - default=False, - help='(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options') -@click.option('--netslice-subnets', - default=1, - help='(NST) Number of netslice subnets. Default 1') -@click.option('--netslice-vlds', - default=1, - help='(NST) Number of netslice vlds. Default 1') +@cli_osm.command(name="package-create", short_help="Create empty NS package structure") +@click.argument("package-type") +@click.argument("package-name") +@click.option( + "--base-directory", + default=".", + help=('(NS/VNF/NST) Set the location for package creation. Default: "."'), +) +@click.option( + "--image", + default="image-name", + help='(VNF) Set the name of the vdu image. Default "image-name"', +) +@click.option( + "--vdus", default=1, help="(VNF) Set the number of vdus in a VNF. Default 1" +) +@click.option( + "--vcpu", default=1, help="(VNF) Set the number of virtual CPUs in a vdu. Default 1" +) +@click.option( + "--memory", + default=1024, + help="(VNF) Set the memory size (MB) of the vdu. Default 1024", +) +@click.option( + "--storage", default=10, help="(VNF) Set the disk size (GB) of the vdu. Default 10" +) +@click.option( + "--interfaces", + default=0, + help="(VNF) Set the number of additional interfaces apart from the management interface. Default 0", +) +@click.option( + "--vendor", default="OSM", help='(NS/VNF) Set the descriptor vendor. Default "OSM"' +) +@click.option( + "--override", + default=False, + is_flag=True, + help="(NS/VNF/NST) Flag for overriding the package if exists.", +) +@click.option( + "--detailed", + is_flag=True, + default=False, + help="(NS/VNF/NST) Flag for generating descriptor .yaml with all possible commented options", +) +@click.option( + "--netslice-subnets", default=1, help="(NST) Number of netslice subnets. Default 1" +) +@click.option( + "--netslice-vlds", default=1, help="(NST) Number of netslice vlds. Default 1" +) @click.pass_context -def package_create(ctx, - package_type, - base_directory, - package_name, - override, - image, - vdus, - vcpu, - memory, - storage, - interfaces, - vendor, - detailed, - netslice_subnets, - netslice_vlds): +def package_create( + ctx, + package_type, + base_directory, + package_name, + override, + image, + vdus, + vcpu, + memory, + storage, + interfaces, + vendor, + detailed, + netslice_subnets, + netslice_vlds, +): """ Creates an OSM NS, VNF, NST package @@ -4288,44 +5227,51 @@ def package_create(ctx, # try: logger.debug("") check_client_version(ctx.obj, ctx.command.name) - print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name)) - resp = ctx.obj.package_tool.create(package_type, - base_directory, - package_name, - override=override, - image=image, - vdus=vdus, - vcpu=vcpu, - memory=memory, - storage=storage, - interfaces=interfaces, - vendor=vendor, - detailed=detailed, - netslice_subnets=netslice_subnets, - netslice_vlds=netslice_vlds) + print( + "Creating the {} structure: {}/{}".format( + package_type.upper(), base_directory, package_name + ) + ) + resp = ctx.obj.package_tool.create( + package_type, + base_directory, + package_name, + override=override, + image=image, + vdus=vdus, + vcpu=vcpu, + memory=memory, + storage=storage, + interfaces=interfaces, + vendor=vendor, + detailed=detailed, + netslice_subnets=netslice_subnets, + netslice_vlds=netslice_vlds, + ) print(resp) # except ClientException as inst: # print("ERROR: {}".format(inst)) # exit(1) -@cli_osm.command(name='package-validate', - short_help='Validate descriptors given a base directory') -@click.argument('base-directory', - default=".", - required=False) -@click.option('--recursive/--no-recursive', - default=True, - help='The activated recursive option will validate the yaml files' - ' within the indicated directory and in its subdirectories') -@click.option('--old', - is_flag=True, - default=False, - help='Validates also the descriptors using the previous OSM format (pre SOL006)') + +@cli_osm.command( + name="package-validate", short_help="Validate descriptors given a base directory" +) +@click.argument("base-directory", default=".", required=False) +@click.option( + "--recursive/--no-recursive", + default=True, + help="The activated recursive option will validate the yaml files" + " within the indicated directory and in its subdirectories", +) +@click.option( + "--old", + is_flag=True, + default=False, + help="Validates also the descriptors using the previous OSM format (pre SOL006)", +) @click.pass_context -def package_validate(ctx, - base_directory, - recursive, - old): +def package_validate(ctx, base_directory, recursive, old): """ Validate descriptors given a base directory. @@ -4340,7 +5286,9 @@ def package_validate(ctx, table.field_names = ["TYPE", "PATH", "VALID", "ERROR"] # Print the dictionary generated by the validation function for result in results: - table.add_row([result["type"], result["path"], result["valid"], result["error"]]) + table.add_row( + [result["type"], result["path"], result["valid"], result["error"]] + ) table.sortby = "VALID" table.align["PATH"] = "l" table.align["TYPE"] = "l" @@ -4350,24 +5298,25 @@ def package_validate(ctx, # print("ERROR: {}".format(inst)) # exit(1) -@cli_osm.command(name='package-translate', - short_help='Translate descriptors given a base directory') -@click.argument('base-directory', - default=".", - required=False) -@click.option('--recursive/--no-recursive', - default=True, - help='The activated recursive option will translate the yaml files' - ' within the indicated directory and in its subdirectories') -@click.option('--dryrun', - is_flag=True, - default=False, - help='Do not translate yet, only make a dry-run to test translation') + +@cli_osm.command( + name="package-translate", short_help="Translate descriptors given a base directory" +) +@click.argument("base-directory", default=".", required=False) +@click.option( + "--recursive/--no-recursive", + default=True, + help="The activated recursive option will translate the yaml files" + " within the indicated directory and in its subdirectories", +) +@click.option( + "--dryrun", + is_flag=True, + default=False, + help="Do not translate yet, only make a dry-run to test translation", +) @click.pass_context -def package_translate(ctx, - base_directory, - recursive, - dryrun): +def package_translate(ctx, base_directory, recursive, dryrun): """ Translate descriptors given a base directory. @@ -4378,10 +5327,26 @@ def package_translate(ctx, check_client_version(ctx.obj, ctx.command.name) results = ctx.obj.package_tool.translate(base_directory, recursive, dryrun) table = PrettyTable() - table.field_names = ["CURRENT TYPE", "NEW TYPE", "PATH", "VALID", "TRANSLATED", "ERROR"] + table.field_names = [ + "CURRENT TYPE", + "NEW TYPE", + "PATH", + "VALID", + "TRANSLATED", + "ERROR", + ] # Print the dictionary generated by the validation function for result in results: - table.add_row([result["current type"], result["new type"], result["path"], result["valid"], result["translated"], result["error"]]) + table.add_row( + [ + result["current type"], + result["new type"], + result["path"], + result["valid"], + result["translated"], + result["error"], + ] + ) table.sortby = "TRANSLATED" table.align["PATH"] = "l" table.align["TYPE"] = "l" @@ -4391,20 +5356,20 @@ def package_translate(ctx, # print("ERROR: {}".format(inst)) # exit(1) -@cli_osm.command(name='package-build', - short_help='Build the tar.gz of the package') -@click.argument('package-folder') -@click.option('--skip-validation', - default=False, - is_flag=True, - help='skip package validation') -@click.option('--skip-charm-build', default=False, is_flag=True, - help='the charm will not be compiled, it is assumed to already exist') + +@cli_osm.command(name="package-build", short_help="Build the tar.gz of the package") +@click.argument("package-folder") +@click.option( + "--skip-validation", default=False, is_flag=True, help="skip package validation" +) +@click.option( + "--skip-charm-build", + default=False, + is_flag=True, + help="the charm will not be compiled, it is assumed to already exist", +) @click.pass_context -def package_build(ctx, - package_folder, - skip_validation, - skip_charm_build): +def package_build(ctx, package_folder, skip_validation, skip_charm_build): """ Build the package NS, VNF given the package_folder. @@ -4414,21 +5379,24 @@ def package_build(ctx, # try: logger.debug("") check_client_version(ctx.obj, ctx.command.name) - results = ctx.obj.package_tool.build(package_folder, - skip_validation=skip_validation, - skip_charm_build=skip_charm_build) + results = ctx.obj.package_tool.build( + package_folder, + skip_validation=skip_validation, + skip_charm_build=skip_charm_build, + ) print(results) # except ClientException as inst: # print("ERROR: {}".format(inst)) # exit(1) -@cli_osm.command(name='descriptor-translate', - short_help='Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output') -@click.argument('descriptor-file', - required=True) + +@cli_osm.command( + name="descriptor-translate", + short_help="Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output", +) +@click.argument("descriptor-file", required=True) @click.pass_context -def descriptor_translate(ctx, - descriptor_file): +def descriptor_translate(ctx, descriptor_file): """ Translate input descriptor. @@ -4447,7 +5415,9 @@ def cli(): exit(0) except pycurl.error as exc: print(exc) - print('Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified') + print( + 'Maybe "--hostname" option or OSM_HOSTNAME environment variable needs to be specified' + ) except ClientException as exc: print("ERROR: {}".format(exc)) except (FileNotFoundError, PermissionError) as exc: @@ -4459,6 +5429,5 @@ def cli(): # TODO remove the ClientException captures from all places, unless they do something different -if __name__ == '__main__': +if __name__ == "__main__": cli() - diff --git a/osmclient/sol005/client.py b/osmclient/sol005/client.py index 00c50cb..495c425 100644 --- a/osmclient/sol005/client.py +++ b/osmclient/sol005/client.py @@ -18,7 +18,7 @@ OSM SOL005 client API """ -#from osmclient.v1 import vca +# from osmclient.v1 import vca from osmclient.sol005 import vnfd from osmclient.sol005 import nsd from osmclient.sol005 import nst @@ -43,39 +43,41 @@ import logging class Client(object): - def __init__( self, host=None, so_port=9999, - user='admin', - password='admin', - project='admin', - **kwargs): + user="admin", + password="admin", + project="admin", + **kwargs + ): self._user = user self._password = password self._project = project self._project_domain_name = kwargs.get("project_domain_name") self._user_domain_name = kwargs.get("user_domain_name") - self._logger = logging.getLogger('osmclient') - self._auth_endpoint = '/admin/v1/tokens' + self._logger = logging.getLogger("osmclient") + self._auth_endpoint = "/admin/v1/tokens" self._headers = {} self._token = None - if len(host.split(':')) > 1: + if len(host.split(":")) > 1: # backwards compatible, port provided as part of host - self._host = host.split(':')[0] - self._so_port = host.split(':')[1] + self._host = host.split(":")[0] + self._so_port = host.split(":")[1] else: self._host = host self._so_port = so_port self._http_client = http.Http( - 'https://{}:{}/osm'.format(self._host,self._so_port), **kwargs) - self._headers['Accept'] = 'application/json' - self._headers['Content-Type'] = 'application/yaml' - http_header = ['{}: {}'.format(key, val) - for (key, val) in list(self._headers.items())] + "https://{}:{}/osm".format(self._host, self._so_port), **kwargs + ) + self._headers["Accept"] = "application/json" + self._headers["Content-Type"] = "application/yaml" + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(self._headers.items()) + ] self._http_client.set_http_header(http_header) self.vnfd = vnfd.Vnfd(self._http_client, client=self) @@ -96,40 +98,46 @@ class Client(object): self.repo = repo.Repo(self._http_client, client=self) self.osmrepo = osmrepo.OSMRepo(self._http_client, client=self) self.package_tool = package_tool.PackageTool(client=self) - ''' + """ self.vca = vca.Vca(http_client, client=self, **kwargs) self.utils = utils.Utils(http_client, **kwargs) - ''' + """ def get_token(self): self._logger.debug("") if self._token is None: - postfields_dict = {'username': self._user, - 'password': self._password, - 'project_id': self._project} + postfields_dict = { + "username": self._user, + "password": self._password, + "project_id": self._project, + } if self._project_domain_name: postfields_dict["project_domain_name"] = self._project_domain_name if self._user_domain_name: postfields_dict["user_domain_name"] = self._user_domain_name - http_code, resp = self._http_client.post_cmd(endpoint=self._auth_endpoint, - postfields_dict=postfields_dict, - skip_query_admin=True) -# if http_code not in (200, 201, 202, 204): -# message ='Authentication error: not possible to get auth token\nresp:\n{}'.format(resp) -# raise ClientException(message) + http_code, resp = self._http_client.post_cmd( + endpoint=self._auth_endpoint, + postfields_dict=postfields_dict, + skip_query_admin=True, + ) + # if http_code not in (200, 201, 202, 204): + # message ='Authentication error: not possible to get auth token\nresp:\n{}'.format(resp) + # raise ClientException(message) token = json.loads(resp) if resp else None - self._token = token['id'] + self._token = token["id"] if self._token is not None: - self._headers['Authorization'] = 'Bearer {}'.format(self._token) - http_header = ['{}: {}'.format(key, val) - for (key, val) in list(self._headers.items())] + self._headers["Authorization"] = "Bearer {}".format(self._token) + http_header = [ + "{}: {}".format(key, val) + for (key, val) in list(self._headers.items()) + ] self._http_client.set_http_header(http_header) def get_version(self): _, resp = self._http_client.get2_cmd(endpoint="/version", skip_query_admin=True) - #print(http_code, resp) + # print(http_code, resp) try: resp = json.loads(resp) version = resp.get("version") @@ -140,10 +148,10 @@ class Client(object): return "{} {}".format(version, date) def set_default_params(self, **kwargs): - host = kwargs.pop('host', None) + host = kwargs.pop("host", None) if host != None: - self._host=host - port = kwargs.pop('port', None) + self._host = host + port = kwargs.pop("port", None) if port != None: - self._so_port=port + self._so_port = port self._http_client.set_query_admin(**kwargs) diff --git a/osmclient/sol005/http.py b/osmclient/sol005/http.py index 9a7bc6e..4234fc8 100644 --- a/osmclient/sol005/http.py +++ b/osmclient/sol005/http.py @@ -27,19 +27,19 @@ import pycurl class Http(http.Http): CONNECT_TIMEOUT = 15 - def __init__(self, url, user='admin', password='admin', **kwargs): + def __init__(self, url, user="admin", password="admin", **kwargs): self._url = url self._user = user self._password = password self._http_header = None - self._logger = logging.getLogger('osmclient') + self._logger = logging.getLogger("osmclient") self._default_query_admin = None self._all_projects = None self._public = None - if 'all_projects' in kwargs: - self._all_projects = kwargs['all_projects'] - if 'public' in kwargs: - self._public = kwargs['public'] + if "all_projects" in kwargs: + self._all_projects = kwargs["all_projects"] + if "public" in kwargs: + self._public = kwargs["public"] self._default_query_admin = self._complete_default_query_admin() def _complete_default_query_admin(self): @@ -52,10 +52,10 @@ class Http(http.Http): def _complete_endpoint(self, endpoint): if self._default_query_admin: - if '?' in endpoint: - endpoint = '&'.join([endpoint, self._default_query_admin]) + if "?" in endpoint: + endpoint = "&".join([endpoint, self._default_query_admin]) else: - endpoint = '?'.join([endpoint, self._default_query_admin]) + endpoint = "?".join([endpoint, self._default_query_admin]) return endpoint def _get_curl_cmd(self, endpoint, skip_query_admin=False): @@ -79,7 +79,9 @@ class Http(http.Http): curl_cmd = self._get_curl_cmd(endpoint, skip_query_admin) curl_cmd.setopt(pycurl.CUSTOMREQUEST, "DELETE") curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write) - self._logger.info("Request METHOD: {} URL: {}".format("DELETE", self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("DELETE", self._url + endpoint) + ) curl_cmd.perform() http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) self._logger.info("Response HTTPCODE: {}".format(http_code)) @@ -93,10 +95,16 @@ class Http(http.Http): else: return http_code, None - def send_cmd(self, endpoint='', postfields_dict=None, - formfile=None, filename=None, - put_method=False, patch_method=False, - skip_query_admin=False): + def send_cmd( + self, + endpoint="", + postfields_dict=None, + formfile=None, + filename=None, + put_method=False, + patch_method=False, + skip_query_admin=False, + ): self._logger.debug("") data = BytesIO() curl_cmd = self._get_curl_cmd(endpoint, skip_query_admin) @@ -109,9 +117,9 @@ class Http(http.Http): if postfields_dict is not None: jsondata = json.dumps(postfields_dict) - if 'password' in postfields_dict: + if "password" in postfields_dict: postfields_dict_copy = copy.deepcopy(postfields_dict) - postfields_dict_copy['password'] = '******' + postfields_dict_copy["password"] = "******" jsondata_log = json.dumps(postfields_dict_copy) else: jsondata_log = jsondata @@ -119,22 +127,26 @@ class Http(http.Http): curl_cmd.setopt(pycurl.POSTFIELDS, jsondata) elif formfile is not None: curl_cmd.setopt( - pycurl.HTTPPOST, - [((formfile[0], - (pycurl.FORM_FILE, - formfile[1])))]) + pycurl.HTTPPOST, [((formfile[0], (pycurl.FORM_FILE, formfile[1])))] + ) elif filename is not None: - with open(filename, 'rb') as stream: + with open(filename, "rb") as stream: postdata = stream.read() self._logger.verbose("Request POSTFIELDS: Binary content") curl_cmd.setopt(pycurl.POSTFIELDS, postdata) if put_method: - self._logger.info("Request METHOD: {} URL: {}".format("PUT", self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("PUT", self._url + endpoint) + ) elif patch_method: - self._logger.info("Request METHOD: {} URL: {}".format("PATCH", self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("PATCH", self._url + endpoint) + ) else: - self._logger.info("Request METHOD: {} URL: {}".format("POST", self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("POST", self._url + endpoint) + ) curl_cmd.perform() http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) self._logger.info("Response HTTPCODE: {}".format(http_code)) @@ -147,35 +159,62 @@ class Http(http.Http): else: return http_code, None - def post_cmd(self, endpoint='', postfields_dict=None, - formfile=None, filename=None, - skip_query_admin=False): + def post_cmd( + self, + endpoint="", + postfields_dict=None, + formfile=None, + filename=None, + skip_query_admin=False, + ): self._logger.debug("") - return self.send_cmd(endpoint=endpoint, - postfields_dict=postfields_dict, - formfile=formfile, filename=filename, - put_method=False, patch_method=False, - skip_query_admin=skip_query_admin) - - def put_cmd(self, endpoint='', postfields_dict=None, - formfile=None, filename=None, - skip_query_admin=False): + return self.send_cmd( + endpoint=endpoint, + postfields_dict=postfields_dict, + formfile=formfile, + filename=filename, + put_method=False, + patch_method=False, + skip_query_admin=skip_query_admin, + ) + + def put_cmd( + self, + endpoint="", + postfields_dict=None, + formfile=None, + filename=None, + skip_query_admin=False, + ): self._logger.debug("") - return self.send_cmd(endpoint=endpoint, - postfields_dict=postfields_dict, - formfile=formfile, filename=filename, - put_method=True, patch_method=False, - skip_query_admin=skip_query_admin) - - def patch_cmd(self, endpoint='', postfields_dict=None, - formfile=None, filename=None, - skip_query_admin=False): + return self.send_cmd( + endpoint=endpoint, + postfields_dict=postfields_dict, + formfile=formfile, + filename=filename, + put_method=True, + patch_method=False, + skip_query_admin=skip_query_admin, + ) + + def patch_cmd( + self, + endpoint="", + postfields_dict=None, + formfile=None, + filename=None, + skip_query_admin=False, + ): self._logger.debug("") - return self.send_cmd(endpoint=endpoint, - postfields_dict=postfields_dict, - formfile=formfile, filename=filename, - put_method=False, patch_method=True, - skip_query_admin=skip_query_admin) + return self.send_cmd( + endpoint=endpoint, + postfields_dict=postfields_dict, + formfile=formfile, + filename=filename, + put_method=False, + patch_method=True, + skip_query_admin=skip_query_admin, + ) def get2_cmd(self, endpoint, skip_query_admin=False): self._logger.debug("") @@ -183,7 +222,9 @@ class Http(http.Http): curl_cmd = self._get_curl_cmd(endpoint, skip_query_admin) curl_cmd.setopt(pycurl.HTTPGET, 1) curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write) - self._logger.info("Request METHOD: {} URL: {}".format("GET", self._url + endpoint)) + self._logger.info( + "Request METHOD: {} URL: {}".format("GET", self._url + endpoint) + ) curl_cmd.perform() http_code = curl_cmd.getinfo(pycurl.HTTP_CODE) self._logger.info("Response HTTPCODE: {}".format(http_code)) @@ -200,7 +241,9 @@ class Http(http.Http): resp = "" if data.getvalue(): data_text = data.getvalue().decode() - self._logger.verbose("Response {} DATA: {}".format(http_code, data_text)) + self._logger.verbose( + "Response {} DATA: {}".format(http_code, data_text) + ) resp = ": " + data_text else: self._logger.verbose("Response {}".format(http_code)) @@ -209,8 +252,8 @@ class Http(http.Http): raise OsmHttpException("Error {}{}".format(http_code, resp)) def set_query_admin(self, **kwargs): - if 'all_projects' in kwargs: - self._all_projects = kwargs['all_projects'] - if 'public' in kwargs: - self._public = kwargs['public'] + if "all_projects" in kwargs: + self._all_projects = kwargs["all_projects"] + if "public" in kwargs: + self._public = kwargs["public"] self._default_query_admin = self._complete_default_query_admin() diff --git a/osmclient/sol005/k8scluster.py b/osmclient/sol005/k8scluster.py index 4ac2e48..0b99a37 100644 --- a/osmclient/sol005/k8scluster.py +++ b/osmclient/sol005/k8scluster.py @@ -21,37 +21,39 @@ from osmclient.common.exceptions import NotFound from osmclient.common.exceptions import ClientException import json + class K8scluster(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/k8sclusters' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/k8sclusters" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def create(self, name, k8s_cluster): - def get_vim_account_id(vim_account): vim = self._client.vim.get(vim_account) if vim is None: raise NotFound("cannot find vim account '{}'".format(vim_account)) - return vim['_id'] + return vim["_id"] self._client.get_token() - k8s_cluster['vim_account'] = get_vim_account_id(k8s_cluster['vim_account']) - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=k8s_cluster) - #print 'HTTP CODE: {}'.format(http_code) - #print 'RESP: {}'.format(resp) - #if http_code in (200, 201, 202, 204): + k8s_cluster["vim_account"] = get_vim_account_id(k8s_cluster["vim_account"]) + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=k8s_cluster + ) + # print 'HTTP CODE: {}'.format(http_code) + # print 'RESP: {}'.format(resp) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format(resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -63,13 +65,15 @@ class K8scluster(object): def update(self, name, k8s_cluster): self._client.get_token() cluster = self.get(name) - http_code, resp = self._http.put_cmd(endpoint='{}/{}'.format(self._apiBase,cluster['_id']), - postfields_dict=k8s_cluster) + http_code, resp = self._http.put_cmd( + endpoint="{}/{}".format(self._apiBase, cluster["_id"]), + postfields_dict=k8s_cluster, + ) # print 'HTTP CODE: {}'.format(http_code) # print 'RESP: {}'.format(resp) - #if http_code in (200, 201, 202, 204): + # if http_code in (200, 201, 202, 204): # pass - #else: + # else: # msg = "" # if resp: # try: @@ -79,11 +83,10 @@ class K8scluster(object): # raise ClientException("failed to update K8s cluster {} - {}".format(name, msg)) def get_id(self, name): - """Returns a K8s cluster id from a K8s cluster name - """ + """Returns a K8s cluster id from a K8s cluster name""" for cluster in self.list(): - if name == cluster['name']: - return cluster['_id'] + if name == cluster["name"]: + return cluster["_id"] raise NotFound("K8s cluster {} not found".format(name)) def delete(self, name, force=False): @@ -91,52 +94,52 @@ class K8scluster(object): cluster_id = name if not utils.validate_uuid4(name): cluster_id = self.get_id(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - cluster_id, querystring)) - #print 'HTTP CODE: {}'.format(http_code) - #print 'RESP: {}'.format(resp) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, cluster_id, querystring) + ) + # print 'HTTP CODE: {}'.format(http_code) + # print 'RESP: {}'.format(resp) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" - # if resp: - # try: - # msg = json.loads(resp) - # except ValueError: - # msg = resp - raise ClientException("failed to delete K8s cluster {} - {}".format(name, msg)) + # if resp: + # try: + # msg = json.loads(resp) + # except ValueError: + # msg = resp + raise ClientException( + "failed to delete K8s cluster {} - {}".format(name, msg) + ) def list(self, filter=None): - """Returns a list of K8s clusters - """ + """Returns a list of K8s clusters""" self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: - return json.loads(resp) + return json.loads(resp) return list() def get(self, name): - """Returns a K8s cluster based on name or id - """ + """Returns a K8s cluster based on name or id""" self._client.get_token() cluster_id = name if not utils.validate_uuid4(name): cluster_id = self.get_id(name) try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase,cluster_id)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, cluster_id)) if resp: resp = json.loads(resp) - if not resp or '_id' not in resp: - raise ClientException('failed to get K8s cluster info: {}'.format(resp)) + if not resp or "_id" not in resp: + raise ClientException("failed to get K8s cluster info: {}".format(resp)) return resp except NotFound: raise NotFound("K8s cluster {} not found".format(name)) - diff --git a/osmclient/sol005/ns.py b/osmclient/sol005/ns.py index b551868..d457cbd 100644 --- a/osmclient/sol005/ns.py +++ b/osmclient/sol005/ns.py @@ -28,58 +28,59 @@ import logging class Ns(object): - def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/nslcm' - self._apiVersion = '/v1' - self._apiResource = '/ns_instances_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/nslcm" + self._apiVersion = "/v1" + self._apiResource = "/ns_instances_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) # NS '--wait' option def _wait(self, id, wait_time, deleteFlag=False): self._logger.debug("") # Endpoint to get operation status - apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/ns_lcm_op_occs') + apiUrlStatus = "{}{}{}".format( + self._apiName, self._apiVersion, "/ns_lcm_op_occs" + ) # Wait for status for NS instance creation/update/deletion if isinstance(wait_time, bool): wait_time = WaitForStatus.TIMEOUT_NS_OPERATION WaitForStatus.wait_for_status( - 'NS', + "NS", str(id), wait_time, apiUrlStatus, self._http.get2_cmd, - deleteFlag=deleteFlag) + deleteFlag=deleteFlag, + ) def list(self, filter=None): - """Returns a list of NS - """ + """Returns a list of NS""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns an NS based on name or id - """ + """Returns an NS based on name or id""" self._logger.debug("") self._client.get_token() if utils.validate_uuid4(name): for ns in self.list(): - if name == ns['_id']: + if name == ns["_id"]: return ns else: for ns in self.list(): - if name == ns['name']: + if name == ns["name"]: return ns raise NotFound("ns '{}' not found".format(name)) @@ -89,13 +90,13 @@ class Ns(object): ns_id = name if not utils.validate_uuid4(name): for ns in self.list(): - if name == ns['name']: - ns_id = ns['_id'] + if name == ns["name"]: + ns_id = ns["_id"] break try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, ns_id)) - #resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, ns_id)) - #print(yaml.safe_dump(resp)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, ns_id)) + # resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, ns_id)) + # print(yaml.safe_dump(resp)) if resp: return json.loads(resp) except NotFound: @@ -118,16 +119,17 @@ class Ns(object): self._logger.debug("") ns = self.get(name) querystring_list = [] - querystring = '' + querystring = "" if config: ns_config = yaml.safe_load(config) querystring_list += ["{}={}".format(k, v) for k, v in ns_config.items()] if force: - querystring_list.append('FORCE=True') + querystring_list.append("FORCE=True") if querystring_list: querystring = "?" + "&".join(querystring_list) - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - ns['_id'], querystring)) + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, ns["_id"], querystring) + ) # TODO change to use a POST self._http.post_cmd('{}/{}/terminate{}'.format(_apiBase, ns['_id'], querystring), # postfields_dict=ns_config) # seting autoremove as True by default @@ -137,11 +139,11 @@ class Ns(object): if wait and resp: resp = json.loads(resp) # For the 'delete' operation, '_id' is used - self._wait(resp.get('_id'), wait, deleteFlag=True) + self._wait(resp.get("_id"), wait, deleteFlag=True) else: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" # if resp: @@ -151,9 +153,17 @@ class Ns(object): # msg = resp raise ClientException("failed to delete ns {} - {}".format(name, msg)) - def create(self, nsd_name, nsr_name, account, config=None, - ssh_keys=None, description='default description', - admin_status='ENABLED', wait=False): + def create( + self, + nsd_name, + nsr_name, + account, + config=None, + ssh_keys=None, + description="default description", + admin_status="ENABLED", + wait=False, + ): self._logger.debug("") self._client.get_token() nsd = self._client.nsd.get(nsd_name) @@ -168,8 +178,8 @@ class Ns(object): vim = self._client.vim.get(vim_account) if vim is None: raise NotFound("cannot find vim account '{}'".format(vim_account)) - vim_account_id[vim_account] = vim['_id'] - return vim['_id'] + vim_account_id[vim_account] = vim["_id"] + return vim["_id"] def get_wim_account_id(wim_account): self._logger.debug("") @@ -181,38 +191,44 @@ class Ns(object): wim = self._client.wim.get(wim_account) if wim is None: raise NotFound("cannot find wim account '{}'".format(wim_account)) - wim_account_id[wim_account] = wim['_id'] - return wim['_id'] + wim_account_id[wim_account] = wim["_id"] + return wim["_id"] ns = {} - ns['nsdId'] = nsd['_id'] - ns['nsName'] = nsr_name - ns['nsDescription'] = description - ns['vimAccountId'] = get_vim_account_id(account) - #ns['userdata'] = {} - #ns['userdata']['key1']='value1' - #ns['userdata']['key2']='value2' + ns["nsdId"] = nsd["_id"] + ns["nsName"] = nsr_name + ns["nsDescription"] = description + ns["vimAccountId"] = get_vim_account_id(account) + # ns['userdata'] = {} + # ns['userdata']['key1']='value1' + # ns['userdata']['key2']='value2' if ssh_keys is not None: - ns['ssh_keys'] = [] - for pubkeyfile in ssh_keys.split(','): - with open(pubkeyfile, 'r') as f: - ns['ssh_keys'].append(f.read()) + ns["ssh_keys"] = [] + for pubkeyfile in ssh_keys.split(","): + with open(pubkeyfile, "r") as f: + ns["ssh_keys"].append(f.read()) if config: ns_config = yaml.safe_load(config) if "vim-network-name" in ns_config: ns_config["vld"] = ns_config.pop("vim-network-name") if "vld" in ns_config: if not isinstance(ns_config["vld"], list): - raise ClientException("Error at --config 'vld' must be a list of dictionaries") + raise ClientException( + "Error at --config 'vld' must be a list of dictionaries" + ) for vld in ns_config["vld"]: if not isinstance(vld, dict): - raise ClientException("Error at --config 'vld' must be a list of dictionaries") + raise ClientException( + "Error at --config 'vld' must be a list of dictionaries" + ) if vld.get("vim-network-name"): if isinstance(vld["vim-network-name"], dict): vim_network_name_dict = {} for vim_account, vim_net in vld["vim-network-name"].items(): - vim_network_name_dict[get_vim_account_id(vim_account)] = vim_net + vim_network_name_dict[ + get_vim_account_id(vim_account) + ] = vim_net vld["vim-network-name"] = vim_network_name_dict if "wim_account" in vld and vld["wim_account"] is not None: vld["wimAccountId"] = get_wim_account_id(vld.pop("wim_account")) @@ -223,20 +239,28 @@ class Ns(object): if "additionalParamsForNs" in ns_config: if not isinstance(ns_config["additionalParamsForNs"], dict): - raise ClientException("Error at --config 'additionalParamsForNs' must be a dictionary") + raise ClientException( + "Error at --config 'additionalParamsForNs' must be a dictionary" + ) if "additionalParamsForVnf" in ns_config: if not isinstance(ns_config["additionalParamsForVnf"], list): - raise ClientException("Error at --config 'additionalParamsForVnf' must be a list") + raise ClientException( + "Error at --config 'additionalParamsForVnf' must be a list" + ) for additional_param_vnf in ns_config["additionalParamsForVnf"]: if not isinstance(additional_param_vnf, dict): - raise ClientException("Error at --config 'additionalParamsForVnf' items must be dictionaries") + raise ClientException( + "Error at --config 'additionalParamsForVnf' items must be dictionaries" + ) if not additional_param_vnf.get("member-vnf-index"): - raise ClientException("Error at --config 'additionalParamsForVnf' items must contain " - "'member-vnf-index'") + raise ClientException( + "Error at --config 'additionalParamsForVnf' items must contain " + "'member-vnf-index'" + ) if "wim_account" in ns_config: wim_account = ns_config.pop("wim_account") if wim_account is not None: - ns['wimAccountId'] = get_wim_account_id(wim_account) + ns["wimAccountId"] = get_wim_account_id(wim_account) # rest of parameters without any transformation or checking # "timeout_ns_deploy" # "placement-engine" @@ -244,30 +268,34 @@ class Ns(object): # print(yaml.safe_dump(ns)) try: - self._apiResource = '/ns_instances_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._apiResource = "/ns_instances_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) headers = self._client._headers - headers['Content-Type'] = 'application/yaml' - http_header = ['{}: {}'.format(key,val) - for (key,val) in list(headers.items())] + headers["Content-Type"] = "application/yaml" + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=ns) + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=ns + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {} '.format( - resp)) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {} ".format(resp) + ) if wait: # Wait for status for NS instance creation - self._wait(resp.get('nslcmop_id'), wait) - print(resp['id']) - return resp['id'] - #else: + self._wait(resp.get("nslcmop_id"), wait) + print(resp["id"]) + return resp["id"] + # else: # msg = "" # if resp: # try: @@ -276,111 +304,121 @@ class Ns(object): # msg = resp # raise ClientException(msg) except ClientException as exc: - message="failed to create ns: {} nsd: {}\nerror:\n{}".format( - nsr_name, - nsd_name, - str(exc)) + message = "failed to create ns: {} nsd: {}\nerror:\n{}".format( + nsr_name, nsd_name, str(exc) + ) raise ClientException(message) def list_op(self, name, filter=None): - """Returns the list of operations of a NS - """ + """Returns the list of operations of a NS""" self._logger.debug("") ns = self.get(name) try: - self._apiResource = '/ns_lcm_op_occs' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - filter_string = '' + self._apiResource = "/ns_lcm_op_occs" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + filter_string = "" if filter: - filter_string = '&{}'.format(filter) - http_code, resp = self._http.get2_cmd('{}?nsInstanceId={}{}'.format( - self._apiBase, ns['_id'], - filter_string) ) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + filter_string = "&{}".format(filter) + http_code, resp = self._http.get2_cmd( + "{}?nsInstanceId={}{}".format(self._apiBase, ns["_id"], filter_string) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 200: if resp: resp = json.loads(resp) return resp else: - raise ClientException('unexpected response from server') + raise ClientException("unexpected response from server") else: msg = resp or "" - # if resp: - # try: - # resp = json.loads(resp) - # msg = resp['detail'] - # except ValueError: - # msg = resp + # if resp: + # try: + # resp = json.loads(resp) + # msg = resp['detail'] + # except ValueError: + # msg = resp raise ClientException(msg) except ClientException as exc: - message="failed to get operation list of NS {}:\nerror:\n{}".format( - name, - str(exc)) + message = "failed to get operation list of NS {}:\nerror:\n{}".format( + name, str(exc) + ) raise ClientException(message) def get_op(self, operationId): - """Returns the status of an operation - """ + """Returns the status of an operation""" self._logger.debug("") self._client.get_token() try: - self._apiResource = '/ns_lcm_op_occs' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - http_code, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, operationId)) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + self._apiResource = "/ns_lcm_op_occs" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + http_code, resp = self._http.get2_cmd( + "{}/{}".format(self._apiBase, operationId) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 200: if resp: resp = json.loads(resp) return resp else: - raise ClientException('unexpected response from server') + raise ClientException("unexpected response from server") else: msg = resp or "" - # if resp: - # try: - # resp = json.loads(resp) - # msg = resp['detail'] - # except ValueError: - # msg = resp + # if resp: + # try: + # resp = json.loads(resp) + # msg = resp['detail'] + # except ValueError: + # msg = resp raise ClientException(msg) except ClientException as exc: - message="failed to get status of operation {}:\nerror:\n{}".format( - operationId, - str(exc)) + message = "failed to get status of operation {}:\nerror:\n{}".format( + operationId, str(exc) + ) raise ClientException(message) - def exec_op(self, name, op_name, op_data=None, wait=False, ): - """Executes an operation on a NS - """ + def exec_op( + self, + name, + op_name, + op_data=None, + wait=False, + ): + """Executes an operation on a NS""" self._logger.debug("") ns = self.get(name) try: ns = self.get(name) - self._apiResource = '/ns_instances' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - endpoint = '{}/{}/{}'.format(self._apiBase, ns['_id'], op_name) - #print('OP_NAME: {}'.format(op_name)) - #print('OP_DATA: {}'.format(json.dumps(op_data))) - http_code, resp = self._http.post_cmd(endpoint=endpoint, postfields_dict=op_data) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + self._apiResource = "/ns_instances" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + endpoint = "{}/{}/{}".format(self._apiBase, ns["_id"], op_name) + # print('OP_NAME: {}'.format(op_name)) + # print('OP_DATA: {}'.format(json.dumps(op_data))) + http_code, resp = self._http.post_cmd( + endpoint=endpoint, postfields_dict=op_data + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) if wait: # Wait for status for NS instance action # For the 'action' operation, 'id' is used - self._wait(resp.get('id'), wait) - return resp['id'] - #else: + self._wait(resp.get("id"), wait) + return resp["id"] + # else: # msg = "" # if resp: # try: @@ -389,18 +427,24 @@ class Ns(object): # msg = resp # raise ClientException(msg) except ClientException as exc: - message="failed to exec operation {}:\nerror:\n{}".format( - name, - str(exc)) + message = "failed to exec operation {}:\nerror:\n{}".format(name, str(exc)) raise ClientException(message) - def scale_vnf(self, ns_name, vnf_name, scaling_group, scale_in, scale_out, wait=False, timeout=None): - """Scales a VNF by adding/removing VDUs - """ + def scale_vnf( + self, + ns_name, + vnf_name, + scaling_group, + scale_in, + scale_out, + wait=False, + timeout=None, + ): + """Scales a VNF by adding/removing VDUs""" self._logger.debug("") self._client.get_token() try: - op_data={} + op_data = {} op_data["scaleType"] = "SCALE_VNF" op_data["scaleVnfData"] = {} if scale_in and not scale_out: @@ -415,11 +459,12 @@ class Ns(object): } if timeout: op_data["timeout_ns_scale"] = timeout - op_id = self.exec_op(ns_name, op_name='scale', op_data=op_data, wait=wait) + op_id = self.exec_op(ns_name, op_name="scale", op_data=op_data, wait=wait) print(str(op_id)) except ClientException as exc: - message="failed to scale vnf {} of ns {}:\nerror:\n{}".format( - vnf_name, ns_name, str(exc)) + message = "failed to scale vnf {} of ns {}:\nerror:\n{}".format( + vnf_name, ns_name, str(exc) + ) raise ClientException(message) def create_alarm(self, alarm): @@ -429,14 +474,15 @@ class Ns(object): data["create_alarm_request"] = {} data["create_alarm_request"]["alarm_create_request"] = alarm try: - http_code, resp = self._http.post_cmd(endpoint='/test/message/alarm_request', - postfields_dict=data) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + http_code, resp = self._http.post_cmd( + endpoint="/test/message/alarm_request", postfields_dict=data + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) # if http_code in (200, 201, 202, 204): # resp = json.loads(resp) - print('Alarm created') - #else: + print("Alarm created") + # else: # msg = "" # if resp: # try: @@ -446,9 +492,7 @@ class Ns(object): # raise ClientException('error: code: {}, resp: {}'.format( # http_code, msg)) except ClientException as exc: - message="failed to create alarm: alarm {}\n{}".format( - alarm, - str(exc)) + message = "failed to create alarm: alarm {}\n{}".format(alarm, str(exc)) raise ClientException(message) def delete_alarm(self, name): @@ -459,14 +503,15 @@ class Ns(object): data["delete_alarm_request"]["alarm_delete_request"] = {} data["delete_alarm_request"]["alarm_delete_request"]["alarm_uuid"] = name try: - http_code, resp = self._http.post_cmd(endpoint='/test/message/alarm_request', - postfields_dict=data) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + http_code, resp = self._http.post_cmd( + endpoint="/test/message/alarm_request", postfields_dict=data + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) # if http_code in (200, 201, 202, 204): # resp = json.loads(resp) - print('Alarm deleted') - #else: + print("Alarm deleted") + # else: # msg = "" # if resp: # try: @@ -476,9 +521,7 @@ class Ns(object): # raise ClientException('error: code: {}, resp: {}'.format( # http_code, msg)) except ClientException as exc: - message="failed to delete alarm: alarm {}\n{}".format( - name, - str(exc)) + message = "failed to delete alarm: alarm {}\n{}".format(name, str(exc)) raise ClientException(message) def export_metric(self, metric): @@ -487,14 +530,15 @@ class Ns(object): data = {} data["read_metric_data_request"] = metric try: - http_code, resp = self._http.post_cmd(endpoint='/test/message/metric_request', - postfields_dict=data) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + http_code, resp = self._http.post_cmd( + endpoint="/test/message/metric_request", postfields_dict=data + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) # if http_code in (200, 201, 202, 204): # resp = json.loads(resp) - return 'Metric exported' - #else: + return "Metric exported" + # else: # msg = "" # if resp: # try: @@ -504,9 +548,7 @@ class Ns(object): # raise ClientException('error: code: {}, resp: {}'.format( # http_code, msg)) except ClientException as exc: - message="failed to export metric: metric {}\n{}".format( - metric, - str(exc)) + message = "failed to export metric: metric {}\n{}".format(metric, str(exc)) raise ClientException(message) def get_field(self, ns_name, field): @@ -520,4 +562,3 @@ class Ns(object): return nsr[field] raise NotFound("failed to find {} in ns {}".format(field, ns_name)) - diff --git a/osmclient/sol005/nsd.py b/osmclient/sol005/nsd.py index 59c6d29..7c29252 100644 --- a/osmclient/sol005/nsd.py +++ b/osmclient/sol005/nsd.py @@ -29,24 +29,24 @@ import os.path class Nsd(object): - def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/nsd' - self._apiVersion = '/v1' - self._apiResource = '/ns_descriptors' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/nsd" + self._apiVersion = "/v1" + self._apiResource = "/ns_descriptors" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def list(self, filter=None): self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase, filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: return json.loads(resp) @@ -57,11 +57,11 @@ class Nsd(object): self._client.get_token() if utils.validate_uuid4(name): for nsd in self.list(): - if name == nsd['_id']: + if name == nsd["_id"]: return nsd else: for nsd in self.list(): - if 'name' in nsd and name == nsd['name']: + if "name" in nsd and name == nsd["name"]: return nsd raise NotFound("nsd {} not found".format(name)) @@ -72,7 +72,7 @@ class Nsd(object): nsd = self.get(name) # It is redundant, since the previous one already gets the whole nsdinfo # The only difference is that a different primitive is exercised - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, nsd['_id'])) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, nsd["_id"])) if resp: return json.loads(resp) except NotFound: @@ -84,50 +84,58 @@ class Nsd(object): # Call to get_token not required, because will be implicitly called by get. nsd = self.get(name) headers = self._client._headers - headers['Accept'] = 'application/binary' - http_code, resp = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, nsd['_id'], thing)) + headers["Accept"] = "application/binary" + http_code, resp = self._http.get2_cmd( + "{}/{}/{}".format(self._apiBase, nsd["_id"], thing) + ) if resp: return json.loads(resp) else: msg = resp or "" - raise ClientException("failed to get {} from {} - {}".format(thing, name, msg)) + raise ClientException( + "failed to get {} from {} - {}".format(thing, name, msg) + ) def get_descriptor(self, name, filename): self._logger.debug("") - self.get_thing(name, 'nsd', filename) + self.get_thing(name, "nsd", filename) def get_package(self, name, filename): self._logger.debug("") - self.get_thing(name, 'package_content', filename) + self.get_thing(name, "package_content", filename) def get_artifact(self, name, artifact, filename): self._logger.debug("") - self.get_thing(name, 'artifacts/{}'.format(artifact), filename) + self.get_thing(name, "artifacts/{}".format(artifact), filename) def delete(self, name, force=False): self._logger.debug("") nsd = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - nsd['_id'], querystring)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, nsd["_id"], querystring) + ) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" raise ClientException("failed to delete nsd {} - {}".format(name, msg)) - def create(self, filename, overwrite=None, update_endpoint=None, skip_charm_build=False): + def create( + self, filename, overwrite=None, update_endpoint=None, skip_charm_build=False + ): self._logger.debug("") if os.path.isdir(filename): - filename = filename.rstrip('/') - filename = self._client.package_tool.build(filename, skip_validation=False, - skip_charm_build=skip_charm_build) + filename = filename.rstrip("/") + filename = self._client.package_tool.build( + filename, skip_validation=False, skip_charm_build=skip_charm_build + ) self.create(filename, overwrite=overwrite, update_endpoint=update_endpoint) else: self._client.get_token() @@ -135,46 +143,56 @@ class Nsd(object): if mime_type is None: raise ClientException( "Unexpected MIME type for file {}: MIME type {}".format( - filename, mime_type) + filename, mime_type + ) ) headers = self._client._headers - headers['Content-Filename'] = basename(filename) - if mime_type in ['application/yaml', 'text/plain', 'application/json']: - headers['Content-Type'] = 'text/plain' - elif mime_type in ['application/gzip', 'application/x-gzip']: - headers['Content-Type'] = 'application/gzip' + headers["Content-Filename"] = basename(filename) + if mime_type in ["application/yaml", "text/plain", "application/json"]: + headers["Content-Type"] = "text/plain" + elif mime_type in ["application/gzip", "application/x-gzip"]: + headers["Content-Type"] = "application/gzip" else: raise ClientException( "Unexpected MIME type for file {}: MIME type {}".format( - filename, mime_type) + filename, mime_type + ) ) headers["Content-File-MD5"] = utils.md5(filename) - http_header = ['{}: {}'.format(key, val) - for (key, val) in list(headers.items())] + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) if update_endpoint: - http_code, resp = self._http.put_cmd(endpoint=update_endpoint, filename=filename) + http_code, resp = self._http.put_cmd( + endpoint=update_endpoint, filename=filename + ) else: - ow_string = '' + ow_string = "" if overwrite: - ow_string = '?{}'.format(overwrite) - self._apiResource = '/ns_descriptors_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - endpoint = '{}{}'.format(self._apiBase, ow_string) - http_code, resp = self._http.post_cmd(endpoint=endpoint, filename=filename) + ow_string = "?{}".format(overwrite) + self._apiResource = "/ns_descriptors_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + endpoint = "{}{}".format(self._apiBase, ow_string) + http_code, resp = self._http.post_cmd( + endpoint=endpoint, filename=filename + ) if http_code in (200, 201, 202): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format(resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) + print(resp["id"]) elif http_code == 204: - print('Updated') + print("Updated") def update(self, name, filename): self._logger.debug("") nsd = self.get(name) - endpoint = '{}/{}/nsd_content'.format(self._apiBase, nsd['_id']) + endpoint = "{}/{}/nsd_content".format(self._apiBase, nsd["_id"]) self.create(filename=filename, update_endpoint=endpoint) diff --git a/osmclient/sol005/nsi.py b/osmclient/sol005/nsi.py index 20065b7..999959e 100644 --- a/osmclient/sol005/nsi.py +++ b/osmclient/sol005/nsi.py @@ -28,59 +28,60 @@ import logging class Nsi(object): - def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/nsilcm' - self._apiVersion = '/v1' - self._apiResource = '/netslice_instances_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/nsilcm" + self._apiVersion = "/v1" + self._apiResource = "/netslice_instances_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) # NSI '--wait' option def _wait(self, id, wait_time, deleteFlag=False): self._logger.debug("") self._client.get_token() # Endpoint to get operation status - apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/nsi_lcm_op_occs') + apiUrlStatus = "{}{}{}".format( + self._apiName, self._apiVersion, "/nsi_lcm_op_occs" + ) # Wait for status for NSI instance creation/update/deletion if isinstance(wait_time, bool): wait_time = WaitForStatus.TIMEOUT_NSI_OPERATION WaitForStatus.wait_for_status( - 'NSI', + "NSI", str(id), wait_time, apiUrlStatus, self._http.get2_cmd, - deleteFlag=deleteFlag) + deleteFlag=deleteFlag, + ) def list(self, filter=None): - """Returns a list of NSI - """ + """Returns a list of NSI""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns an NSI based on name or id - """ + """Returns an NSI based on name or id""" self._logger.debug("") self._client.get_token() if utils.validate_uuid4(name): for nsi in self.list(): - if name == nsi['_id']: + if name == nsi["_id"]: return nsi else: for nsi in self.list(): - if name == nsi['name']: + if name == nsi["name"]: return nsi raise NotFound("nsi {} not found".format(name)) @@ -90,13 +91,13 @@ class Nsi(object): self._client.get_token() if not utils.validate_uuid4(name): for nsi in self.list(): - if name == nsi['name']: - nsi_id = nsi['_id'] + if name == nsi["name"]: + nsi_id = nsi["_id"] break try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, nsi_id)) - #resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, nsi_id)) - #print(yaml.safe_dump(resp)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, nsi_id)) + # resp = self._http.get_cmd('{}/{}/nsd_content'.format(self._apiBase, nsi_id)) + # print(yaml.safe_dump(resp)) if resp: return json.loads(resp) except NotFound: @@ -106,11 +107,12 @@ class Nsi(object): def delete(self, name, force=False, wait=False): self._logger.debug("") nsi = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - nsi['_id'], querystring)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, nsi["_id"], querystring) + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) if http_code == 202: @@ -118,11 +120,11 @@ class Nsi(object): resp = json.loads(resp) # Wait for status for NSI instance deletion # For the 'delete' operation, '_id' is used - self._wait(resp.get('_id'), wait, deleteFlag=True) + self._wait(resp.get("_id"), wait, deleteFlag=True) else: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" # if resp: @@ -132,9 +134,17 @@ class Nsi(object): # msg = resp raise ClientException("failed to delete nsi {} - {}".format(name, msg)) - def create(self, nst_name, nsi_name, account, config=None, - ssh_keys=None, description='default description', - admin_status='ENABLED', wait=False): + def create( + self, + nst_name, + nsi_name, + account, + config=None, + ssh_keys=None, + description="default description", + admin_status="ENABLED", + wait=False, + ): self._logger.debug("") self._client.get_token() @@ -150,17 +160,17 @@ class Nsi(object): vim = self._client.vim.get(vim_account) if vim is None: raise NotFound("cannot find vim account '{}'".format(vim_account)) - vim_account_id[vim_account] = vim['_id'] - return vim['_id'] + vim_account_id[vim_account] = vim["_id"] + return vim["_id"] nsi = {} - nsi['nstId'] = nst['_id'] - nsi['nsiName'] = nsi_name - nsi['nsiDescription'] = description - nsi['vimAccountId'] = get_vim_account_id(account) - #nsi['userdata'] = {} - #nsi['userdata']['key1']='value1' - #nsi['userdata']['key2']='value2' + nsi["nstId"] = nst["_id"] + nsi["nsiName"] = nsi_name + nsi["nsiDescription"] = description + nsi["vimAccountId"] = get_vim_account_id(account) + # nsi['userdata'] = {} + # nsi['userdata']['key1']='value1' + # nsi['userdata']['key2']='value2' if ssh_keys is not None: # ssh_keys is comma separate list @@ -169,10 +179,10 @@ class Nsi(object): # ssh_keys_format.append({'key-pair-ref': key}) # # ns['ssh-authorized-key'] = ssh_keys_format - nsi['ssh_keys'] = [] - for pubkeyfile in ssh_keys.split(','): - with open(pubkeyfile, 'r') as f: - nsi['ssh_keys'].append(f.read()) + nsi["ssh_keys"] = [] + for pubkeyfile in ssh_keys.split(","): + with open(pubkeyfile, "r") as f: + nsi["ssh_keys"].append(f.read()) if config: nsi_config = yaml.safe_load(config) if "netslice-vld" in nsi_config: @@ -180,8 +190,12 @@ class Nsi(object): if vld.get("vim-network-name"): if isinstance(vld["vim-network-name"], dict): vim_network_name_dict = {} - for vim_account, vim_net in list(vld["vim-network-name"].items()): - vim_network_name_dict[get_vim_account_id(vim_account)] = vim_net + for vim_account, vim_net in list( + vld["vim-network-name"].items() + ): + vim_network_name_dict[ + get_vim_account_id(vim_account) + ] = vim_net vld["vim-network-name"] = vim_network_name_dict nsi["netslice-vld"] = nsi_config["netslice-vld"] if "netslice-subnet" in nsi_config: @@ -191,60 +205,83 @@ class Nsi(object): if vld.get("vim-network-name"): if isinstance(vld["vim-network-name"], dict): vim_network_name_dict = {} - for vim_account, vim_net in list(vld["vim-network-name"].items()): - vim_network_name_dict[get_vim_account_id(vim_account)] = vim_net + for vim_account, vim_net in list( + vld["vim-network-name"].items() + ): + vim_network_name_dict[ + get_vim_account_id(vim_account) + ] = vim_net vld["vim-network-name"] = vim_network_name_dict if "vnf" in nssubnet: for vnf in nssubnet["vnf"]: if vnf.get("vim_account"): - vnf["vimAccountId"] = get_vim_account_id(vnf.pop("vim_account")) + vnf["vimAccountId"] = get_vim_account_id( + vnf.pop("vim_account") + ) nsi["netslice-subnet"] = nsi_config["netslice-subnet"] if "additionalParamsForNsi" in nsi_config: nsi["additionalParamsForNsi"] = nsi_config.pop("additionalParamsForNsi") if not isinstance(nsi["additionalParamsForNsi"], dict): - raise ValueError("Error at --config 'additionalParamsForNsi' must be a dictionary") + raise ValueError( + "Error at --config 'additionalParamsForNsi' must be a dictionary" + ) if "additionalParamsForSubnet" in nsi_config: - nsi["additionalParamsForSubnet"] = nsi_config.pop("additionalParamsForSubnet") + nsi["additionalParamsForSubnet"] = nsi_config.pop( + "additionalParamsForSubnet" + ) if not isinstance(nsi["additionalParamsForSubnet"], list): - raise ValueError("Error at --config 'additionalParamsForSubnet' must be a list") + raise ValueError( + "Error at --config 'additionalParamsForSubnet' must be a list" + ) for additional_param_subnet in nsi["additionalParamsForSubnet"]: if not isinstance(additional_param_subnet, dict): - raise ValueError("Error at --config 'additionalParamsForSubnet' items must be dictionaries") + raise ValueError( + "Error at --config 'additionalParamsForSubnet' items must be dictionaries" + ) if not additional_param_subnet.get("id"): - raise ValueError("Error at --config 'additionalParamsForSubnet' items must contain subnet 'id'") - if not additional_param_subnet.get("additionalParamsForNs") and\ - not additional_param_subnet.get("additionalParamsForVnf"): - raise ValueError("Error at --config 'additionalParamsForSubnet' items must contain " - "'additionalParamsForNs' and/or 'additionalParamsForVnf'") + raise ValueError( + "Error at --config 'additionalParamsForSubnet' items must contain subnet 'id'" + ) + if not additional_param_subnet.get( + "additionalParamsForNs" + ) and not additional_param_subnet.get("additionalParamsForVnf"): + raise ValueError( + "Error at --config 'additionalParamsForSubnet' items must contain " + "'additionalParamsForNs' and/or 'additionalParamsForVnf'" + ) if "timeout_nsi_deploy" in nsi_config: nsi["timeout_nsi_deploy"] = nsi_config.pop("timeout_nsi_deploy") # print(yaml.safe_dump(nsi)) try: - self._apiResource = '/netslice_instances_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._apiResource = "/netslice_instances_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) headers = self._client._headers - headers['Content-Type'] = 'application/yaml' - http_header = ['{}: {}'.format(key,val) - for (key,val) in list(headers.items())] + headers["Content-Type"] = "application/yaml" + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=nsi) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=nsi + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {} '.format( - resp)) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {} ".format(resp) + ) if wait: # Wait for status for NSI instance creation - self._wait(resp.get('nsilcmop_id'), wait) - print(resp['id']) - #else: + self._wait(resp.get("nsilcmop_id"), wait) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -253,36 +290,37 @@ class Nsi(object): # msg = resp # raise ClientException(msg) except ClientException as exc: - message="failed to create nsi: {} nst: {}\nerror:\n{}".format( - nsi_name, - nst_name, - str(exc)) + message = "failed to create nsi: {} nst: {}\nerror:\n{}".format( + nsi_name, nst_name, str(exc) + ) raise ClientException(message) def list_op(self, name, filter=None): - """Returns the list of operations of a NSI - """ + """Returns the list of operations of a NSI""" self._logger.debug("") nsi = self.get(name) try: - self._apiResource = '/nsi_lcm_op_occs' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - filter_string = '' + self._apiResource = "/nsi_lcm_op_occs" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + filter_string = "" if filter: - filter_string = '&{}'.format(filter) - http_code, resp = self._http.get2_cmd('{}?netsliceInstanceId={}{}'.format( - self._apiBase, nsi['_id'], - filter_string) ) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code == 200: + filter_string = "&{}".format(filter) + http_code, resp = self._http.get2_cmd( + "{}?netsliceInstanceId={}{}".format( + self._apiBase, nsi["_id"], filter_string + ) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code == 200: if resp: resp = json.loads(resp) return resp else: - raise ClientException('unexpected response from server') - #else: + raise ClientException("unexpected response from server") + # else: # msg = "" # if resp: # try: @@ -292,30 +330,32 @@ class Nsi(object): # msg = resp # raise ClientException(msg) except ClientException as exc: - message="failed to get operation list of NSI {}:\nerror:\n{}".format( - name, - str(exc)) + message = "failed to get operation list of NSI {}:\nerror:\n{}".format( + name, str(exc) + ) raise ClientException(message) def get_op(self, operationId): - """Returns the status of an operation - """ + """Returns the status of an operation""" self._logger.debug("") self._client.get_token() try: - self._apiResource = '/nsi_lcm_op_occs' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - http_code, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, operationId)) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code == 200: + self._apiResource = "/nsi_lcm_op_occs" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + http_code, resp = self._http.get2_cmd( + "{}/{}".format(self._apiBase, operationId) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code == 200: if resp: resp = json.loads(resp) return resp else: - raise ClientException('unexpected response from server') - #else: + raise ClientException("unexpected response from server") + # else: # msg = "" # if resp: # try: @@ -325,34 +365,37 @@ class Nsi(object): # msg = resp # raise ClientException(msg) except ClientException as exc: - message="failed to get status of operation {}:\nerror:\n{}".format( - operationId, - str(exc)) + message = "failed to get status of operation {}:\nerror:\n{}".format( + operationId, str(exc) + ) raise ClientException(message) def exec_op(self, name, op_name, op_data=None): - """Executes an operation on a NSI - """ + """Executes an operation on a NSI""" self._logger.debug("") nsi = self.get(name) try: - self._apiResource = '/netslice_instances' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - endpoint = '{}/{}/{}'.format(self._apiBase, nsi['_id'], op_name) - #print('OP_NAME: {}'.format(op_name)) - #print('OP_DATA: {}'.format(json.dumps(op_data))) - http_code, resp = self._http.post_cmd(endpoint=endpoint, postfields_dict=op_data) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + self._apiResource = "/netslice_instances" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + endpoint = "{}/{}/{}".format(self._apiBase, nsi["_id"], op_name) + # print('OP_NAME: {}'.format(op_name)) + # print('OP_DATA: {}'.format(json.dumps(op_data))) + http_code, resp = self._http.post_cmd( + endpoint=endpoint, postfields_dict=op_data + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -361,8 +404,5 @@ class Nsi(object): # msg = resp # raise ClientException(msg) except ClientException as exc: - message="failed to exec operation {}:\nerror:\n{}".format( - name, - str(exc)) + message = "failed to exec operation {}:\nerror:\n{}".format(name, str(exc)) raise ClientException(message) - diff --git a/osmclient/sol005/nst.py b/osmclient/sol005/nst.py index 214a79d..19092b2 100644 --- a/osmclient/sol005/nst.py +++ b/osmclient/sol005/nst.py @@ -25,29 +25,31 @@ import json import magic import logging import os.path -#from os import stat -#from os.path import basename -class Nst(object): +# from os import stat +# from os.path import basename + +class Nst(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/nst' - self._apiVersion = '/v1' - self._apiResource = '/netslice_templates' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/nst" + self._apiVersion = "/v1" + self._apiResource = "/netslice_templates" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def list(self, filter=None): self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase, filter_string)) - #print(yaml.safe_dump(resp)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) + # print(yaml.safe_dump(resp)) if resp: return json.loads(resp) return list() @@ -57,11 +59,11 @@ class Nst(object): self._client.get_token() if utils.validate_uuid4(name): for nst in self.list(): - if name == nst['_id']: + if name == nst["_id"]: return nst else: for nst in self.list(): - if 'name' in nst and name == nst['name']: + if "name" in nst and name == nst["name"]: return nst raise NotFound("nst {} not found".format(name)) @@ -71,8 +73,8 @@ class Nst(object): # It is redundant, since the previous one already gets the whole nstinfo # The only difference is that a different primitive is exercised try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, nst['_id'])) - #print(yaml.safe_dump(resp)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, nst["_id"])) + # print(yaml.safe_dump(resp)) if resp: return json.loads(resp) except NotFound: @@ -83,18 +85,20 @@ class Nst(object): self._logger.debug("") nst = self.get(name) headers = self._client._headers - headers['Accept'] = 'application/binary' + headers["Accept"] = "application/binary" try: - http_code, resp = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, nst['_id'], thing)) + http_code, resp = self._http.get2_cmd( + "{}/{}/{}".format(self._apiBase, nst["_id"], thing) + ) except NotFound: raise NotFound("nst '{} 'not found".format(name)) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: - #store in a file + # store in a file return json.loads(resp) - #else: + # else: # msg = "" # if resp: # try: @@ -105,30 +109,31 @@ class Nst(object): def get_descriptor(self, name, filename): self._logger.debug("") - self.get_thing(name, 'nst', filename) + self.get_thing(name, "nst", filename) def get_package(self, name, filename): self._logger.debug("") - self.get_thing(name, 'nst_content', filename) + self.get_thing(name, "nst_content", filename) def get_artifact(self, name, artifact, filename): self._logger.debug("") - self.get_thing(name, 'artifacts/{}'.format(artifact), filename) + self.get_thing(name, "artifacts/{}".format(artifact), filename) def delete(self, name, force=False): self._logger.debug("") nst = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - nst['_id'], querystring)) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, nst["_id"], querystring) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" # if resp: @@ -141,66 +146,82 @@ class Nst(object): def create(self, filename, overwrite=None, update_endpoint=None): self._logger.debug("") if os.path.isdir(filename): - charm_folder = filename.rstrip('/') + charm_folder = filename.rstrip("/") for files in os.listdir(charm_folder): if "nst.yaml" in files: - results = self._client.package_tool.validate(charm_folder, recursive=False) + results = self._client.package_tool.validate( + charm_folder, recursive=False + ) for result in results: if result["valid"] != "OK": - raise ClientException('There was an error validating the file: {} ' - 'with error: {}'.format(result["path"], result["error"])) + raise ClientException( + "There was an error validating the file: {} " + "with error: {}".format(result["path"], result["error"]) + ) result = self._client.package_tool.build(charm_folder) - if 'Created' in result: + if "Created" in result: filename = "{}.tar.gz".format(charm_folder) else: - raise ClientException('Failed in {}tar.gz creation'.format(charm_folder)) + raise ClientException( + "Failed in {}tar.gz creation".format(charm_folder) + ) self.create(filename, overwrite, update_endpoint) else: self._client.get_token() mime_type = magic.from_file(filename, mime=True) if mime_type is None: raise ClientException( - "Unexpected MIME type for file {}: MIME type {}".format( - filename, mime_type) - ) - headers= self._client._headers - if mime_type in ['application/yaml', 'text/plain']: - headers['Content-Type'] = 'application/yaml' - elif mime_type in ['application/gzip', 'application/x-gzip']: - headers['Content-Type'] = 'application/gzip' - #headers['Content-Type'] = 'application/binary' + "Unexpected MIME type for file {}: MIME type {}".format( + filename, mime_type + ) + ) + headers = self._client._headers + if mime_type in ["application/yaml", "text/plain"]: + headers["Content-Type"] = "application/yaml" + elif mime_type in ["application/gzip", "application/x-gzip"]: + headers["Content-Type"] = "application/gzip" + # headers['Content-Type'] = 'application/binary' # Next three lines are to be removed in next version - #headers['Content-Filename'] = basename(filename) - #file_size = stat(filename).st_size - #headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size) + # headers['Content-Filename'] = basename(filename) + # file_size = stat(filename).st_size + # headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size) else: raise ClientException( - "Unexpected MIME type for file {}: MIME type {}".format( - filename, mime_type) - ) + "Unexpected MIME type for file {}: MIME type {}".format( + filename, mime_type + ) + ) headers["Content-File-MD5"] = utils.md5(filename) - http_header = ['{}: {}'.format(key,val) - for (key,val) in list(headers.items())] + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) if update_endpoint: - http_code, resp = self._http.put_cmd(endpoint=update_endpoint, filename=filename) + http_code, resp = self._http.put_cmd( + endpoint=update_endpoint, filename=filename + ) else: - ow_string = '' + ow_string = "" if overwrite: - ow_string = '?{}'.format(overwrite) - self._apiResource = '/netslice_templates_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - endpoint = '{}{}'.format(self._apiBase,ow_string) - http_code, resp = self._http.post_cmd(endpoint=endpoint, filename=filename) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + ow_string = "?{}".format(overwrite) + self._apiResource = "/netslice_templates_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + endpoint = "{}{}".format(self._apiBase, ow_string) + http_code, resp = self._http.post_cmd( + endpoint=endpoint, filename=filename + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format(resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) + print(resp["id"]) # else: # msg = "Error {}".format(http_code) # if resp: @@ -213,6 +234,5 @@ class Nst(object): def update(self, name, filename): self._logger.debug("") nst = self.get(name) - endpoint = '{}/{}/nst_content'.format(self._apiBase, nst['_id']) + endpoint = "{}/{}/nst_content".format(self._apiBase, nst["_id"]) self.create(filename=filename, update_endpoint=endpoint) - diff --git a/osmclient/sol005/osmrepo.py b/osmclient/sol005/osmrepo.py index aa2a5f0..6ccc061 100644 --- a/osmclient/sol005/osmrepo.py +++ b/osmclient/sol005/osmrepo.py @@ -38,16 +38,17 @@ class OSMRepo(Repo): def __init__(self, http=None, client=None): self._http = http self._client = client - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/osmrepos' - self._logger = logging.getLogger('osmclient') - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/osmrepos" + self._logger = logging.getLogger("osmclient") + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def pkg_list(self, pkgtype, filter=None, repo=None): """ - Returns a repo based on name or id + Returns a repo based on name or id """ self._logger.debug("") self._client.get_token() @@ -56,37 +57,46 @@ class OSMRepo(Repo): if repo: repositories = [r for r in repositories if r["name"] == repo] if not repositories: - raise ClientException('Not repository found') + raise ClientException("Not repository found") vnf_repos = [] for repository in repositories: try: - r = requests.get('{}/index.yaml'.format(repository.get('url'))) + r = requests.get("{}/index.yaml".format(repository.get("url"))) if r.status_code == 200: repo_list = yaml.safe_load(r.text) - vnf_packages = repo_list.get('{}_packages'.format(pkgtype)) + vnf_packages = repo_list.get("{}_packages".format(pkgtype)) for repo in vnf_packages: versions = vnf_packages.get(repo) - latest = versions.get('latest') - del versions['latest'] + latest = versions.get("latest") + del versions["latest"] for version in versions: latest_version = False if version == latest: latest_version = True - vnf_repos.append({'vendor': versions[version].get("vendor"), - 'name': versions[version].get("name"), - 'version': version, - 'description': versions[version].get("description"), - 'location': versions[version].get("path"), - 'repository': repository.get('name'), - 'repourl': repository.get('url'), - 'latest': latest_version - }) + vnf_repos.append( + { + "vendor": versions[version].get("vendor"), + "name": versions[version].get("name"), + "version": version, + "description": versions[version].get("description"), + "location": versions[version].get("path"), + "repository": repository.get("name"), + "repourl": repository.get("url"), + "latest": latest_version, + } + ) else: - raise Exception('repository in url {} unreachable'.format(repository.get('url'))) + raise Exception( + "repository in url {} unreachable".format(repository.get("url")) + ) except Exception as e: - logging.error("Error cannot read from repository {} '{}': {}".format(repository['name'], repository['url'], e)) + logging.error( + "Error cannot read from repository {} '{}': {}".format( + repository["name"], repository["url"], e + ) + ) continue vnf_repos_filtered = [] @@ -94,7 +104,7 @@ class OSMRepo(Repo): for vnf_repo in vnf_repos: for k, v in vnf_repo.items(): if v: - kf, vf = filter.split('=') + kf, vf = filter.split("=") if k == kf and vf in v: vnf_repos_filtered.append(vnf_repo) break @@ -103,7 +113,7 @@ class OSMRepo(Repo): def get_pkg(self, pkgtype, name, repo, filter, version): """ - Returns the filename of the PKG downloaded to disk + Returns the filename of the PKG downloaded to disk """ self._logger.debug("") self._client.get_token() @@ -112,14 +122,17 @@ class OSMRepo(Repo): # Get OSM registered repository list pkgs = self.pkg_list(pkgtype, filter, repo) for pkg in pkgs: - if pkg.get('repository') == repo and pkg.get('name') == name: - if 'latest' in version: - if not pkg.get('latest'): + if pkg.get("repository") == repo and pkg.get("name") == name: + if "latest" in version: + if not pkg.get("latest"): continue else: - version = pkg.get('version') - if pkg.get('version') == version: - r = requests.get('{}{}'.format(pkg.get('repourl'), pkg.get('location')), stream=True) + version = pkg.get("version") + if pkg.get("version") == version: + r = requests.get( + "{}{}".format(pkg.get("repourl"), pkg.get("location")), + stream=True, + ) if r.status_code != 200: raise ClientException("Package not found") @@ -127,58 +140,75 @@ class OSMRepo(Repo): f.write(r.raw.read()) f_name = f.name if not f_name: - raise ClientException("{} {} not found at repo {}".format(pkgtype, name, repo)) + raise ClientException( + "{} {} not found at repo {}".format(pkgtype, name, repo) + ) return f_name def pkg_get(self, pkgtype, name, repo, version, filter): pkg_name = self.get_pkg(pkgtype, name, repo, filter, version) if not pkg_name: - raise ClientException('Package not found') + raise ClientException("Package not found") folder, descriptor = self.zip_extraction(pkg_name) with open(descriptor) as pkg: pkg_descriptor = yaml.safe_load(pkg) rmtree(folder, ignore_errors=False) - if ((pkgtype == 'vnf' and (pkg_descriptor.get('vnfd') or pkg_descriptor.get('vnfd:vnfd_catalog'))) or - (pkgtype == 'ns' and (pkg_descriptor.get('nsd') or pkg_descriptor.get('nsd:nsd_catalog')))): - raise ClientException('Wrong Package type') + if ( + pkgtype == "vnf" + and (pkg_descriptor.get("vnfd") or pkg_descriptor.get("vnfd:vnfd_catalog")) + ) or ( + pkgtype == "ns" + and (pkg_descriptor.get("nsd") or pkg_descriptor.get("nsd:nsd_catalog")) + ): + raise ClientException("Wrong Package type") return pkg_descriptor - def repo_index(self, origin=".", destination='.'): + def repo_index(self, origin=".", destination="."): """ - Repo Index main function - :param origin: origin directory for getting all the artifacts - :param destination: destination folder for create and index the valid artifacts + Repo Index main function + :param origin: origin directory for getting all the artifacts + :param destination: destination folder for create and index the valid artifacts """ self._logger.debug("") - if destination == '.': + if destination == ".": if origin == destination: - destination = 'repository' + destination = "repository" destination = abspath(destination) origin = abspath(origin) - if origin[0] != '/': + if origin[0] != "/": origin = join(getcwd(), origin) - if destination[0] != '/': + if destination[0] != "/": destination = join(getcwd(), destination) self.init_directory(destination) artifacts = [f for f in listdir(origin) if isfile(join(origin, f))] directories = [f for f in listdir(origin) if isdir(join(origin, f))] for artifact in artifacts: - self.register_artifact_in_repository(join(origin, artifact), destination, source='file') + self.register_artifact_in_repository( + join(origin, artifact), destination, source="file" + ) for artifact in directories: - self.register_artifact_in_repository(join(origin, artifact), destination, source='directory') + self.register_artifact_in_repository( + join(origin, artifact), destination, source="directory" + ) print("\nFinal Results: ") - print("VNF Packages Indexed: " + str(len(glob.glob(destination + "/vnf/*/*/metadata.yaml")))) - print("NS Packages Indexed: " + str(len(glob.glob(destination + "/ns/*/*/metadata.yaml")))) + print( + "VNF Packages Indexed: " + + str(len(glob.glob(destination + "/vnf/*/*/metadata.yaml"))) + ) + print( + "NS Packages Indexed: " + + str(len(glob.glob(destination + "/ns/*/*/metadata.yaml"))) + ) def md5(self, fname): """ - Checksum generator - :param fname: file path - :return: checksum string + Checksum generator + :param fname: file path + :return: checksum string """ self._logger.debug("") hash_md5 = hashlib.md5() @@ -189,99 +219,115 @@ class OSMRepo(Repo): def fields_building(self, descriptor_dict, file, package_type): """ - From an artifact descriptor, obtain the fields required for indexing - :param descriptor_dict: artifact description - :param file: artifact package - :param package_type: type of artifact (vnf or ns) - :return: fields + From an artifact descriptor, obtain the fields required for indexing + :param descriptor_dict: artifact description + :param file: artifact package + :param package_type: type of artifact (vnf or ns) + :return: fields """ self._logger.debug("") fields = {} - base_path = '/{}/'.format(package_type) + base_path = "/{}/".format(package_type) aux_dict = {} if package_type == "vnf": - if descriptor_dict.get('vnfd-catalog', False): - aux_dict = descriptor_dict.get('vnfd-catalog', {}).get('vnfd', [{}])[0] + if descriptor_dict.get("vnfd-catalog", False): + aux_dict = descriptor_dict.get("vnfd-catalog", {}).get("vnfd", [{}])[0] else: - aux_dict = descriptor_dict.get('vnfd:vnfd-catalog', {}).get('vnfd', [{}])[0] + aux_dict = descriptor_dict.get("vnfd:vnfd-catalog", {}).get( + "vnfd", [{}] + )[0] images = [] - for vdu in aux_dict.get('vdu', ()): - images.append(vdu.get('image')) - fields['images'] = images + for vdu in aux_dict.get("vdu", ()): + images.append(vdu.get("image")) + fields["images"] = images if package_type == "ns": - if descriptor_dict.get('nsd-catalog', False): - aux_dict = descriptor_dict.get('nsd-catalog', {}).get('nsd', [{}])[0] + if descriptor_dict.get("nsd-catalog", False): + aux_dict = descriptor_dict.get("nsd-catalog", {}).get("nsd", [{}])[0] else: - aux_dict = descriptor_dict.get('nsd:nsd-catalog', {}).get('nsd', [{}])[0] + aux_dict = descriptor_dict.get("nsd:nsd-catalog", {}).get("nsd", [{}])[ + 0 + ] vnfs = [] - for vnf in aux_dict.get('constituent-vnfd', ()): - vnfs.append(vnf.get('vnfd-id-ref')) - self._logger.debug('Used VNFS in the NSD: ' + str(vnfs)) - fields['vnfd-id-ref'] = vnfs - - fields['name'] = aux_dict.get('name') - fields['id'] = aux_dict.get('id') - fields['description'] = aux_dict.get('description') - fields['vendor'] = aux_dict.get('vendor') - fields['version'] = aux_dict.get('version', '1.0') - fields['path'] = "{}{}/{}/{}-{}.tar.gz".format(base_path, fields['id'], fields['version'], fields.get('id'), - fields.get('version')) + for vnf in aux_dict.get("constituent-vnfd", ()): + vnfs.append(vnf.get("vnfd-id-ref")) + self._logger.debug("Used VNFS in the NSD: " + str(vnfs)) + fields["vnfd-id-ref"] = vnfs + + fields["name"] = aux_dict.get("name") + fields["id"] = aux_dict.get("id") + fields["description"] = aux_dict.get("description") + fields["vendor"] = aux_dict.get("vendor") + fields["version"] = aux_dict.get("version", "1.0") + fields["path"] = "{}{}/{}/{}-{}.tar.gz".format( + base_path, + fields["id"], + fields["version"], + fields.get("id"), + fields.get("version"), + ) return fields def zip_extraction(self, file_name): """ - Validation of artifact. - :param file: file path - :return: status details, status, fields, package_type + Validation of artifact. + :param file: file path + :return: status details, status, fields, package_type """ self._logger.debug("Decompressing package file") - temp_file = '/tmp/{}'.format(file_name.split('/')[-1]) + temp_file = "/tmp/{}".format(file_name.split("/")[-1]) if file_name != temp_file: copyfile(file_name, temp_file) with tarfile.open(temp_file, "r:gz") as tar: - folder = tar.getnames()[0].split('/')[0] + folder = tar.getnames()[0].split("/")[0] tar.extractall() remove(temp_file) - descriptor_file = glob.glob('{}/*.y*ml'.format(folder))[0] + descriptor_file = glob.glob("{}/*.y*ml".format(folder))[0] return folder, descriptor_file def validate_artifact(self, path, source): """ - Validation of artifact. - :param path: file path - :return: status details, status, fields, package_type + Validation of artifact. + :param path: file path + :return: status details, status, fields, package_type """ self._logger.debug("") - package_type = '' - folder = '' + package_type = "" + folder = "" try: - if source == 'directory': - descriptor_file = glob.glob('{}/*.y*ml'.format(path))[0] + if source == "directory": + descriptor_file = glob.glob("{}/*.y*ml".format(path))[0] else: folder, descriptor_file = self.zip_extraction(path) self._logger.debug("Opening descriptor file: {}".format(descriptor_file)) - with open(descriptor_file, 'r') as f: + with open(descriptor_file, "r") as f: descriptor_data = f.read() validation = validation_im() desc_type, descriptor_dict = validation.yaml_validation(descriptor_data) validation_im.pyangbind_validation(self, desc_type, descriptor_dict) - if 'vnf' in list(descriptor_dict.keys())[0]: - package_type = 'vnf' + if "vnf" in list(descriptor_dict.keys())[0]: + package_type = "vnf" else: # raise ClientException("Not VNF package") - package_type = 'ns' + package_type = "ns" self._logger.debug("Descriptor: {}".format(descriptor_dict)) fields = self.fields_building(descriptor_dict, path, package_type) self._logger.debug("Descriptor sucessfully validated") - return {"detail": "{}D successfully validated".format(package_type.upper()), - "code": "OK"}, True, fields, package_type + return ( + { + "detail": "{}D successfully validated".format(package_type.upper()), + "code": "OK", + }, + True, + fields, + package_type, + ) except Exception as e: # Delete the folder we just created return {"detail": str(e)}, False, {}, package_type @@ -291,9 +337,9 @@ class OSMRepo(Repo): def register_artifact_in_repository(self, path, destination, source): """ - Registration of one artifact in a repository - file: VNF or NS - destination: path for index creation + Registration of one artifact in a repository + file: VNF or NS + destination: path for index creation """ self._logger.debug("") pt = PackageTool() @@ -302,90 +348,157 @@ class OSMRepo(Repo): fields = {} _, valid, fields, package_type = self.validate_artifact(path, source) if not valid: - raise Exception('{} {} Not well configured.'.format(package_type.upper(), str(path))) + raise Exception( + "{} {} Not well configured.".format(package_type.upper(), str(path)) + ) else: - if source == 'directory': + if source == "directory": path = pt.build(path) compresed = True - fields['checksum'] = self.md5(path) + fields["checksum"] = self.md5(path) self.indexation(destination, path, package_type, fields) except Exception as e: - self._logger.exception("Error registering artifact in Repository: {}".format(e)) + self._logger.exception( + "Error registering artifact in Repository: {}".format(e) + ) finally: - if source == 'directory' and compresed: + if source == "directory" and compresed: remove(path) def indexation(self, destination, path, package_type, fields): """ - Process for index packages - :param destination: index repository path - :param path: path of the package - :param package_type: package type (vnf, ns) - :param fields: dict with the required values + Process for index packages + :param destination: index repository path + :param path: path of the package + :param package_type: package type (vnf, ns) + :param fields: dict with the required values """ self._logger.debug("") - data_ind = {'name': fields.get('name'), 'description': fields.get('description'), - 'vendor': fields.get('vendor'), 'path': fields.get('path')} - - final_path = join(destination, package_type, fields.get('id'), fields.get('version')) - if isdir(join(destination, package_type, fields.get('id'))): + data_ind = { + "name": fields.get("name"), + "description": fields.get("description"), + "vendor": fields.get("vendor"), + "path": fields.get("path"), + } + + final_path = join( + destination, package_type, fields.get("id"), fields.get("version") + ) + if isdir(join(destination, package_type, fields.get("id"))): if isdir(final_path): - self._logger.warning('{} {} already exists'.format(package_type.upper(), str(path))) + self._logger.warning( + "{} {} already exists".format(package_type.upper(), str(path)) + ) else: mkdir(final_path) - copyfile(path, - final_path + '/' + fields.get('id') + "-" + fields.get('version') + '.tar.gz') - yaml.safe_dump(fields, open(final_path + '/' + 'metadata.yaml', 'w'), - default_flow_style=False, width=80, indent=4) - index = yaml.safe_load(open(destination + '/index.yaml')) - - index['{}_packages'.format(package_type)][fields.get('id')][fields.get('version')] = data_ind - if versioning.parse(index['{}_packages'.format(package_type)][fields.get('id')][ - 'latest']) < versioning.parse(fields.get('version')): - index['{}_packages'.format(package_type)][fields.get('id')]['latest'] = fields.get( - 'version') - yaml.safe_dump(index, open(destination + '/index.yaml', 'w'), - default_flow_style=False, width=80, indent=4) - self._logger.info('{} {} added in the repository'.format(package_type.upper(), str(path))) + copyfile( + path, + final_path + + "/" + + fields.get("id") + + "-" + + fields.get("version") + + ".tar.gz", + ) + yaml.safe_dump( + fields, + open(final_path + "/" + "metadata.yaml", "w"), + default_flow_style=False, + width=80, + indent=4, + ) + index = yaml.safe_load(open(destination + "/index.yaml")) + + index["{}_packages".format(package_type)][fields.get("id")][ + fields.get("version") + ] = data_ind + if versioning.parse( + index["{}_packages".format(package_type)][fields.get("id")][ + "latest" + ] + ) < versioning.parse(fields.get("version")): + index["{}_packages".format(package_type)][fields.get("id")][ + "latest" + ] = fields.get("version") + yaml.safe_dump( + index, + open(destination + "/index.yaml", "w"), + default_flow_style=False, + width=80, + indent=4, + ) + self._logger.info( + "{} {} added in the repository".format( + package_type.upper(), str(path) + ) + ) else: - mkdir(destination + '/{}/'.format(package_type) + fields.get('id')) + mkdir(destination + "/{}/".format(package_type) + fields.get("id")) mkdir(final_path) - copyfile(path, - final_path + '/' + fields.get('id') + "-" + fields.get('version') + '.tar.gz') - yaml.safe_dump(fields, open(join(final_path, 'metadata.yaml'), 'w'), - default_flow_style=False, width=80, indent=4) - index = yaml.safe_load(open(destination + '/index.yaml')) - - index['{}_packages'.format(package_type)][fields.get('id')] = {fields.get('version'): data_ind} - index['{}_packages'.format(package_type)][fields.get('id')]['latest'] = fields.get('version') - yaml.safe_dump(index, open(join(destination, 'index.yaml'), 'w'), - default_flow_style=False, width=80, indent=4) - self._logger.info('{} {} added in the repository'.format(package_type.upper(), str(path))) + copyfile( + path, + final_path + + "/" + + fields.get("id") + + "-" + + fields.get("version") + + ".tar.gz", + ) + yaml.safe_dump( + fields, + open(join(final_path, "metadata.yaml"), "w"), + default_flow_style=False, + width=80, + indent=4, + ) + index = yaml.safe_load(open(destination + "/index.yaml")) + + index["{}_packages".format(package_type)][fields.get("id")] = { + fields.get("version"): data_ind + } + index["{}_packages".format(package_type)][fields.get("id")][ + "latest" + ] = fields.get("version") + yaml.safe_dump( + index, + open(join(destination, "index.yaml"), "w"), + default_flow_style=False, + width=80, + indent=4, + ) + self._logger.info( + "{} {} added in the repository".format(package_type.upper(), str(path)) + ) def current_datatime(self): """ - Datetime Generator - :return: Datetime as string with the following structure "2020-04-29T08:41:07.681653Z" + Datetime Generator + :return: Datetime as string with the following structure "2020-04-29T08:41:07.681653Z" """ self._logger.debug("") - return time.strftime('%Y-%m-%dT%H:%M:%S.%sZ') + return time.strftime("%Y-%m-%dT%H:%M:%S.%sZ") def init_directory(self, destination): """ - Initialize the index directory. Creation of index.yaml, and the directories for vnf and ns - :param destination: - :return: + Initialize the index directory. Creation of index.yaml, and the directories for vnf and ns + :param destination: + :return: """ self._logger.debug("") if not isdir(destination): mkdir(destination) - if not isfile(join(destination, 'index.yaml')): - mkdir(join(destination, 'vnf')) - mkdir(join(destination, 'ns')) - index_data = {'apiVersion': 'v1', 'generated': self.current_datatime(), 'vnf_packages': {}, - 'ns_packages': {}} - with open(join(destination, 'index.yaml'), 'w') as outfile: - yaml.safe_dump(index_data, outfile, default_flow_style=False, width=80, indent=4) - + if not isfile(join(destination, "index.yaml")): + mkdir(join(destination, "vnf")) + mkdir(join(destination, "ns")) + index_data = { + "apiVersion": "v1", + "generated": self.current_datatime(), + "vnf_packages": {}, + "ns_packages": {}, + } + with open(join(destination, "index.yaml"), "w") as outfile: + yaml.safe_dump( + index_data, outfile, default_flow_style=False, width=80, indent=4 + ) diff --git a/osmclient/sol005/package.py b/osmclient/sol005/package.py index 622fb86..1fa0e24 100644 --- a/osmclient/sol005/package.py +++ b/osmclient/sol005/package.py @@ -18,8 +18,8 @@ OSM package API handling """ -#from os import stat -#from os.path import basename +# from os import stat +# from os.path import basename from osmclient.common.exceptions import ClientException from osmclient.common.exceptions import NotFound from osmclient.common import utils @@ -32,7 +32,7 @@ class Package(object): def __init__(self, http=None, client=None): self._client = client self._http = http - self._logger = logging.getLogger('osmclient') + self._logger = logging.getLogger("osmclient") def get_key_val_from_pkg(self, descriptor_file): self._logger.debug("") @@ -40,9 +40,9 @@ class Package(object): def _wait_for_package(self, pkg_type): self._logger.debug("") - if 'vnfd' in pkg_type['type']: + if "vnfd" in pkg_type["type"]: get_method = self._client.vnfd.get - elif 'nsd' in pkg_type['type']: + elif "nsd" in pkg_type["type"]: get_method = self._client.nsd.get else: raise ClientException("no valid package type found") @@ -56,13 +56,13 @@ class Package(object): return False return True - return utils.wait_for_value(lambda: - check_exists(lambda: - get_method(pkg_type['name']))) + return utils.wait_for_value( + lambda: check_exists(lambda: get_method(pkg_type["name"])) + ) def wait_for_upload(self, filename): """wait(block) for an upload to succeed. - The filename passed is assumed to be a descriptor tarball. + The filename passed is assumed to be a descriptor tarball. """ self._logger.debug("") self._client.get_token() @@ -72,47 +72,50 @@ class Package(object): raise ClientException("Cannot determine package type") if not self._wait_for_package(pkg_type): - raise ClientException("package {} failed to upload" - .format(filename)) + raise ClientException("package {} failed to upload".format(filename)) def upload(self, filename, skip_charm_build=False): self._logger.debug("") if os.path.isdir(filename): - filename = filename.rstrip('/') - filename = self._client.package_tool.build(filename, skip_validation=False, skip_charm_build=skip_charm_build) + filename = filename.rstrip("/") + filename = self._client.package_tool.build( + filename, skip_validation=False, skip_charm_build=skip_charm_build + ) self.upload(filename) else: self._client.get_token() pkg_type = utils.get_key_val_from_pkg(filename) if pkg_type is None: raise ClientException("Cannot determine package type") - if pkg_type['type'] == 'nsd': - endpoint = '/nsd/v1/ns_descriptors_content' + if pkg_type["type"] == "nsd": + endpoint = "/nsd/v1/ns_descriptors_content" else: - endpoint = '/vnfpkgm/v1/vnf_packages_content' - #endpoint = '/nsds' if pkg_type['type'] == 'nsd' else '/vnfds' - #print('Endpoint: {}'.format(endpoint)) + endpoint = "/vnfpkgm/v1/vnf_packages_content" + # endpoint = '/nsds' if pkg_type['type'] == 'nsd' else '/vnfds' + # print('Endpoint: {}'.format(endpoint)) headers = self._client._headers - headers['Content-Type'] = 'application/gzip' - #headers['Content-Type'] = 'application/binary' + headers["Content-Type"] = "application/gzip" + # headers['Content-Type'] = 'application/binary' # Next three lines are to be removed in next version - #headers['Content-Filename'] = basename(filename) - #file_size = stat(filename).st_size - #headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size) + # headers['Content-Filename'] = basename(filename) + # file_size = stat(filename).st_size + # headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size) headers["Content-File-MD5"] = utils.md5(filename) - http_header = ['{}: {}'.format(key,val) - for (key,val) in list(headers.items())] + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) http_code, resp = self._http.post_cmd(endpoint=endpoint, filename=filename) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) + print(resp["id"]) # else: # msg = "" # if resp: diff --git a/osmclient/sol005/pdud.py b/osmclient/sol005/pdud.py index aa4bf69..df5bad1 100644 --- a/osmclient/sol005/pdud.py +++ b/osmclient/sol005/pdud.py @@ -26,24 +26,24 @@ import logging class Pdu(object): - def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/pdu' - self._apiVersion = '/v1' - self._apiResource = '/pdu_descriptors' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/pdu" + self._apiVersion = "/v1" + self._apiResource = "/pdu_descriptors" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def list(self, filter=None): self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: return json.loads(resp) return list() @@ -53,11 +53,11 @@ class Pdu(object): self._client.get_token() if utils.validate_uuid4(name): for pdud in self.list(): - if name == pdud['_id']: + if name == pdud["_id"]: return pdud else: for pdud in self.list(): - if 'name' in pdud and name == pdud['name']: + if "name" in pdud and name == pdud["name"]: return pdud raise NotFound("pdud {} not found".format(name)) @@ -67,10 +67,10 @@ class Pdu(object): # It is redundant, since the previous one already gets the whole pdudInfo # The only difference is that a different primitive is exercised try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, pdud['_id'])) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, pdud["_id"])) except NotFound: raise NotFound("pdu '{}' not found".format(name)) - #print(yaml.safe_dump(resp)) + # print(yaml.safe_dump(resp)) if resp: return json.loads(resp) raise NotFound("pdu '{}' not found".format(name)) @@ -78,17 +78,18 @@ class Pdu(object): def delete(self, name, force=False): self._logger.debug("") pdud = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - pdud['_id'], querystring)) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, pdud["_id"], querystring) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" # if resp: @@ -101,27 +102,31 @@ class Pdu(object): def create(self, pdu, update_endpoint=None): self._logger.debug("") self._client.get_token() - headers= self._client._headers - headers['Content-Type'] = 'application/yaml' - http_header = ['{}: {}'.format(key,val) - for (key,val) in list(headers.items())] + headers = self._client._headers + headers["Content-Type"] = "application/yaml" + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) if update_endpoint: - http_code, resp = self._http.put_cmd(endpoint=update_endpoint, postfields_dict=pdu) + http_code, resp = self._http.put_cmd( + endpoint=update_endpoint, postfields_dict=pdu + ) else: endpoint = self._apiBase - #endpoint = '{}{}'.format(self._apiBase,ow_string) - http_code, resp = self._http.post_cmd(endpoint=endpoint, postfields_dict=pdu) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # endpoint = '{}{}'.format(self._apiBase,ow_string) + http_code, resp = self._http.post_cmd( + endpoint=endpoint, postfields_dict=pdu + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server: {}'.format( - resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException("unexpected response from server: {}".format(resp)) + print(resp["id"]) + # else: # msg = "Error {}".format(http_code) # if resp: # try: @@ -133,6 +138,5 @@ class Pdu(object): def update(self, name, filename): self._logger.debug("") pdud = self.get(name) - endpoint = '{}/{}'.format(self._apiBase, pdud['_id']) + endpoint = "{}/{}".format(self._apiBase, pdud["_id"]) self.create(filename=filename, update_endpoint=endpoint) - diff --git a/osmclient/sol005/project.py b/osmclient/sol005/project.py index ed781fa..3658772 100644 --- a/osmclient/sol005/project.py +++ b/osmclient/sol005/project.py @@ -30,31 +30,30 @@ class Project(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/projects' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/projects" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def create(self, name, project): - """Creates a new OSM project - """ + """Creates a new OSM project""" self._logger.debug("") self._client.get_token() - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=project, - skip_query_admin=True) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=project, skip_query_admin=True + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -64,26 +63,28 @@ class Project(object): # raise ClientException("failed to create project {} - {}".format(name, msg)) def update(self, project, project_changes): - """Updates an OSM project identified by name - """ + """Updates an OSM project identified by name""" self._logger.debug("") self._client.get_token() proj = self.get(project) - http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase, proj['_id']), - postfields_dict=project_changes, - skip_query_admin=True) + http_code, resp = self._http.patch_cmd( + endpoint="{}/{}".format(self._apiBase, proj["_id"]), + postfields_dict=project_changes, + skip_query_admin=True, + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) if http_code in (200, 201, 202): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) + print(resp["id"]) elif http_code == 204: print("Updated") - #else: + # else: # msg = "" # if resp: # try: @@ -93,25 +94,25 @@ class Project(object): # raise ClientException("failed to update project {} - {}".format(project, msg)) def delete(self, name, force=False): - """Deletes an OSM project identified by name - """ + """Deletes an OSM project identified by name""" self._logger.debug("") self._client.get_token() project = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - project['_id'], querystring), - skip_query_admin=True) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, project["_id"], querystring), + skip_query_admin=True, + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') - elif resp and 'result' in resp: - print('Deleted') + print("Deleted") + elif resp and "result" in resp: + print("Deleted") else: msg = resp or "" # if resp: @@ -122,32 +123,30 @@ class Project(object): raise ClientException("failed to delete project {} - {}".format(name, msg)) def list(self, filter=None): - """Returns the list of OSM projects - """ + """Returns the list of OSM projects""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string), - skip_query_admin=True) - #print('RESP: {}'.format(resp)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd( + "{}{}".format(self._apiBase, filter_string), skip_query_admin=True + ) + # print('RESP: {}'.format(resp)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns a specific OSM project based on name or id - """ + """Returns a specific OSM project based on name or id""" self._logger.debug("") self._client.get_token() if utils.validate_uuid4(name): for proj in self.list(): - if name == proj['_id']: + if name == proj["_id"]: return proj else: for proj in self.list(): - if name == proj['name']: + if name == proj["name"]: return proj raise NotFound("Project {} not found".format(name)) - diff --git a/osmclient/sol005/repo.py b/osmclient/sol005/repo.py index cc82402..6e6e927 100644 --- a/osmclient/sol005/repo.py +++ b/osmclient/sol005/repo.py @@ -21,30 +21,32 @@ from osmclient.common.exceptions import ClientException from osmclient.common.exceptions import NotFound import json + class Repo(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/k8srepos' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/k8srepos" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def create(self, name, repo): self._client.get_token() - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=repo) - #print 'HTTP CODE: {}'.format(http_code) - #print 'RESP: {}'.format(resp) - #if http_code in (200, 201, 202, 204): + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=repo + ) + # print 'HTTP CODE: {}'.format(http_code) + # print 'RESP: {}'.format(resp) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -56,13 +58,15 @@ class Repo(object): def update(self, name, repo): self._client.get_token() repo_dict = self.get(name) - http_code, resp = self._http.put_cmd(endpoint='{}/{}'.format(self._apiBase,repo_dict['_id']), - postfields_dict=repo) + http_code, resp = self._http.put_cmd( + endpoint="{}/{}".format(self._apiBase, repo_dict["_id"]), + postfields_dict=repo, + ) # print 'HTTP CODE: {}'.format(http_code) # print 'RESP: {}'.format(resp) - #if http_code in (200, 201, 202, 204): + # if http_code in (200, 201, 202, 204): # pass - #else: + # else: # msg = "" # if resp: # try: @@ -72,12 +76,11 @@ class Repo(object): # raise ClientException("failed to update repo {} - {}".format(name, msg)) def get_id(self, name): - """Returns a repo id from a repo name - """ + """Returns a repo id from a repo name""" self._client.get_token() for repo in self.list(): - if name == repo['name']: - return repo['_id'] + if name == repo["name"]: + return repo["_id"] raise NotFound("Repo {} not found".format(name)) def delete(self, name, force=False): @@ -85,17 +88,18 @@ class Repo(object): repo_id = name if not utils.validate_uuid4(name): repo_id = self.get_id(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - repo_id, querystring)) - #print 'HTTP CODE: {}'.format(http_code) - #print 'RESP: {}'.format(resp) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, repo_id, querystring) + ) + # print 'HTTP CODE: {}'.format(http_code) + # print 'RESP: {}'.format(resp) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" # if resp: @@ -106,31 +110,28 @@ class Repo(object): raise ClientException("failed to delete repo {} - {}".format(name, msg)) def list(self, filter=None): - """Returns a list of repos - """ + """Returns a list of repos""" self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns a repo based on name or id - """ + """Returns a repo based on name or id""" self._client.get_token() repo_id = name if not utils.validate_uuid4(name): repo_id = self.get_id(name) try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase,repo_id)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, repo_id)) if resp: resp = json.loads(resp) - if not resp or '_id' not in resp: - raise ClientException('failed to get repo info: {}'.format(resp)) + if not resp or "_id" not in resp: + raise ClientException("failed to get repo info: {}".format(resp)) return resp except NotFound: raise NotFound("Repo {} not found".format(name)) - diff --git a/osmclient/sol005/role.py b/osmclient/sol005/role.py index 2544a7b..46158d7 100644 --- a/osmclient/sol005/role.py +++ b/osmclient/sol005/role.py @@ -32,12 +32,13 @@ class Role(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/roles' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/roles" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def create(self, name, permissions): """ @@ -56,27 +57,32 @@ class Role(object): role_permissions = yaml.safe_load(permissions) if not isinstance(role_permissions, dict): - raise ClientException('Role permissions should be provided in a key-value fashion') + raise ClientException( + "Role permissions should be provided in a key-value fashion" + ) for key, value in role_permissions.items(): if not isinstance(value, bool): - raise ClientException("Value of '{}' in a role permissions should be boolean".format(key)) + raise ClientException( + "Value of '{}' in a role permissions should be boolean".format( + key + ) + ) role["permissions"] = role_permissions - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=role, - skip_query_admin=True) + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=role, skip_query_admin=True + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('Unexpected response from server - {}'.format( - resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException("Unexpected response from server - {}".format(resp)) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -102,9 +108,9 @@ class Role(object): self._logger.debug("") self._client.get_token() if new_name is None and permissions is None and add is None and remove is None: - raise ClientException('At least one option should be provided') + raise ClientException("At least one option should be provided") elif permissions and (add or remove): - raise ClientException('permissions and add/remove are mutually exclusive') + raise ClientException("permissions and add/remove are mutually exclusive") role_obj = self.get(name) new_role_obj = {"permissions": {}} @@ -115,11 +121,15 @@ class Role(object): role_definition = yaml.safe_load(permissions) if not isinstance(role_definition, dict): - raise ClientException('Role permissions should be provided in a key-value fashion') + raise ClientException( + "Role permissions should be provided in a key-value fashion" + ) for key, value in role_definition.items(): if not isinstance(value, bool) and value is not None: - raise ClientException('Value in a role permissions should be boolean or None to remove') + raise ClientException( + "Value in a role permissions should be boolean or None to remove" + ) new_role_obj["permissions"] = role_definition else: @@ -127,42 +137,51 @@ class Role(object): keys_from_remove = yaml.safe_load(remove) if not isinstance(keys_from_remove, list): - raise ClientException('Keys should be provided in a list fashion') + raise ClientException("Keys should be provided in a list fashion") for key in keys_from_remove: if not isinstance(key, str): - raise ClientException('Individual keys should be strings') + raise ClientException("Individual keys should be strings") new_role_obj["permissions"][key] = None if add: add_roles = yaml.safe_load(add) if not isinstance(add_roles, dict): - raise ClientException('Add should be provided in a key-value fashion') + raise ClientException( + "Add should be provided in a key-value fashion" + ) for key, value in add_roles.items(): if not isinstance(value, bool): - raise ClientException("Value '{}' in a role permissions should be boolean".format(key)) + raise ClientException( + "Value '{}' in a role permissions should be boolean".format( + key + ) + ) new_role_obj["permissions"][key] = value if not new_role_obj["permissions"]: del new_role_obj["permissions"] - http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase, role_obj['_id']), - postfields_dict=new_role_obj, - skip_query_admin=True) + http_code, resp = self._http.patch_cmd( + endpoint="{}/{}".format(self._apiBase, role_obj["_id"]), + postfields_dict=new_role_obj, + skip_query_admin=True, + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) if http_code in (200, 201, 202): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('Unexpected response from server - {}'.format( - resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "Unexpected response from server - {}".format(resp) + ) + print(resp["id"]) elif http_code == 204: print("Updated") - #else: + # else: # msg = "" # if resp: # try: @@ -182,20 +201,21 @@ class Role(object): self._logger.debug("") self._client.get_token() role = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - role['_id'], querystring), - skip_query_admin=True) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, role["_id"], querystring), + skip_query_admin=True, + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') - elif resp and 'result' in resp: - print('Deleted') + print("Deleted") + elif resp and "result" in resp: + print("Deleted") else: msg = resp or "" # if resp: @@ -214,10 +234,12 @@ class Role(object): """ self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase, filter_string),skip_query_admin=True) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd( + "{}{}".format(self._apiBase, filter_string), skip_query_admin=True + ) # print('RESP: {}'.format(resp)) if resp: return json.loads(resp) @@ -235,11 +257,10 @@ class Role(object): self._client.get_token() if utils.validate_uuid4(name): for role in self.list(): - if name == role['_id']: + if name == role["_id"]: return role else: for role in self.list(): - if name == role['name']: + if name == role["name"]: return role raise NotFound("Role {} not found".format(name)) - diff --git a/osmclient/sol005/sdncontroller.py b/osmclient/sol005/sdncontroller.py index 5b85ef4..3d4b7f7 100644 --- a/osmclient/sol005/sdncontroller.py +++ b/osmclient/sol005/sdncontroller.py @@ -31,62 +31,63 @@ class SdnController(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/sdns' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/sdns" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) # SDNC '--wait' option def _wait(self, id, wait_time, deleteFlag=False): self._logger.debug("") self._client.get_token() # Endpoint to get operation status - apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/sdns') + apiUrlStatus = "{}{}{}".format(self._apiName, self._apiVersion, "/sdns") # Wait for status for SDN instance creation/update/deletion if isinstance(wait_time, bool): wait_time = WaitForStatus.TIMEOUT_SDNC_OPERATION WaitForStatus.wait_for_status( - 'SDNC', + "SDNC", str(id), wait_time, apiUrlStatus, self._http.get2_cmd, - deleteFlag=deleteFlag) + deleteFlag=deleteFlag, + ) def _get_id_for_wait(self, name): - """Returns id of name, or the id itself if given as argument - """ + """Returns id of name, or the id itself if given as argument""" self._logger.debug("") for sdnc in self.list(): - if name == sdnc['_id']: - return sdnc['_id'] + if name == sdnc["_id"]: + return sdnc["_id"] for sdnc in self.list(): - if name == sdnc['name']: - return sdnc['_id'] - return '' + if name == sdnc["name"]: + return sdnc["_id"] + return "" def create(self, name, sdn_controller, wait=False): self._logger.debug("") - if 'config' in sdn_controller and isinstance(sdn_controller["config"], str): + if "config" in sdn_controller and isinstance(sdn_controller["config"], str): sdn_controller["config"] = yaml.safe_load(sdn_controller["config"]) self._client.get_token() - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=sdn_controller) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=sdn_controller + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) if wait: # Wait for status for SDNC instance creation - self._wait(resp.get('id'), wait) - print(resp['id']) - #else: + self._wait(resp.get("id"), wait) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -97,16 +98,18 @@ class SdnController(object): def update(self, name, sdn_controller, wait=False): self._logger.debug("") - if 'config' in sdn_controller and isinstance(sdn_controller["config"], str): + if "config" in sdn_controller and isinstance(sdn_controller["config"], str): sdn_controller["config"] = yaml.safe_load(sdn_controller["config"]) self._client.get_token() sdnc = self.get(name) sdnc_id_for_wait = self._get_id_for_wait(name) - http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase,sdnc['_id']), - postfields_dict=sdn_controller) + http_code, resp = self._http.patch_cmd( + endpoint="{}/{}".format(self._apiBase, sdnc["_id"]), + postfields_dict=sdn_controller, + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # if http_code in (200, 201, 202, 204): if wait: # In this case, 'resp' always returns None, so 'resp['id']' cannot be used. # Use the previously obtained id instead. @@ -115,7 +118,7 @@ class SdnController(object): self._wait(wait_id, wait) # else: # pass - #else: + # else: # msg = "" # if resp: # try: @@ -129,11 +132,12 @@ class SdnController(object): self._client.get_token() sdn_controller = self.get(name) sdnc_id_for_wait = self._get_id_for_wait(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - sdn_controller['_id'], querystring)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, sdn_controller["_id"], querystring) + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) if http_code == 202: @@ -141,11 +145,11 @@ class SdnController(object): # Wait for status for SDNC instance deletion self._wait(sdnc_id_for_wait, wait, deleteFlag=True) else: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') - elif resp and 'result' in resp: - print('Deleted') + print("Deleted") + elif resp and "result" in resp: + print("Deleted") else: msg = resp or "" # if resp: @@ -153,34 +157,33 @@ class SdnController(object): # msg = json.loads(resp) # except ValueError: # msg = resp - raise ClientException("failed to delete SDN controller {} - {}".format(name, msg)) + raise ClientException( + "failed to delete SDN controller {} - {}".format(name, msg) + ) def list(self, filter=None): - """Returns a list of SDN controllers - """ + """Returns a list of SDN controllers""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) - #print('RESP: {}'.format(resp)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) + # print('RESP: {}'.format(resp)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns an SDN controller based on name or id - """ + """Returns an SDN controller based on name or id""" self._logger.debug("") self._client.get_token() if utils.validate_uuid4(name): for sdnc in self.list(): - if name == sdnc['_id']: + if name == sdnc["_id"]: return sdnc else: for sdnc in self.list(): - if name == sdnc['name']: + if name == sdnc["name"]: return sdnc raise NotFound("SDN controller {} not found".format(name)) - diff --git a/osmclient/sol005/user.py b/osmclient/sol005/user.py index d28514e..d6c1e16 100644 --- a/osmclient/sol005/user.py +++ b/osmclient/sol005/user.py @@ -29,19 +29,21 @@ class User(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/users' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/users" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def create(self, name, user): - """Creates a new OSM user - """ + """Creates a new OSM user""" self._logger.debug("") self._client.get_token() - if not user["projects"] or (len(user["projects"]) == 1 and not user["projects"][0]): + if not user["projects"] or ( + len(user["projects"]) == 1 and not user["projects"][0] + ): del user["projects"] elif len(user["projects"]) == 1: user["projects"] = user["projects"][0].split(",") @@ -62,19 +64,18 @@ class User(object): else: del user["project_role_mappings"] - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=user, - skip_query_admin=True) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=user, skip_query_admin=True + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) - #else: + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -84,8 +85,7 @@ class User(object): # raise ClientException("failed to create user {} - {}".format(name, msg)) def update(self, name, user): - """Updates an existing OSM user identified by name - """ + """Updates an existing OSM user identified by name""" self._logger.debug("") self._client.get_token() # print(user) @@ -113,14 +113,18 @@ class User(object): for role in roles: mapping = {"project": project, "role": role} update_user["add_project_role_mappings"].append(mapping) - + if user["remove-project"]: for remove_project in user["remove-project"]: - update_user["remove_project_role_mappings"].append({"project": remove_project}) + update_user["remove_project_role_mappings"].append( + {"project": remove_project} + ) if user["add-project-role"]: for add_project_role in user["add-project-role"]: - add_project_role_clean = [m.strip() for m in add_project_role.split(",")] + add_project_role_clean = [ + m.strip() for m in add_project_role.split(",") + ] project, roles = add_project_role_clean[0], add_project_role_clean[1:] for role in roles: @@ -129,8 +133,13 @@ class User(object): if user["remove-project-role"]: for remove_project_role in user["remove-project-role"]: - remove_project_role_clean = [m.strip() for m in remove_project_role.split(",")] - project, roles = remove_project_role_clean[0], remove_project_role_clean[1:] + remove_project_role_clean = [ + m.strip() for m in remove_project_role.split(",") + ] + project, roles = ( + remove_project_role_clean[0], + remove_project_role_clean[1:], + ) for role in roles: mapping = {"project": project, "role": role} @@ -143,20 +152,24 @@ class User(object): if not update_user: raise ClientException("At least something should be changed.") - http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase, myuser['_id']), - postfields_dict=update_user, skip_query_admin=True) + http_code, resp = self._http.patch_cmd( + endpoint="{}/{}".format(self._apiBase, myuser["_id"]), + postfields_dict=update_user, + skip_query_admin=True, + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) if http_code in (200, 201, 202): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server - {}".format(resp) + ) + print(resp["id"]) elif http_code == 204: - print('Updated') - #else: + print("Updated") + # else: # msg = "" # if resp: # try: @@ -166,24 +179,25 @@ class User(object): # raise ClientException("failed to update user {} - {}".format(name, msg)) def delete(self, name, force=False): - """Deletes an existing OSM user identified by name - """ + """Deletes an existing OSM user identified by name""" self._logger.debug("") self._client.get_token() user = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - user['_id'], querystring), skip_query_admin=True) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, user["_id"], querystring), + skip_query_admin=True, + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') - elif resp and 'result' in resp: - print('Deleted') + print("Deleted") + elif resp and "result" in resp: + print("Deleted") else: msg = resp or "" # if resp: @@ -194,32 +208,31 @@ class User(object): raise ClientException("failed to delete user {} - {}".format(name, msg)) def list(self, filter=None): - """Returns the list of OSM users - """ + """Returns the list of OSM users""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string), skip_query_admin=True) - #print('RESP: {}'.format(resp)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd( + "{}{}".format(self._apiBase, filter_string), skip_query_admin=True + ) + # print('RESP: {}'.format(resp)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns an OSM user based on name or id - """ + """Returns an OSM user based on name or id""" self._logger.debug("") self._client.get_token() # keystone with external LDAP contains large ids, not uuid format # utils.validate_uuid4(name) cannot be used user_list = self.list() for user in user_list: - if name == user['_id']: + if name == user["_id"]: return user for user in user_list: - if name == user['username']: + if name == user["username"]: return user raise NotFound("User {} not found".format(name)) - diff --git a/osmclient/sol005/vim.py b/osmclient/sol005/vim.py index fa17dfc..f2a11e6 100644 --- a/osmclient/sol005/vim.py +++ b/osmclient/sol005/vim.py @@ -31,82 +31,85 @@ class Vim(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/vim_accounts' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/vim_accounts" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) # VIM '--wait' option def _wait(self, id, wait_time, deleteFlag=False): self._logger.debug("") self._client.get_token() # Endpoint to get operation status - apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/vim_accounts') + apiUrlStatus = "{}{}{}".format(self._apiName, self._apiVersion, "/vim_accounts") # Wait for status for VIM instance creation/deletion if isinstance(wait_time, bool): wait_time = WaitForStatus.TIMEOUT_VIM_OPERATION WaitForStatus.wait_for_status( - 'VIM', + "VIM", str(id), wait_time, apiUrlStatus, self._http.get2_cmd, - deleteFlag=deleteFlag) + deleteFlag=deleteFlag, + ) def _get_id_for_wait(self, name): - """ Returns id of name, or the id itself if given as argument - """ + """Returns id of name, or the id itself if given as argument""" self._logger.debug("") self._client.get_token() for vim in self.list(): - if name == vim['uuid']: - return vim['uuid'] + if name == vim["uuid"]: + return vim["uuid"] for vim in self.list(): - if name == vim['name']: - return vim['uuid'] - return '' + if name == vim["name"]: + return vim["uuid"] + return "" - def create(self, name, vim_access, sdn_controller=None, sdn_port_mapping=None, wait=False): + def create( + self, name, vim_access, sdn_controller=None, sdn_port_mapping=None, wait=False + ): self._logger.debug("") self._client.get_token() - if 'vim-type' not in vim_access: + if "vim-type" not in vim_access: #'openstack' not in vim_access['vim-type']): raise Exception("vim type not provided") vim_account = {} - vim_account['name'] = name + vim_account["name"] = name vim_account = self.update_vim_account_dict(vim_account, vim_access) vim_config = {} - if 'config' in vim_access and vim_access['config'] is not None: - vim_config = yaml.safe_load(vim_access['config']) + if "config" in vim_access and vim_access["config"] is not None: + vim_config = yaml.safe_load(vim_access["config"]) if sdn_controller: sdnc = self._client.sdnc.get(sdn_controller) - vim_config['sdn-controller'] = sdnc['_id'] + vim_config["sdn-controller"] = sdnc["_id"] if sdn_port_mapping: - with open(sdn_port_mapping, 'r') as f: - vim_config['sdn-port-mapping'] = yaml.safe_load(f.read()) + with open(sdn_port_mapping, "r") as f: + vim_config["sdn-port-mapping"] = yaml.safe_load(f.read()) if vim_config: - vim_account['config'] = vim_config - #vim_account['config'] = json.dumps(vim_config) - - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=vim_account) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + vim_account["config"] = vim_config + # vim_account['config'] = json.dumps(vim_config) + + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=vim_account + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) if wait: # Wait for status for VIM instance creation - self._wait(resp.get('id'), wait) - print(resp['id']) - #else: + self._wait(resp.get("id"), wait) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -115,36 +118,42 @@ class Vim(object): # msg = resp # raise ClientException("failed to create vim {} - {}".format(name, msg)) - def update(self, vim_name, vim_account, sdn_controller, sdn_port_mapping, wait=False): + def update( + self, vim_name, vim_account, sdn_controller, sdn_port_mapping, wait=False + ): self._logger.debug("") self._client.get_token() vim = self.get(vim_name) vim_id_for_wait = self._get_id_for_wait(vim_name) vim_config = {} - if 'config' in vim_account: - if vim_account.get('config')=="" and (sdn_controller or sdn_port_mapping): - raise ClientException("clearing config is incompatible with updating SDN info") - if vim_account.get('config')=="": + if "config" in vim_account: + if vim_account.get("config") == "" and (sdn_controller or sdn_port_mapping): + raise ClientException( + "clearing config is incompatible with updating SDN info" + ) + if vim_account.get("config") == "": vim_config = None else: - vim_config = yaml.safe_load(vim_account['config']) + vim_config = yaml.safe_load(vim_account["config"]) if sdn_controller == "": - vim_config['sdn-controller'] = None - vim_config['sdn-port-mapping'] = None + vim_config["sdn-controller"] = None + vim_config["sdn-port-mapping"] = None else: if sdn_controller: sdnc = self._client.sdnc.get(sdn_controller) - vim_config['sdn-controller'] = sdnc['_id'] + vim_config["sdn-controller"] = sdnc["_id"] if sdn_port_mapping: - with open(sdn_port_mapping, 'r') as f: - vim_config['sdn-port-mapping'] = yaml.safe_load(f.read()) - vim_account['config'] = vim_config - #vim_account['config'] = json.dumps(vim_config) - http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase,vim['_id']), - postfields_dict=vim_account) + with open(sdn_port_mapping, "r") as f: + vim_config["sdn-port-mapping"] = yaml.safe_load(f.read()) + vim_account["config"] = vim_config + # vim_account['config'] = json.dumps(vim_config) + http_code, resp = self._http.patch_cmd( + endpoint="{}/{}".format(self._apiBase, vim["_id"]), + postfields_dict=vim_account, + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + # if http_code in (200, 201, 202, 204): if wait: # In this case, 'resp' always returns None, so 'resp['id']' cannot be used. # Use the previously obtained id instead. @@ -153,7 +162,7 @@ class Vim(object): self._wait(wait_id, wait) # else: # pass - #else: + # else: # msg = "" # if resp: # try: @@ -164,21 +173,20 @@ class Vim(object): def update_vim_account_dict(self, vim_account, vim_access): self._logger.debug("") - vim_account['vim_type'] = vim_access['vim-type'] - vim_account['description'] = vim_access['description'] - vim_account['vim_url'] = vim_access['vim-url'] - vim_account['vim_user'] = vim_access['vim-username'] - vim_account['vim_password'] = vim_access['vim-password'] - vim_account['vim_tenant_name'] = vim_access['vim-tenant-name'] + vim_account["vim_type"] = vim_access["vim-type"] + vim_account["description"] = vim_access["description"] + vim_account["vim_url"] = vim_access["vim-url"] + vim_account["vim_user"] = vim_access["vim-username"] + vim_account["vim_password"] = vim_access["vim-password"] + vim_account["vim_tenant_name"] = vim_access["vim-tenant-name"] return vim_account def get_id(self, name): - """Returns a VIM id from a VIM name - """ + """Returns a VIM id from a VIM name""" self._logger.debug("") for vim in self.list(): - if name == vim['name']: - return vim['uuid'] + if name == vim["name"]: + return vim["uuid"] raise NotFound("vim {} not found".format(name)) def delete(self, vim_name, force=False, wait=False): @@ -187,13 +195,14 @@ class Vim(object): vim_id = vim_name if not utils.validate_uuid4(vim_name): vim_id = self.get_id(vim_name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - vim_id, querystring)) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, vim_id, querystring) + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) if http_code == 202: if wait: # When deleting an account, 'resp' may be None. @@ -201,13 +210,13 @@ class Vim(object): wait_id = vim_id if resp: resp = json.loads(resp) - wait_id = resp.get('id') + wait_id = resp.get("id") # Wait for status for VIM account deletion self._wait(wait_id, wait, deleteFlag=True) else: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" # if resp: @@ -218,36 +227,33 @@ class Vim(object): raise ClientException("failed to delete vim {} - {}".format(vim_name, msg)) def list(self, filter=None): - """Returns a list of VIM accounts - """ + """Returns a list of VIM accounts""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if not resp: return list() vim_accounts = json.loads(resp) for datacenter in vim_accounts: - datacenter["uuid"] = datacenter.get('_id') # backward compatibility? + datacenter["uuid"] = datacenter.get("_id") # backward compatibility? return vim_accounts def get(self, name): - """Returns a VIM account based on name or id - """ + """Returns a VIM account based on name or id""" self._logger.debug("") self._client.get_token() vim_id = name if not utils.validate_uuid4(name): vim_id = self.get_id(name) try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase,vim_id)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, vim_id)) if resp: resp = json.loads(resp) - if not resp or '_id' not in resp: - raise ClientException('failed to get vim info: {}'.format(resp)) + if not resp or "_id" not in resp: + raise ClientException("failed to get vim info: {}".format(resp)) return resp except NotFound: raise NotFound("vim '{}' not found".format(name)) - diff --git a/osmclient/sol005/vnf.py b/osmclient/sol005/vnf.py index edae358..f7c20d9 100644 --- a/osmclient/sol005/vnf.py +++ b/osmclient/sol005/vnf.py @@ -23,50 +23,49 @@ from osmclient.common.exceptions import NotFound import logging import json -class Vnf(object): +class Vnf(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/nslcm' - self._apiVersion = '/v1' - self._apiResource = '/vnfrs' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/nslcm" + self._apiVersion = "/v1" + self._apiResource = "/vnfrs" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def list(self, ns=None, filter=None): - """Returns a list of VNF instances - """ + """Returns a list of VNF instances""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) + filter_string = "?{}".format(filter) if ns: ns_instance = self._client.ns.get(ns) if filter_string: - filter_string += ',nsr-id-ref={}'.format(ns_instance['_id']) + filter_string += ",nsr-id-ref={}".format(ns_instance["_id"]) else: - filter_string = '?nsr-id-ref={}'.format(ns_instance['_id']) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) - #print('RESP: {}'.format(resp)) + filter_string = "?nsr-id-ref={}".format(ns_instance["_id"]) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) + # print('RESP: {}'.format(resp)) if resp: return json.loads(resp) return list() def get(self, name): - """Returns a VNF instance based on name or id - """ + """Returns a VNF instance based on name or id""" self._logger.debug("") self._client.get_token() if utils.validate_uuid4(name): for vnf in self.list(): - if name == vnf['_id']: + if name == vnf["_id"]: return vnf else: for vnf in self.list(): - if name == vnf.get('name'): + if name == vnf.get("name"): return vnf raise NotFound("vnf {} not found".format(name)) @@ -76,12 +75,12 @@ class Vnf(object): vnf_id = name if not utils.validate_uuid4(name): for vnf in self.list(): - if name == vnf['name']: - vnf_id = vnf['_id'] + if name == vnf["name"]: + vnf_id = vnf["_id"] break try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, vnf_id)) - #print('RESP: {}'.format(resp)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, vnf_id)) + # print('RESP: {}'.format(resp)) if resp: return json.loads(resp) except NotFound: diff --git a/osmclient/sol005/vnfd.py b/osmclient/sol005/vnfd.py index e32ac83..4542d56 100644 --- a/osmclient/sol005/vnfd.py +++ b/osmclient/sol005/vnfd.py @@ -33,24 +33,24 @@ from osm_im.validation import Validation as validation_im class Vnfd(object): - def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/vnfpkgm' - self._apiVersion = '/v1' - self._apiResource = '/vnf_packages' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/vnfpkgm" + self._apiVersion = "/v1" + self._apiResource = "/vnf_packages" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) def list(self, filter=None): self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase, filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if resp: return json.loads(resp) @@ -61,13 +61,13 @@ class Vnfd(object): self._client.get_token() if utils.validate_uuid4(name): for vnfd in self.list(): - if name == vnfd['_id']: + if name == vnfd["_id"]: return vnfd else: for vnfd in self.list(): - if 'product-name' in vnfd and name == vnfd['product-name']: + if "product-name" in vnfd and name == vnfd["product-name"]: return vnfd - elif 'name' in vnfd and name == vnfd['name']: + elif "name" in vnfd and name == vnfd["name"]: return vnfd raise NotFound("vnfd {} not found".format(name)) @@ -77,7 +77,7 @@ class Vnfd(object): # It is redundant, since the previous one already gets the whole vnfpkginfo # The only difference is that a different primitive is exercised try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, vnfd['_id'])) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, vnfd["_id"])) if resp: return json.loads(resp) except NotFound: @@ -88,97 +88,122 @@ class Vnfd(object): self._logger.debug("") vnfd = self.get(name) headers = self._client._headers - headers['Accept'] = 'application/binary' - http_code, resp = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, vnfd['_id'], thing)) + headers["Accept"] = "application/binary" + http_code, resp = self._http.get2_cmd( + "{}/{}/{}".format(self._apiBase, vnfd["_id"], thing) + ) if resp: return json.loads(resp) def get_descriptor(self, name, filename): self._logger.debug("") - self.get_thing(name, 'vnfd', filename) + self.get_thing(name, "vnfd", filename) def get_package(self, name, filename): self._logger.debug("") - self.get_thing(name, 'package_content', filename) + self.get_thing(name, "package_content", filename) def get_artifact(self, name, artifact, filename): self._logger.debug("") - self.get_thing(name, 'artifacts/{}'.format(artifact), filename) + self.get_thing(name, "artifacts/{}".format(artifact), filename) def delete(self, name, force=False): self._logger.debug("") self._client.get_token() vnfd = self.get(name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - vnfd['_id'], querystring)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, vnfd["_id"], querystring) + ) if http_code == 202: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: msg = resp or "" raise ClientException("failed to delete vnfd {} - {}".format(name, msg)) - def create(self, filename, overwrite=None, update_endpoint=None, skip_charm_build=False, - override_epa=False, override_nonepa=False, override_paravirt=False): + def create( + self, + filename, + overwrite=None, + update_endpoint=None, + skip_charm_build=False, + override_epa=False, + override_nonepa=False, + override_paravirt=False, + ): self._logger.debug("") if os.path.isdir(filename): - filename = filename.rstrip('/') - filename = self._client.package_tool.build(filename, skip_validation=False, - skip_charm_build=skip_charm_build) + filename = filename.rstrip("/") + filename = self._client.package_tool.build( + filename, skip_validation=False, skip_charm_build=skip_charm_build + ) - print('Uploading package {}'.format(filename)) - self.create(filename, overwrite=overwrite, update_endpoint=update_endpoint, - override_epa=override_epa, override_nonepa=override_nonepa, - override_paravirt=override_paravirt) + print("Uploading package {}".format(filename)) + self.create( + filename, + overwrite=overwrite, + update_endpoint=update_endpoint, + override_epa=override_epa, + override_nonepa=override_nonepa, + override_paravirt=override_paravirt, + ) else: self._client.get_token() mime_type = magic.from_file(filename, mime=True) if mime_type is None: raise ClientException( "Unexpected MIME type for file {}: MIME type {}".format( - filename, mime_type) + filename, mime_type + ) ) headers = self._client._headers - headers['Content-Filename'] = basename(filename) - if mime_type in ['application/yaml', 'text/plain', 'application/json']: - headers['Content-Type'] = 'text/plain' - elif mime_type in ['application/gzip', 'application/x-gzip']: - headers['Content-Type'] = 'application/gzip' + headers["Content-Filename"] = basename(filename) + if mime_type in ["application/yaml", "text/plain", "application/json"]: + headers["Content-Type"] = "text/plain" + elif mime_type in ["application/gzip", "application/x-gzip"]: + headers["Content-Type"] = "application/gzip" else: raise ClientException( "Unexpected MIME type for file {}: MIME type {}".format( - filename, mime_type) + filename, mime_type + ) ) - special_override_string = '' + special_override_string = "" if override_epa or override_nonepa or override_paravirt: # If override for EPA, non-EPA or paravirt is required, get the descriptor data descriptor_data = None - if mime_type in ['application/yaml', 'text/plain', 'application/json']: + if mime_type in ["application/yaml", "text/plain", "application/json"]: with open(filename) as df: descriptor_data = df.read() - elif mime_type in ['application/gzip', 'application/x-gzip']: + elif mime_type in ["application/gzip", "application/x-gzip"]: tar_object = tarfile.open(filename, "r:gz") descriptor_list = [] for member in tar_object: if member.isreg(): - if '/' not in os.path.dirname(member.name) and member.name.endswith('.yaml'): + if "/" not in os.path.dirname( + member.name + ) and member.name.endswith(".yaml"): descriptor_list.append(member.name) if len(descriptor_list) > 1: - raise ClientException('Found more than one potential descriptor in the tar.gz file') + raise ClientException( + "Found more than one potential descriptor in the tar.gz file" + ) elif len(descriptor_list) == 0: - raise ClientException('No descriptor was found in the tar.gz file') + raise ClientException( + "No descriptor was found in the tar.gz file" + ) with tar_object.extractfile(descriptor_list[0]) as df: descriptor_data = df.read() tar_object.close() if not descriptor_data: - raise ClientException('Descriptor could not be read') + raise ClientException("Descriptor could not be read") desc_type, vnfd = validation_im().yaml_validation(descriptor_data) validation_im().pyangbind_validation(desc_type, vnfd) @@ -189,8 +214,8 @@ class Vnfd(object): # Get only the first descriptor in case there are many in the yaml file # k can be vnfd or etsi-nfv-vnfd:vnfd. This check is skipped first_vnfd = vnfd.get(k, {}) - vcd_list = first_vnfd.get('virtual-compute-desc', []) - vdu_list = first_vnfd.get('vdu', []) + vcd_list = first_vnfd.get("virtual-compute-desc", []) + vdu_list = first_vnfd.get("vdu", []) break for vcd_number, vcd in enumerate(vcd_list): @@ -200,22 +225,31 @@ class Vnfd(object): virtual_memory["numa-enabled"] = True virtual_memory["numa-node-policy"] = { "node-cnt": 1, - "mem-policy": "STRICT" + "mem-policy": "STRICT", } virtual_cpu = vcd["virtual-cpu"] virtual_cpu["pinning"] = { "policy": "static", - "thread-policy": "PREFER" + "thread-policy": "PREFER", } - cpu_override_string = "virtual-compute-desc.{}.virtual-cpu={};"\ - .format(vcd_number, quote(yaml.safe_dump(virtual_cpu))) - memory_override_string = "virtual-compute-desc.{}.virtual-memory={};"\ - .format(vcd_number, quote(yaml.safe_dump(virtual_memory))) - special_override_string = "{}{}{}".format(special_override_string, - cpu_override_string, memory_override_string) + cpu_override_string = ( + "virtual-compute-desc.{}.virtual-cpu={};".format( + vcd_number, quote(yaml.safe_dump(virtual_cpu)) + ) + ) + memory_override_string = ( + "virtual-compute-desc.{}.virtual-memory={};".format( + vcd_number, quote(yaml.safe_dump(virtual_memory)) + ) + ) + special_override_string = "{}{}{}".format( + special_override_string, + cpu_override_string, + memory_override_string, + ) - headers['Query-String-Format'] = 'yaml' + headers["Query-String-Format"] = "yaml" if override_nonepa: virtual_memory = vcd["virtual-memory"] virtual_memory["mempage-size"] = "" @@ -224,32 +258,52 @@ class Vnfd(object): virtual_cpu = vcd["virtual-cpu"] virtual_cpu["pinning"] = {} - cpu_override_string = "virtual-compute-desc.{}.virtual-cpu={};"\ - .format(vcd_number, quote(yaml.safe_dump(virtual_cpu))) - memory_override_string = "virtual-compute-desc.{}.virtual-memory={};"\ - .format(vcd_number, quote(yaml.safe_dump(virtual_memory))) - special_override_string = "{}{}{}".format(special_override_string, - cpu_override_string, memory_override_string) + cpu_override_string = ( + "virtual-compute-desc.{}.virtual-cpu={};".format( + vcd_number, quote(yaml.safe_dump(virtual_cpu)) + ) + ) + memory_override_string = ( + "virtual-compute-desc.{}.virtual-memory={};".format( + vcd_number, quote(yaml.safe_dump(virtual_memory)) + ) + ) + special_override_string = "{}{}{}".format( + special_override_string, + cpu_override_string, + memory_override_string, + ) if override_paravirt: for vdu_number, vdu in enumerate(vdu_list): for cpd_number, cpd in enumerate(vdu["int-cpd"]): - for vnir_number, vnir in enumerate(cpd['virtual-network-interface-requirement']): - special_override_string = "{}vdu.{}.int-cpd.{}.virtual-network-interface-" \ - "requirement.{}.virtual-interface.type=PARAVIRT;"\ - .format(special_override_string, vdu_number, cpd_number, vnir_number) + for vnir_number, vnir in enumerate( + cpd["virtual-network-interface-requirement"] + ): + special_override_string = ( + "{}vdu.{}.int-cpd.{}.virtual-network-interface-" + "requirement.{}.virtual-interface.type=PARAVIRT;".format( + special_override_string, + vdu_number, + cpd_number, + vnir_number, + ) + ) special_override_string = special_override_string.rstrip(";") headers["Content-File-MD5"] = utils.md5(filename) - http_header = ['{}: {}'.format(key, val) - for (key, val) in list(headers.items())] + http_header = [ + "{}: {}".format(key, val) for (key, val) in list(headers.items()) + ] self._http.set_http_header(http_header) if update_endpoint: - http_code, resp = self._http.put_cmd(endpoint=update_endpoint, filename=filename) + http_code, resp = self._http.put_cmd( + endpoint=update_endpoint, filename=filename + ) else: - ow_string = '' + ow_string = "" if special_override_string: if overwrite: overwrite = "{};{}".format(overwrite, special_override_string) @@ -257,25 +311,30 @@ class Vnfd(object): overwrite = special_override_string if overwrite: - ow_string = '?{}'.format(overwrite) - self._apiResource = '/vnf_packages_content' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) - endpoint = '{}{}'.format(self._apiBase, ow_string) - http_code, resp = self._http.post_cmd(endpoint=endpoint, filename=filename) + ow_string = "?{}".format(overwrite) + self._apiResource = "/vnf_packages_content" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) + endpoint = "{}{}".format(self._apiBase, ow_string) + http_code, resp = self._http.post_cmd( + endpoint=endpoint, filename=filename + ) if http_code in (200, 201, 202): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server: {}'.format(resp)) - print(resp['id']) + if not resp or "id" not in resp: + raise ClientException( + "unexpected response from server: {}".format(resp) + ) + print(resp["id"]) elif http_code == 204: - print('Updated') + print("Updated") def update(self, name, filename): self._logger.debug("") self._client.get_token() vnfd = self.get(name) - endpoint = '{}/{}/package_content'.format(self._apiBase, vnfd['_id']) + endpoint = "{}/{}/package_content".format(self._apiBase, vnfd["_id"]) self.create(filename=filename, update_endpoint=endpoint) diff --git a/osmclient/sol005/wim.py b/osmclient/sol005/wim.py index 5da3941..2466113 100644 --- a/osmclient/sol005/wim.py +++ b/osmclient/sol005/wim.py @@ -31,76 +31,77 @@ class Wim(object): def __init__(self, http=None, client=None): self._http = http self._client = client - self._logger = logging.getLogger('osmclient') - self._apiName = '/admin' - self._apiVersion = '/v1' - self._apiResource = '/wim_accounts' - self._apiBase = '{}{}{}'.format(self._apiName, - self._apiVersion, self._apiResource) + self._logger = logging.getLogger("osmclient") + self._apiName = "/admin" + self._apiVersion = "/v1" + self._apiResource = "/wim_accounts" + self._apiBase = "{}{}{}".format( + self._apiName, self._apiVersion, self._apiResource + ) # WIM '--wait' option def _wait(self, id, wait_time, deleteFlag=False): self._logger.debug("") self._client.get_token() # Endpoint to get operation status - apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/wim_accounts') + apiUrlStatus = "{}{}{}".format(self._apiName, self._apiVersion, "/wim_accounts") # Wait for status for WIM instance creation/deletion if isinstance(wait_time, bool): wait_time = WaitForStatus.TIMEOUT_WIM_OPERATION WaitForStatus.wait_for_status( - 'WIM', + "WIM", str(id), wait_time, apiUrlStatus, self._http.get2_cmd, - deleteFlag=deleteFlag) + deleteFlag=deleteFlag, + ) def _get_id_for_wait(self, name): - """Returns id of name, or the id itself if given as argument - """ + """Returns id of name, or the id itself if given as argument""" self._logger.debug("") for wim in self.list(): - if name == wim['uuid']: - return wim['uuid'] + if name == wim["uuid"]: + return wim["uuid"] for wim in self.list(): - if name == wim['name']: - return wim['uuid'] - return '' + if name == wim["name"]: + return wim["uuid"] + return "" def create(self, name, wim_input, wim_port_mapping=None, wait=False): self._logger.debug("") self._client.get_token() - if 'wim_type' not in wim_input: + if "wim_type" not in wim_input: raise Exception("wim type not provided") wim_account = wim_input wim_account["name"] = name wim_config = {} - if 'config' in wim_input and wim_input['config'] is not None: - wim_config = yaml.safe_load(wim_input['config']) + if "config" in wim_input and wim_input["config"] is not None: + wim_config = yaml.safe_load(wim_input["config"]) if wim_port_mapping: - with open(wim_port_mapping, 'r') as f: - wim_config['wim_port_mapping'] = yaml.safe_load(f.read()) + with open(wim_port_mapping, "r") as f: + wim_config["wim_port_mapping"] = yaml.safe_load(f.read()) if wim_config: - wim_account['config'] = wim_config - #wim_account['config'] = json.dumps(wim_config) - - http_code, resp = self._http.post_cmd(endpoint=self._apiBase, - postfields_dict=wim_account) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + wim_account["config"] = wim_config + # wim_account['config'] = json.dumps(wim_config) + + http_code, resp = self._http.post_cmd( + endpoint=self._apiBase, postfields_dict=wim_account + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if resp: resp = json.loads(resp) - if not resp or 'id' not in resp: - raise ClientException('unexpected response from server - {}'.format( - resp)) + if not resp or "id" not in resp: + raise ClientException("unexpected response from server - {}".format(resp)) if wait: # Wait for status for WIM instance creation - self._wait(resp.get('id'), wait) - print(resp['id']) - #else: + self._wait(resp.get("id"), wait) + print(resp["id"]) + # else: # msg = "" # if resp: # try: @@ -115,23 +116,27 @@ class Wim(object): wim = self.get(wim_name) wim_id_for_wait = self._get_id_for_wait(wim_name) wim_config = {} - if 'config' in wim_account: - if wim_account.get('config')=="" and (wim_port_mapping): - raise ClientException("clearing config is incompatible with updating SDN info") - if wim_account.get('config')=="": + if "config" in wim_account: + if wim_account.get("config") == "" and (wim_port_mapping): + raise ClientException( + "clearing config is incompatible with updating SDN info" + ) + if wim_account.get("config") == "": wim_config = None else: - wim_config = yaml.safe_load(wim_account['config']) + wim_config = yaml.safe_load(wim_account["config"]) if wim_port_mapping: - with open(wim_port_mapping, 'r') as f: - wim_config['wim_port_mapping'] = yaml.safe_load(f.read()) - wim_account['config'] = wim_config - #wim_account['config'] = json.dumps(wim_config) - http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase,wim['_id']), - postfields_dict=wim_account) - #print('HTTP CODE: {}'.format(http_code)) - #print('RESP: {}'.format(resp)) - #if http_code in (200, 201, 202, 204): + with open(wim_port_mapping, "r") as f: + wim_config["wim_port_mapping"] = yaml.safe_load(f.read()) + wim_account["config"] = wim_config + # wim_account['config'] = json.dumps(wim_config) + http_code, resp = self._http.patch_cmd( + endpoint="{}/{}".format(self._apiBase, wim["_id"]), + postfields_dict=wim_account, + ) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # if http_code in (200, 201, 202, 204): if wait: # In this case, 'resp' always returns None, so 'resp['id']' cannot be used. # Use the previously obtained id instead. @@ -140,7 +145,7 @@ class Wim(object): self._wait(wait_id, wait) # else: # pass - #else: + # else: # msg = "" # if resp: # try: @@ -152,20 +157,19 @@ class Wim(object): def update_wim_account_dict(self, wim_account, wim_input): self._logger.debug("") self._logger.debug(str(wim_input)) - wim_account['wim_type'] = wim_input['wim_type'] - wim_account['description'] = wim_input['description'] - wim_account['wim_url'] = wim_input['url'] - wim_account['user'] = wim_input.get('wim-username') - wim_account['password'] = wim_input.get('wim-password') + wim_account["wim_type"] = wim_input["wim_type"] + wim_account["description"] = wim_input["description"] + wim_account["wim_url"] = wim_input["url"] + wim_account["user"] = wim_input.get("wim-username") + wim_account["password"] = wim_input.get("wim-password") return wim_account def get_id(self, name): - """Returns a WIM id from a WIM name - """ + """Returns a WIM id from a WIM name""" self._logger.debug("") for wim in self.list(): - if name == wim['name']: - return wim['uuid'] + if name == wim["name"]: + return wim["uuid"] raise NotFound("wim {} not found".format(name)) def delete(self, wim_name, force=False, wait=False): @@ -175,11 +179,12 @@ class Wim(object): wim_id_for_wait = self._get_id_for_wait(wim_name) if not utils.validate_uuid4(wim_name): wim_id = self.get_id(wim_name) - querystring = '' + querystring = "" if force: - querystring = '?FORCE=True' - http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, - wim_id, querystring)) + querystring = "?FORCE=True" + http_code, resp = self._http.delete_cmd( + "{}/{}{}".format(self._apiBase, wim_id, querystring) + ) # print('HTTP CODE: {}'.format(http_code)) # print('RESP: {}'.format(resp)) # print('WIM_ID: {}'.format(wim_id)) @@ -190,15 +195,15 @@ class Wim(object): wait_id = wim_id_for_wait if resp: resp = json.loads(resp) - wait_id = resp.get('id') + wait_id = resp.get("id") # Wait for status for WIM account deletion self._wait(wait_id, wait, deleteFlag=True) else: - print('Deletion in progress') + print("Deletion in progress") elif http_code == 204: - print('Deleted') + print("Deleted") else: - msg = resp or "" + msg = resp or "" # if resp: # try: # msg = json.loads(resp) @@ -207,37 +212,38 @@ class Wim(object): raise ClientException("failed to delete wim {} - {}".format(wim_name, msg)) def list(self, filter=None): - """Returns a list of VIM accounts - """ + """Returns a list of VIM accounts""" self._logger.debug("") self._client.get_token() - filter_string = '' + filter_string = "" if filter: - filter_string = '?{}'.format(filter) - _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string)) + filter_string = "?{}".format(filter) + _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) if not resp: return list() wim_accounts = [] for datacenter in json.loads(resp): - wim_accounts.append({"name": datacenter['name'], "uuid": datacenter['_id'] - if '_id' in datacenter else None}) + wim_accounts.append( + { + "name": datacenter["name"], + "uuid": datacenter["_id"] if "_id" in datacenter else None, + } + ) return wim_accounts def get(self, name): - """Returns a VIM account based on name or id - """ + """Returns a VIM account based on name or id""" self._logger.debug("") self._client.get_token() wim_id = name if not utils.validate_uuid4(name): wim_id = self.get_id(name) try: - _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase,wim_id)) + _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, wim_id)) if resp: - resp = json.loads(resp) - if not resp or '_id' not in resp: - raise ClientException('failed to get wim info: {}'.format(resp)) + resp = json.loads(resp) + if not resp or "_id" not in resp: + raise ClientException("failed to get wim info: {}".format(resp)) return resp except NotFound: raise NotFound("wim '{}' not found".format(name)) - diff --git a/osmclient/v1/client.py b/osmclient/v1/client.py index ba765e1..cad9c94 100644 --- a/osmclient/v1/client.py +++ b/osmclient/v1/client.py @@ -31,59 +31,60 @@ from osmclient.common import package_tool class Client(object): - def __init__( self, host=None, so_port=8008, - so_project='default', + so_project="default", ro_host=None, ro_port=9090, upload_port=8443, - **kwargs): - self._user = 'admin' - self._password = 'admin' + **kwargs + ): + self._user = "admin" + self._password = "admin" - if len(host.split(':')) > 1: + if len(host.split(":")) > 1: # backwards compatible, port provided as part of host - self._host = host.split(':')[0] - self._so_port = host.split(':')[1] + self._host = host.split(":")[0] + self._so_port = host.split(":")[1] else: self._host = host self._so_port = so_port self._so_project = so_project - http_client = http.Http( - 'https://{}:{}/'.format( - self._host, - self._so_port)) + http_client = http.Http("https://{}:{}/".format(self._host, self._so_port)) http_client.set_http_header( - ['Accept: application/vnd.yand.data+json', - 'Content-Type: application/json']) + ["Accept: application/vnd.yand.data+json", "Content-Type: application/json"] + ) self._so_version = self.get_so_version(http_client) if ro_host is None: ro_host = host - ro_http_client = http.Http('http://{}:{}/'.format(ro_host, ro_port)) + ro_http_client = http.Http("http://{}:{}/".format(ro_host, ro_port)) ro_http_client.set_http_header( - ['Accept: application/vnd.yand.data+json', - 'Content-Type: application/json']) - - upload_client_url = 'https://{}:{}/composer/upload?api_server={}{}'.format( - self._host, - upload_port, - 'https://localhost&upload_server=https://', - self._host) - - if self._so_version == 'v3': - upload_client_url = 'https://{}:{}/composer/upload?api_server={}{}&project_name={}'.format( - self._host, - upload_port, - 'https://localhost&upload_server=https://', - self._host, - self._so_project) + ["Accept: application/vnd.yand.data+json", "Content-Type: application/json"] + ) + + upload_client_url = "https://{}:{}/composer/upload?api_server={}{}".format( + self._host, + upload_port, + "https://localhost&upload_server=https://", + self._host, + ) + + if self._so_version == "v3": + upload_client_url = ( + "https://{}:{}/composer/upload?api_server={}{}&project_name={}".format( + self._host, + upload_port, + "https://localhost&upload_server=https://", + self._host, + self._so_project, + ) + ) upload_client = http.Http(upload_client_url) @@ -92,37 +93,31 @@ class Client(object): self.ns = ns.Ns(http=http_client, client=self, **kwargs) self.nsd = nsd.Nsd(http_client, client=self, **kwargs) self.vim = vim.Vim( - http=http_client, - ro_http=ro_http_client, - client=self, - **kwargs) + http=http_client, ro_http=ro_http_client, client=self, **kwargs + ) self.package = package.Package( - http=http_client, - upload_http=upload_client, - client=self, - **kwargs) + http=http_client, upload_http=upload_client, client=self, **kwargs + ) self.vca = vca.Vca(http_client, client=self, **kwargs) self.utils = utils.Utils(http_client, **kwargs) self.package_tool = package_tool.PackageTool(client=self) @property def so_rbac_project_path(self): - if self._so_version == 'v3': - return 'project/{}/'.format(self._so_project) + if self._so_version == "v3": + return "project/{}/".format(self._so_project) else: - return '' + return "" def get_so_version(self, http_client): try: - resp = http_client.get_cmd('api/operational/version') - if not resp or 'rw-base:version' not in resp: - return 'v2' + resp = http_client.get_cmd("api/operational/version") + if not resp or "rw-base:version" not in resp: + return "v2" - if resp['rw-base:version']['version'].split('.')[0] == '5': + if resp["rw-base:version"]["version"].split(".")[0] == "5": # SO Version 5.x.x.x.x translates to OSM V3 - return 'v3' - return 'v2' + return "v3" + return "v2" except Exception: - return 'v2' - - + return "v2" diff --git a/osmclient/v1/key.py b/osmclient/v1/key.py index a0dcef9..4e51b78 100644 --- a/osmclient/v1/key.py +++ b/osmclient/v1/key.py @@ -24,18 +24,17 @@ from io import BytesIO class Key(object): - def __init__(self, client=None): self._client = client def list(self): data = BytesIO() - curl_cmd = self._client.get_curl_cmd('v1/api/config/key-pair?deep') + curl_cmd = self._client.get_curl_cmd("v1/api/config/key-pair?deep") curl_cmd.setopt(pycurl.HTTPGET, 1) curl_cmd.setopt(pycurl.WRITEFUNCTION, data.write) curl_cmd.perform() curl_cmd.close() resp = json.loads(data.getvalue().decode()) - if 'nsr:key-pair' in resp: - return resp['nsr:key-pair'] + if "nsr:key-pair" in resp: + return resp["nsr:key-pair"] return list() diff --git a/osmclient/v1/ns.py b/osmclient/v1/ns.py index e6b747f..5006c1f 100644 --- a/osmclient/v1/ns.py +++ b/osmclient/v1/ns.py @@ -26,126 +26,143 @@ import yaml class Ns(object): - def __init__(self, http=None, client=None): self._http = http self._client = client def list(self): - """Returns a list of ns's - """ - resp = self._http.get_cmd('api/running/{}ns-instance-config' - .format(self._client.so_rbac_project_path)) - if not resp or 'nsr:ns-instance-config' not in resp: + """Returns a list of ns's""" + resp = self._http.get_cmd( + "api/running/{}ns-instance-config".format(self._client.so_rbac_project_path) + ) + if not resp or "nsr:ns-instance-config" not in resp: return list() - if 'nsr' not in resp['nsr:ns-instance-config']: + if "nsr" not in resp["nsr:ns-instance-config"]: return list() - return resp['nsr:ns-instance-config']['nsr'] + return resp["nsr:ns-instance-config"]["nsr"] def get(self, name): - """Returns an ns based on name - """ + """Returns an ns based on name""" for ns in self.list(): - if name == ns['name']: + if name == ns["name"]: return ns raise NotFound("ns {} not found".format(name)) def scale(self, ns_name, ns_scale_group, instance_index): postdata = {} - postdata['instance'] = list() + postdata["instance"] = list() instance = {} - instance['id'] = instance_index - postdata['instance'].append(instance) + instance["id"] = instance_index + postdata["instance"].append(instance) ns = self.get(ns_name) resp = self._http.post_cmd( - 'v1/api/config/{}ns-instance-config/nsr/{}/scaling-group/{}/instance' - .format(self._client.so_rbac_project_path, ns['id'], ns_scale_group), postdata) - if 'success' not in resp: + "v1/api/config/{}ns-instance-config/nsr/{}/scaling-group/{}/instance".format( + self._client.so_rbac_project_path, ns["id"], ns_scale_group + ), + postdata, + ) + if "success" not in resp: raise ClientException( - "failed to scale ns: {} result: {}".format( - ns_name, - resp)) - - def create(self, nsd_name, nsr_name, account, config=None, - ssh_keys=None, description='default description', - admin_status='ENABLED'): + "failed to scale ns: {} result: {}".format(ns_name, resp) + ) + + def create( + self, + nsd_name, + nsr_name, + account, + config=None, + ssh_keys=None, + description="default description", + admin_status="ENABLED", + ): postdata = {} - postdata['nsr'] = list() + postdata["nsr"] = list() nsr = {} - nsr['id'] = str(uuid.uuid1()) + nsr["id"] = str(uuid.uuid1()) nsd = self._client.nsd.get(nsd_name) - - if self._client._so_version == 'v3': + + if self._client._so_version == "v3": datacenter, resource_orchestrator = self._client.vim.get_datacenter(account) if datacenter is None or resource_orchestrator is None: raise NotFound("cannot find datacenter account {}".format(account)) - if 'uuid' not in datacenter: - raise NotFound("The RO Datacenter - {} is invalid. Please select another".format(account)) + if "uuid" not in datacenter: + raise NotFound( + "The RO Datacenter - {} is invalid. Please select another".format( + account + ) + ) else: # Backwards Compatiility datacenter = self._client.vim.get_datacenter(account) if datacenter is None: raise NotFound("cannot find datacenter account {}".format(account)) - nsr['nsd'] = nsd - nsr['name'] = nsr_name - nsr['short-name'] = nsr_name - nsr['description'] = description - nsr['admin-status'] = admin_status - - if self._client._so_version == 'v3': + nsr["nsd"] = nsd + nsr["name"] = nsr_name + nsr["short-name"] = nsr_name + nsr["description"] = description + nsr["admin-status"] = admin_status + + if self._client._so_version == "v3": # New format for V3 - nsr['resource-orchestrator'] = resource_orchestrator - nsr['datacenter'] = datacenter['name'] + nsr["resource-orchestrator"] = resource_orchestrator + nsr["datacenter"] = datacenter["name"] else: # Backwards Compatiility - nsr['om-datacenter'] = datacenter['uuid'] + nsr["om-datacenter"] = datacenter["uuid"] if ssh_keys is not None: # ssh_keys is comma separate list ssh_keys_format = [] - for key in ssh_keys.split(','): - ssh_keys_format.append({'key-pair-ref': key}) + for key in ssh_keys.split(","): + ssh_keys_format.append({"key-pair-ref": key}) - nsr['ssh-authorized-key'] = ssh_keys_format + nsr["ssh-authorized-key"] = ssh_keys_format ns_config = {} - if config: + if config: ns_config = yaml.safe_load(config) - if ns_config and 'vim-network-name' in ns_config: - for network in ns_config['vim-network-name']: + if ns_config and "vim-network-name" in ns_config: + for network in ns_config["vim-network-name"]: # now find this network - vld_name = network['name'] + vld_name = network["name"] # vim_vld_name = network['vim-network-name'] - for index, vld in enumerate(nsr['nsd']['vld']): - if vld['name'] == vld_name: - nsr['nsd']['vld'][index]['vim-network-name'] = network['vim-network-name'] + for index, vld in enumerate(nsr["nsd"]["vld"]): + if vld["name"] == vld_name: + nsr["nsd"]["vld"][index]["vim-network-name"] = network[ + "vim-network-name" + ] - postdata['nsr'].append(nsr) + postdata["nsr"].append(nsr) resp = self._http.post_cmd( - 'api/config/{}ns-instance-config/nsr' - .format(self._client.so_rbac_project_path), - postdata) + "api/config/{}ns-instance-config/nsr".format( + self._client.so_rbac_project_path + ), + postdata, + ) - if 'success' not in resp: + if "success" not in resp: raise ClientException( "failed to create ns: {} nsd: {} result: {}".format( - nsr_name, - nsd_name, - resp)) + nsr_name, nsd_name, resp + ) + ) def get_opdata(self, id): return self._http.get_cmd( - 'api/operational/{}ns-instance-opdata/nsr/{}?deep' - .format(self._client.so_rbac_project_path, id)) + "api/operational/{}ns-instance-opdata/nsr/{}?deep".format( + self._client.so_rbac_project_path, id + ) + ) def get_field(self, ns_name, field): nsr = self.get(ns_name) @@ -155,10 +172,10 @@ class Ns(object): if field in nsr: return nsr[field] - nsopdata = self.get_opdata(nsr['id']) + nsopdata = self.get_opdata(nsr["id"]) - if field in nsopdata['nsr:nsr']: - return nsopdata['nsr:nsr'][field] + if field in nsopdata["nsr:nsr"]: + return nsopdata["nsr:nsr"][field] raise NotFound("failed to find {} in ns {}".format(field, ns_name)) @@ -167,14 +184,17 @@ class Ns(object): if ns is None: raise NotFound("cannot find ns {}".format(ns_name)) - return self._http.delete_cmd('api/config/{}ns-instance-config/nsr/{}' - .format(self._client.so_rbac_project_path, ns['id'])) + return self._http.delete_cmd( + "api/config/{}ns-instance-config/nsr/{}".format( + self._client.so_rbac_project_path, ns["id"] + ) + ) def delete(self, ns_name, wait=True): - vnfs = self.get_field(ns_name, 'constituent-vnfr-ref') + vnfs = self.get_field(ns_name, "constituent-vnfr-ref") resp = self._terminate(ns_name) - if 'success' not in resp: + if "success" not in resp: raise ClientException("failed to delete ns {}".format(ns_name)) # helper method to check if pkg exists @@ -186,15 +206,13 @@ class Ns(object): return True for vnf in vnfs: - if (not utils.wait_for_value( - lambda: - check_not_exists(lambda: - self._client.vnf.get(vnf['vnfr-id'])))): - raise ClientException( - "vnf {} failed to delete".format(vnf['vnfr-id'])) - if not utils.wait_for_value(lambda: - check_not_exists(lambda: - self.get(ns_name))): + if not utils.wait_for_value( + lambda: check_not_exists(lambda: self._client.vnf.get(vnf["vnfr-id"])) + ): + raise ClientException("vnf {} failed to delete".format(vnf["vnfr-id"])) + if not utils.wait_for_value( + lambda: check_not_exists(lambda: self.get(ns_name)) + ): raise ClientException("ns {} failed to delete".format(ns_name)) def get_monitoring(self, ns_name): @@ -205,8 +223,8 @@ class Ns(object): vnfs = self._client.vnf.list() for vnf in vnfs: - if ns['id'] == vnf['nsr-id-ref']: - if 'monitoring-param' in vnf: - mon_list[vnf['name']] = vnf['monitoring-param'] + if ns["id"] == vnf["nsr-id-ref"]: + if "monitoring-param" in vnf: + mon_list[vnf["name"]] = vnf["monitoring-param"] return mon_list diff --git a/osmclient/v1/nsd.py b/osmclient/v1/nsd.py index 52c5772..527a45f 100644 --- a/osmclient/v1/nsd.py +++ b/osmclient/v1/nsd.py @@ -23,28 +23,28 @@ from osmclient.common.exceptions import ClientException class Nsd(object): - def __init__(self, http=None, client=None): self._http = http self._client = client def list(self): - resp = self._http.get_cmd('api/running/{}nsd-catalog/nsd' - .format(self._client.so_rbac_project_path)) - - if self._client._so_version == 'v3': - if resp and 'project-nsd:nsd' in resp: - return resp['project-nsd:nsd'] + resp = self._http.get_cmd( + "api/running/{}nsd-catalog/nsd".format(self._client.so_rbac_project_path) + ) + + if self._client._so_version == "v3": + if resp and "project-nsd:nsd" in resp: + return resp["project-nsd:nsd"] else: # Backwards Compatibility - if resp and 'nsd:nsd' in resp: - return resp['nsd:nsd'] + if resp and "nsd:nsd" in resp: + return resp["nsd:nsd"] return list() def get(self, name): for nsd in self.list(): - if name == nsd['name']: + if name == nsd["name"]: return nsd raise NotFound("cannot find nsd {}".format(name)) @@ -54,7 +54,9 @@ class Nsd(object): raise NotFound("cannot find nsd {}".format(nsd_name)) resp = self._http.delete_cmd( - 'api/running/{}nsd-catalog/nsd/{}' - .format(self._client.so_rbac_project_path, nsd['id'])) - if 'success' not in resp: + "api/running/{}nsd-catalog/nsd/{}".format( + self._client.so_rbac_project_path, nsd["id"] + ) + ) + if "success" not in resp: raise ClientException("failed to delete nsd {}".format(nsd_name)) diff --git a/osmclient/v1/package.py b/osmclient/v1/package.py index b7a2d97..f1a4bf4 100644 --- a/osmclient/v1/package.py +++ b/osmclient/v1/package.py @@ -30,9 +30,9 @@ class Package(object): self._upload_http = upload_http def _wait_for_package(self, pkg_type): - if 'vnfd' in pkg_type['type']: + if "vnfd" in pkg_type["type"]: get_method = self._client.vnfd.get - elif 'nsd' in pkg_type['type']: + elif "nsd" in pkg_type["type"]: get_method = self._client.nsd.get else: raise ClientException("no valid package type found") @@ -45,16 +45,16 @@ class Package(object): return False return True - return utils.wait_for_value(lambda: - check_exists(lambda: - get_method(pkg_type['name']))) + return utils.wait_for_value( + lambda: check_exists(lambda: get_method(pkg_type["name"])) + ) def get_key_val_from_pkg(self, descriptor_file): return utils.get_key_val_from_pkg(descriptor_file) def wait_for_upload(self, filename): """wait(block) for an upload to succeed. - The filename passed is assumed to be a descriptor tarball. + The filename passed is assumed to be a descriptor tarball. """ pkg_type = utils.get_key_val_from_pkg(filename) @@ -62,10 +62,9 @@ class Package(object): raise ClientException("Cannot determine package type") if not self._wait_for_package(pkg_type): - raise ClientException("package {} failed to upload" - .format(filename)) + raise ClientException("package {} failed to upload".format(filename)) def upload(self, filename): - resp = self._upload_http.post_cmd(formfile=('package', filename)) - if not resp or 'transaction_id' not in resp: + resp = self._upload_http.post_cmd(formfile=("package", filename)) + if not resp or "transaction_id" not in resp: raise ClientException("failed to upload package") diff --git a/osmclient/v1/tests/test_ns.py b/osmclient/v1/tests/test_ns.py index 19fc58f..616b8a4 100644 --- a/osmclient/v1/tests/test_ns.py +++ b/osmclient/v1/tests/test_ns.py @@ -21,24 +21,31 @@ from osmclient.v1 import client from osmclient.common.exceptions import NotFound -class TestNs(unittest.TestCase): +class TestNs(unittest.TestCase): def test_list_empty(self): mock = Mock() mock.get_cmd.return_value = list() - assert len(ns.Ns(mock, client=client.Client(host='127.0.0.1')).list()) == 0 + assert len(ns.Ns(mock, client=client.Client(host="127.0.0.1")).list()) == 0 def test_get_notfound(self): mock = Mock() - mock.get_cmd.return_value = 'foo' - self.assertRaises(NotFound, ns.Ns(mock, client=client.Client(host='127.0.0.1')).get, 'bar') + mock.get_cmd.return_value = "foo" + self.assertRaises( + NotFound, ns.Ns(mock, client=client.Client(host="127.0.0.1")).get, "bar" + ) def test_get_found(self): mock = Mock() - mock.get_cmd.return_value = {'nsr:ns-instance-config': - {'nsr': [{'name': 'foo'}]}} - assert ns.Ns(mock, client=client.Client(host='127.0.0.1')).get('foo') + mock.get_cmd.return_value = { + "nsr:ns-instance-config": {"nsr": [{"name": "foo"}]} + } + assert ns.Ns(mock, client=client.Client(host="127.0.0.1")).get("foo") def test_get_monitoring_notfound(self): mock = Mock() - mock.get_cmd.return_value = 'foo' - self.assertRaises(NotFound, ns.Ns(mock, client=client.Client(host='127.0.0.1')).get_monitoring, 'bar') + mock.get_cmd.return_value = "foo" + self.assertRaises( + NotFound, + ns.Ns(mock, client=client.Client(host="127.0.0.1")).get_monitoring, + "bar", + ) diff --git a/osmclient/v1/tests/test_nsd.py b/osmclient/v1/tests/test_nsd.py index b0b5492..6f0255e 100644 --- a/osmclient/v1/tests/test_nsd.py +++ b/osmclient/v1/tests/test_nsd.py @@ -25,18 +25,20 @@ class TestNsd(unittest.TestCase): def test_list_empty(self): mock = Mock() mock.get_cmd.return_value = list() - assert len(nsd.Nsd(mock, client=client.Client(host='127.0.0.1')).list()) == 0 + assert len(nsd.Nsd(mock, client=client.Client(host="127.0.0.1")).list()) == 0 def test_get_notfound(self): mock = Mock() - mock.get_cmd.return_value = 'foo' - self.assertRaises(NotFound, nsd.Nsd(mock, client=client.Client(host='127.0.0.1')).get, 'bar') + mock.get_cmd.return_value = "foo" + self.assertRaises( + NotFound, nsd.Nsd(mock, client=client.Client(host="127.0.0.1")).get, "bar" + ) def test_get_found(self): mock = Mock() - if client.Client(host='127.0.0.1')._so_version == 'v3': - mock.get_cmd.return_value = {'project-nsd:nsd': [{'name': 'foo'}]} + if client.Client(host="127.0.0.1")._so_version == "v3": + mock.get_cmd.return_value = {"project-nsd:nsd": [{"name": "foo"}]} else: # Backwards Compatibility - mock.get_cmd.return_value = {'nsd:nsd': [{'name': 'foo'}]} - assert nsd.Nsd(mock, client=client.Client(host='127.0.0.1')).get('foo') + mock.get_cmd.return_value = {"nsd:nsd": [{"name": "foo"}]} + assert nsd.Nsd(mock, client=client.Client(host="127.0.0.1")).get("foo") diff --git a/osmclient/v1/tests/test_package.py b/osmclient/v1/tests/test_package.py index 5211b12..2f0362c 100644 --- a/osmclient/v1/tests/test_package.py +++ b/osmclient/v1/tests/test_package.py @@ -21,20 +21,21 @@ from osmclient.common.exceptions import ClientException class TestPackage(unittest.TestCase): - def test_upload_fail(self): mock = Mock() - mock.post_cmd.return_value = 'foo' - self.assertRaises(ClientException, - package.Package(upload_http=mock).upload, 'bar') + mock.post_cmd.return_value = "foo" + self.assertRaises( + ClientException, package.Package(upload_http=mock).upload, "bar" + ) mock.post_cmd.return_value = None - self.assertRaises(ClientException, - package.Package(upload_http=mock).upload, 'bar') + self.assertRaises( + ClientException, package.Package(upload_http=mock).upload, "bar" + ) def test_wait_for_upload_bad_file(self): mock = Mock() - mock.post_cmd.return_value = 'foo' - self.assertRaises(IOError, - package.Package(upload_http=mock).wait_for_upload, - 'invalidfile') + mock.post_cmd.return_value = "foo" + self.assertRaises( + IOError, package.Package(upload_http=mock).wait_for_upload, "invalidfile" + ) diff --git a/osmclient/v1/tests/test_vnf.py b/osmclient/v1/tests/test_vnf.py index 69aca68..40b4648 100644 --- a/osmclient/v1/tests/test_vnf.py +++ b/osmclient/v1/tests/test_vnf.py @@ -25,25 +25,34 @@ class TestVnf(unittest.TestCase): def test_list_empty(self): mock = Mock() mock.get_cmd.return_value = list() - assert len(vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).list()) == 0 + assert len(vnf.Vnf(mock, client=client.Client(host="127.0.0.1")).list()) == 0 def test_get_notfound(self): mock = Mock() - mock.get_cmd.return_value = 'foo' - self.assertRaises(NotFound, vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get, 'bar') + mock.get_cmd.return_value = "foo" + self.assertRaises( + NotFound, vnf.Vnf(mock, client=client.Client(host="127.0.0.1")).get, "bar" + ) def test_get_found(self): mock = Mock() - mock.get_cmd.return_value = {'vnfr:vnfr': [{'name': 'foo'}]} - assert vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get('foo') + mock.get_cmd.return_value = {"vnfr:vnfr": [{"name": "foo"}]} + assert vnf.Vnf(mock, client=client.Client(host="127.0.0.1")).get("foo") def test_get_monitoring_notfound(self): mock = Mock() - mock.get_cmd.return_value = 'foo' - self.assertRaises(NotFound, vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get_monitoring, 'bar') + mock.get_cmd.return_value = "foo" + self.assertRaises( + NotFound, + vnf.Vnf(mock, client=client.Client(host="127.0.0.1")).get_monitoring, + "bar", + ) def test_get_monitoring_found(self): mock = Mock() - mock.get_cmd.return_value = {'vnfr:vnfr': [{'name': 'foo', - 'monitoring-param': True}]} - assert vnf.Vnf(mock, client=client.Client(host='127.0.0.1')).get_monitoring('foo') + mock.get_cmd.return_value = { + "vnfr:vnfr": [{"name": "foo", "monitoring-param": True}] + } + assert vnf.Vnf(mock, client=client.Client(host="127.0.0.1")).get_monitoring( + "foo" + ) diff --git a/osmclient/v1/tests/test_vnfd.py b/osmclient/v1/tests/test_vnfd.py index cd98888..f069742 100644 --- a/osmclient/v1/tests/test_vnfd.py +++ b/osmclient/v1/tests/test_vnfd.py @@ -25,19 +25,21 @@ class TestVnfd(unittest.TestCase): def test_list_empty(self): mock = Mock() mock.get_cmd.return_value = list() - assert len(vnfd.Vnfd(mock, client=client.Client(host='127.0.0.1')).list()) == 0 + assert len(vnfd.Vnfd(mock, client=client.Client(host="127.0.0.1")).list()) == 0 def test_get_notfound(self): mock = Mock() - mock.get_cmd.return_value = 'foo' - self.assertRaises(NotFound, vnfd.Vnfd(mock, client=client.Client(host='127.0.0.1')).get, 'bar') + mock.get_cmd.return_value = "foo" + self.assertRaises( + NotFound, vnfd.Vnfd(mock, client=client.Client(host="127.0.0.1")).get, "bar" + ) def test_get_found(self): mock = Mock() - if client.Client(host='127.0.0.1')._so_version == 'v3': - mock.get_cmd.return_value = {'project-vnfd:vnfd': [{'name': 'foo'}]} + if client.Client(host="127.0.0.1")._so_version == "v3": + mock.get_cmd.return_value = {"project-vnfd:vnfd": [{"name": "foo"}]} else: # Backwards Compatibility - mock.get_cmd.return_value = {'vnfd:vnfd': [{'name': 'foo'}]} + mock.get_cmd.return_value = {"vnfd:vnfd": [{"name": "foo"}]} - assert vnfd.Vnfd(mock, client=client.Client(host='127.0.0.1')).get('foo') + assert vnfd.Vnfd(mock, client=client.Client(host="127.0.0.1")).get("foo") diff --git a/osmclient/v1/utils.py b/osmclient/v1/utils.py index f4baef8..092f193 100644 --- a/osmclient/v1/utils.py +++ b/osmclient/v1/utils.py @@ -24,7 +24,7 @@ class Utils(object): self._http = http def get_vcs_info(self): - resp = self._http.get_cmd('api/operational/vcs/info') + resp = self._http.get_cmd("api/operational/vcs/info") if resp: - return resp['rw-base:info']['components']['component_info'] + return resp["rw-base:info"]["components"]["component_info"] return list() diff --git a/osmclient/v1/vca.py b/osmclient/v1/vca.py index adac986..d2f17c6 100644 --- a/osmclient/v1/vca.py +++ b/osmclient/v1/vca.py @@ -22,39 +22,41 @@ from osmclient.common.exceptions import ClientException class Vca(object): - def __init__(self, http=None, client=None): self._http = http self._client = client def list(self): - resp = self._http.get_cmd('api/config/{}config-agent' - .format(self._client.so_rbac_project_path)) - if resp and 'rw-config-agent:config-agent' in resp: - return resp['rw-config-agent:config-agent']['account'] + resp = self._http.get_cmd( + "api/config/{}config-agent".format(self._client.so_rbac_project_path) + ) + if resp and "rw-config-agent:config-agent" in resp: + return resp["rw-config-agent:config-agent"]["account"] return list() def delete(self, name): - if ('success' not in - self._http.delete_cmd('api/config/{}config-agent/account/{}' - .format(self._client.so_rbac_project_path, name))): - raise ClientException("failed to delete config agent {}" - .format(name)) + if "success" not in self._http.delete_cmd( + "api/config/{}config-agent/account/{}".format( + self._client.so_rbac_project_path, name + ) + ): + raise ClientException("failed to delete config agent {}".format(name)) def create(self, name, account_type, server, user, secret): postdata = {} - postdata['account'] = list() + postdata["account"] = list() account = {} - account['name'] = name - account['account-type'] = account_type - account['juju'] = {} - account['juju']['user'] = user - account['juju']['secret'] = secret - account['juju']['ip-address'] = server - postdata['account'].append(account) - - if 'success' not in self._http.post_cmd('api/config/{}config-agent' - .format(self._client.so_rbac_project_path), postdata): - raise ClientException("failed to create config agent {}" - .format(name)) + account["name"] = name + account["account-type"] = account_type + account["juju"] = {} + account["juju"]["user"] = user + account["juju"]["secret"] = secret + account["juju"]["ip-address"] = server + postdata["account"].append(account) + + if "success" not in self._http.post_cmd( + "api/config/{}config-agent".format(self._client.so_rbac_project_path), + postdata, + ): + raise ClientException("failed to create config agent {}".format(name)) diff --git a/osmclient/v1/vim.py b/osmclient/v1/vim.py index 849f6dc..35266aa 100644 --- a/osmclient/v1/vim.py +++ b/osmclient/v1/vim.py @@ -20,7 +20,7 @@ OSM vim API handling from osmclient.common.exceptions import ClientException from osmclient.common.exceptions import NotFound -import yaml +import yaml import time @@ -31,110 +31,119 @@ class Vim(object): self._http = http def _attach(self, vim_name, vim_account): - tenant_name = 'osm' + tenant_name = "osm" tenant = self._get_ro_tenant() if tenant is None: raise ClientException("tenant {} not found".format(tenant_name)) datacenter = self._get_ro_datacenter(vim_name) if datacenter is None: - raise Exception('datacenter {} not found'.format(vim_name)) + raise Exception("datacenter {} not found".format(vim_name)) - return self._ro_http.post_cmd('openmano/{}/datacenters/{}' - .format(tenant['uuid'], - datacenter['uuid']), vim_account) + return self._ro_http.post_cmd( + "openmano/{}/datacenters/{}".format(tenant["uuid"], datacenter["uuid"]), + vim_account, + ) def _detach(self, vim_name): - tenant_name = 'osm' + tenant_name = "osm" tenant = self._get_ro_tenant() if tenant is None: raise ClientException("tenant {} not found".format(tenant_name)) - return self._ro_http.delete_cmd('openmano/{}/datacenters/{}' - .format(tenant["uuid"], vim_name)) + return self._ro_http.delete_cmd( + "openmano/{}/datacenters/{}".format(tenant["uuid"], vim_name) + ) def create(self, name, vim_access): vim_account = {} - vim_account['datacenter'] = {} + vim_account["datacenter"] = {} # currently assumes vim_acc - if ('vim-type' not in vim_access): - #'openstack' not in vim_access['vim-type']): + if "vim-type" not in vim_access: + #'openstack' not in vim_access['vim-type']): raise Exception("vim type not provided") - vim_account['datacenter']['name'] = name - vim_account['datacenter']['type'] = vim_access['vim-type'] + vim_account["datacenter"]["name"] = name + vim_account["datacenter"]["type"] = vim_access["vim-type"] vim_config = {} - if 'config' in vim_access and vim_access['config'] is not None: - vim_config = yaml.safe_load(vim_access['config']) + if "config" in vim_access and vim_access["config"] is not None: + vim_config = yaml.safe_load(vim_access["config"]) if vim_config: - vim_account['datacenter']['config'] = vim_config + vim_account["datacenter"]["config"] = vim_config vim_account = self.update_vim_account_dict(vim_account, vim_access, vim_config) - resp = self._ro_http.post_cmd('openmano/datacenters', vim_account) - if resp and 'error' in resp: + resp = self._ro_http.post_cmd("openmano/datacenters", vim_account) + if resp and "error" in resp: raise ClientException("failed to create vim") else: self._attach(name, vim_account) self._update_ro_accounts() - def _update_ro_accounts(self): - get_ro_accounts = self._http.get_cmd('api/operational/{}ro-account' - .format(self._client.so_rbac_project_path)) - if not get_ro_accounts or 'rw-ro-account:ro-account' not in get_ro_accounts: + get_ro_accounts = self._http.get_cmd( + "api/operational/{}ro-account".format(self._client.so_rbac_project_path) + ) + if not get_ro_accounts or "rw-ro-account:ro-account" not in get_ro_accounts: return - for account in get_ro_accounts['rw-ro-account:ro-account']['account']: - if account['ro-account-type'] == 'openmano': + for account in get_ro_accounts["rw-ro-account:ro-account"]["account"]: + if account["ro-account-type"] == "openmano": # Refresh the Account Status - refresh_body = {"input": { - "ro-account": account['name'], - "project-name": self._client._so_project - } - } - refresh_status = self._http.post_cmd('api/operations/update-ro-account-status', - refresh_body) - if refresh_status and 'error' in refresh_status: + refresh_body = { + "input": { + "ro-account": account["name"], + "project-name": self._client._so_project, + } + } + refresh_status = self._http.post_cmd( + "api/operations/update-ro-account-status", refresh_body + ) + if refresh_status and "error" in refresh_status: raise ClientException("Failed to refersh RO Account Status") - def update_vim_account_dict(self, vim_account, vim_access, vim_config): - if vim_access['vim-type'] == 'vmware': - if 'admin_username' in vim_config: - vim_account['datacenter']['admin_username'] = vim_config['admin_username'] - if 'admin_password' in vim_config: - vim_account['datacenter']['admin_password'] = vim_config['admin_password'] - if 'nsx_manager' in vim_config: - vim_account['datacenter']['nsx_manager'] = vim_config['nsx_manager'] - if 'nsx_user' in vim_config: - vim_account['datacenter']['nsx_user'] = vim_config['nsx_user'] - if 'nsx_password' in vim_config: - vim_account['datacenter']['nsx_password'] = vim_config['nsx_password'] - if 'orgname' in vim_config: - vim_account['datacenter']['orgname'] = vim_config['orgname'] - if 'vcenter_ip' in vim_config: - vim_account['datacenter']['vcenter_ip'] = vim_config['vcenter_ip'] - if 'vcenter_user' in vim_config: - vim_account['datacenter']['vcenter_user'] = vim_config['vcenter_user'] - if 'vcenter_password' in vim_config: - vim_account['datacenter']['vcenter_password'] = vim_config['vcenter_password'] - if 'vcenter_port' in vim_config: - vim_account['datacenter']['vcenter_port'] = vim_config['vcenter_port'] - vim_account['datacenter']['vim_url'] = vim_access['vim-url'] - vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url'] - vim_account['datacenter']['description'] = vim_access['description'] - vim_account['datacenter']['vim_username'] = vim_access['vim-username'] - vim_account['datacenter']['vim_password'] = vim_access['vim-password'] - vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name'] + if vim_access["vim-type"] == "vmware": + if "admin_username" in vim_config: + vim_account["datacenter"]["admin_username"] = vim_config[ + "admin_username" + ] + if "admin_password" in vim_config: + vim_account["datacenter"]["admin_password"] = vim_config[ + "admin_password" + ] + if "nsx_manager" in vim_config: + vim_account["datacenter"]["nsx_manager"] = vim_config["nsx_manager"] + if "nsx_user" in vim_config: + vim_account["datacenter"]["nsx_user"] = vim_config["nsx_user"] + if "nsx_password" in vim_config: + vim_account["datacenter"]["nsx_password"] = vim_config["nsx_password"] + if "orgname" in vim_config: + vim_account["datacenter"]["orgname"] = vim_config["orgname"] + if "vcenter_ip" in vim_config: + vim_account["datacenter"]["vcenter_ip"] = vim_config["vcenter_ip"] + if "vcenter_user" in vim_config: + vim_account["datacenter"]["vcenter_user"] = vim_config["vcenter_user"] + if "vcenter_password" in vim_config: + vim_account["datacenter"]["vcenter_password"] = vim_config[ + "vcenter_password" + ] + if "vcenter_port" in vim_config: + vim_account["datacenter"]["vcenter_port"] = vim_config["vcenter_port"] + vim_account["datacenter"]["vim_url"] = vim_access["vim-url"] + vim_account["datacenter"]["vim_url_admin"] = vim_access["vim-url"] + vim_account["datacenter"]["description"] = vim_access["description"] + vim_account["datacenter"]["vim_username"] = vim_access["vim-username"] + vim_account["datacenter"]["vim_password"] = vim_access["vim-password"] + vim_account["datacenter"]["vim_tenant_name"] = vim_access["vim-tenant-name"] else: - vim_account['datacenter']['vim_url'] = vim_access['vim-url'] - vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url'] - vim_account['datacenter']['description'] = vim_access['description'] - vim_account['datacenter']['vim_username'] = vim_access['vim-username'] - vim_account['datacenter']['vim_password'] = vim_access['vim-password'] - vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name'] + vim_account["datacenter"]["vim_url"] = vim_access["vim-url"] + vim_account["datacenter"]["vim_url_admin"] = vim_access["vim-url"] + vim_account["datacenter"]["description"] = vim_access["description"] + vim_account["datacenter"]["vim_username"] = vim_access["vim-username"] + vim_account["datacenter"]["vim_password"] = vim_access["vim-password"] + vim_account["datacenter"]["vim_tenant_name"] = vim_access["vim-tenant-name"] return vim_account def delete(self, vim_name): @@ -142,9 +151,8 @@ class Vim(object): self._detach(vim_name) # detach. continue if error, # it could be the datacenter is left without attachment - resp = self._ro_http.delete_cmd('openmano/datacenters/{}' - .format(vim_name)) - if 'result' not in resp: + resp = self._ro_http.delete_cmd("openmano/datacenters/{}".format(vim_name)) + if "result" not in resp: raise ClientException("failed to delete vim {} - {}".format(vim_name, resp)) self._update_ro_accounts() @@ -155,68 +163,79 @@ class Vim(object): # and waits a resonable amount of time for the update to finish time.sleep(2) - if self._client._so_version == 'v3': - resp = self._http.get_cmd('v1/api/operational/{}ro-account-state' - .format(self._client.so_rbac_project_path)) + if self._client._so_version == "v3": + resp = self._http.get_cmd( + "v1/api/operational/{}ro-account-state".format( + self._client.so_rbac_project_path + ) + ) datacenters = [] - if not resp or 'rw-ro-account:ro-account-state' not in resp: + if not resp or "rw-ro-account:ro-account-state" not in resp: return list() - ro_accounts = resp['rw-ro-account:ro-account-state'] - for ro_account in ro_accounts['account']: - if 'datacenters' not in ro_account: + ro_accounts = resp["rw-ro-account:ro-account-state"] + for ro_account in ro_accounts["account"]: + if "datacenters" not in ro_account: continue - if 'datacenters' not in ro_account['datacenters']: + if "datacenters" not in ro_account["datacenters"]: continue - for datacenter in ro_account['datacenters']['datacenters']: - datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid'] - if 'uuid' in datacenter else None}) + for datacenter in ro_account["datacenters"]["datacenters"]: + datacenters.append( + { + "name": datacenter["name"], + "uuid": datacenter["uuid"] + if "uuid" in datacenter + else None, + } + ) vim_accounts = datacenters return vim_accounts else: # Backwards Compatibility - resp = self._http.get_cmd('v1/api/operational/datacenters') - if not resp or 'rw-launchpad:datacenters' not in resp: + resp = self._http.get_cmd("v1/api/operational/datacenters") + if not resp or "rw-launchpad:datacenters" not in resp: return list() - - datacenters = resp['rw-launchpad:datacenters'] - + + datacenters = resp["rw-launchpad:datacenters"] + vim_accounts = list() - if 'ro-accounts' not in datacenters: + if "ro-accounts" not in datacenters: return vim_accounts - + tenant = self._get_ro_tenant() if tenant is None: return vim_accounts - - for roaccount in datacenters['ro-accounts']: - if 'datacenters' not in roaccount: + + for roaccount in datacenters["ro-accounts"]: + if "datacenters" not in roaccount: continue - for datacenter in roaccount['datacenters']: - vim_accounts.append(self._get_ro_datacenter(datacenter['name'], - tenant['uuid'])) + for datacenter in roaccount["datacenters"]: + vim_accounts.append( + self._get_ro_datacenter(datacenter["name"], tenant["uuid"]) + ) return vim_accounts - def _get_ro_tenant(self, name='osm'): - resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name)) + def _get_ro_tenant(self, name="osm"): + resp = self._ro_http.get_cmd("openmano/tenants/{}".format(name)) if not resp: return None - if 'tenant' in resp and 'uuid' in resp['tenant']: - return resp['tenant'] + if "tenant" in resp and "uuid" in resp["tenant"]: + return resp["tenant"] else: return None - def _get_ro_datacenter(self, name, tenant_uuid='any'): - resp = self._ro_http.get_cmd('openmano/{}/datacenters/{}' - .format(tenant_uuid, name)) + def _get_ro_datacenter(self, name, tenant_uuid="any"): + resp = self._ro_http.get_cmd( + "openmano/{}/datacenters/{}".format(tenant_uuid, name) + ) if not resp: raise NotFound("datacenter {} not found".format(name)) - if 'datacenter' in resp and 'uuid' in resp['datacenter']: - return resp['datacenter'] + if "datacenter" in resp and "uuid" in resp["datacenter"]: + return resp["datacenter"] else: raise NotFound("datacenter {} not found".format(name)) @@ -225,50 +244,56 @@ class Vim(object): if tenant is None: raise NotFound("no ro tenant found") - return self._get_ro_datacenter(name, tenant['uuid']) + return self._get_ro_datacenter(name, tenant["uuid"]) def get_datacenter(self, name): - if self._client._so_version == 'v3': - resp = self._http.get_cmd('v1/api/operational/{}ro-account-state' - .format(self._client.so_rbac_project_path)) + if self._client._so_version == "v3": + resp = self._http.get_cmd( + "v1/api/operational/{}ro-account-state".format( + self._client.so_rbac_project_path + ) + ) if not resp: return None, None - if not resp or 'rw-ro-account:ro-account-state' not in resp: + if not resp or "rw-ro-account:ro-account-state" not in resp: return None, None - ro_accounts = resp['rw-ro-account:ro-account-state'] - for ro_account in ro_accounts['account']: - if 'datacenters' not in ro_account: + ro_accounts = resp["rw-ro-account:ro-account-state"] + for ro_account in ro_accounts["account"]: + if "datacenters" not in ro_account: continue - if 'datacenters' not in ro_account['datacenters']: + if "datacenters" not in ro_account["datacenters"]: continue - for datacenter in ro_account['datacenters']['datacenters']: - if datacenter['name'] == name: - return datacenter, ro_account['name'] + for datacenter in ro_account["datacenters"]["datacenters"]: + if datacenter["name"] == name: + return datacenter, ro_account["name"] return None, None else: # Backwards Compatibility - resp = self._http.get_cmd('v1/api/operational/datacenters') + resp = self._http.get_cmd("v1/api/operational/datacenters") if not resp: return None - - if not resp or 'rw-launchpad:datacenters' not in resp: + + if not resp or "rw-launchpad:datacenters" not in resp: return None - if 'ro-accounts' not in resp['rw-launchpad:datacenters']: + if "ro-accounts" not in resp["rw-launchpad:datacenters"]: return None - for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']: - if 'datacenters' not in roaccount: + for roaccount in resp["rw-launchpad:datacenters"]["ro-accounts"]: + if "datacenters" not in roaccount: continue - for datacenter in roaccount['datacenters']: - if datacenter['name'] == name: + for datacenter in roaccount["datacenters"]: + if datacenter["name"] == name: return datacenter return None def get_resource_orchestrator(self): - resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator' - .format(self._client.so_rbac_project_path)) + resp = self._http.get_cmd( + "v1/api/operational/{}resource-orchestrator".format( + self._client.so_rbac_project_path + ) + ) - if not resp or 'rw-launchpad:resource-orchestrator' not in resp: + if not resp or "rw-launchpad:resource-orchestrator" not in resp: return None - return resp['rw-launchpad:resource-orchestrator'] + return resp["rw-launchpad:resource-orchestrator"] diff --git a/osmclient/v1/vnf.py b/osmclient/v1/vnf.py index 46ff3af..5db0240 100644 --- a/osmclient/v1/vnf.py +++ b/osmclient/v1/vnf.py @@ -27,23 +27,26 @@ class Vnf(object): self._client = client def list(self): - resp = self._http.get_cmd('v1/api/operational/{}vnfr-catalog/vnfr' - .format(self._client.so_rbac_project_path)) - if resp and 'vnfr:vnfr' in resp: - return resp['vnfr:vnfr'] + resp = self._http.get_cmd( + "v1/api/operational/{}vnfr-catalog/vnfr".format( + self._client.so_rbac_project_path + ) + ) + if resp and "vnfr:vnfr" in resp: + return resp["vnfr:vnfr"] return list() def get(self, vnf_name): vnfs = self.list() for vnf in vnfs: - if vnf_name == vnf['name']: + if vnf_name == vnf["name"]: return vnf - if vnf_name == vnf['id']: + if vnf_name == vnf["id"]: return vnf raise NotFound("vnf {} not found".format(vnf_name)) def get_monitoring(self, vnf_name): vnf = self.get(vnf_name) - if vnf and 'monitoring-param' in vnf: - return vnf['monitoring-param'] + if vnf and "monitoring-param" in vnf: + return vnf["monitoring-param"] return None diff --git a/osmclient/v1/vnfd.py b/osmclient/v1/vnfd.py index dd3b117..e43475d 100644 --- a/osmclient/v1/vnfd.py +++ b/osmclient/v1/vnfd.py @@ -23,34 +23,37 @@ from osmclient.common.exceptions import ClientException class Vnfd(object): - def __init__(self, http=None, client=None): self._http = http self._client = client def list(self): - resp = self._http.get_cmd('api/running/{}vnfd-catalog/vnfd' - .format(self._client.so_rbac_project_path)) + resp = self._http.get_cmd( + "api/running/{}vnfd-catalog/vnfd".format(self._client.so_rbac_project_path) + ) - if self._client._so_version == 'v3': - if resp and 'project-vnfd:vnfd' in resp: - return resp['project-vnfd:vnfd'] + if self._client._so_version == "v3": + if resp and "project-vnfd:vnfd" in resp: + return resp["project-vnfd:vnfd"] else: # Backwards Compatibility - if resp and 'vnfd:vnfd' in resp: - return resp['vnfd:vnfd'] - + if resp and "vnfd:vnfd" in resp: + return resp["vnfd:vnfd"] + return list() def get(self, name): for vnfd in self.list(): - if name == vnfd['name']: + if name == vnfd["name"]: return vnfd raise NotFound("vnfd {} not found".format(name)) def delete(self, vnfd_name): vnfd = self.get(vnfd_name) - resp = self._http.delete_cmd('api/running/{}vnfd-catalog/vnfd/{}' - .format(self._client.so_rbac_project_path, vnfd['id'])) - if 'success' not in resp: + resp = self._http.delete_cmd( + "api/running/{}vnfd-catalog/vnfd/{}".format( + self._client.so_rbac_project_path, vnfd["id"] + ) + ) + if "success" not in resp: raise ClientException("failed to delete vnfd {}".format(vnfd_name)) diff --git a/setup.py b/setup.py index 22b5a54..e9b09bd 100644 --- a/setup.py +++ b/setup.py @@ -14,29 +14,39 @@ # under the License. from setuptools import setup, find_packages -_description = 'OSM client library and console script' +_description = "OSM client library and console script" setup( - name='osmclient', - version_command=('git describe --match v* --tags --long --dirty', - 'pep440-git-full'), - author='ETSI', + name="osmclient", + version_command=( + "git describe --match v* --tags --long --dirty", + "pep440-git-full", + ), + author="ETSI", packages=find_packages(), include_package_data=True, - maintainer='Gerardo Garcia', - maintainer_email='gerardo.garciadeblas@telefonica.com', + maintainer="Gerardo Garcia", + maintainer_email="gerardo.garciadeblas@telefonica.com", description=_description, - license='Apache 2', + license="Apache 2", install_requires=[ - 'Click', 'prettytable', 'pyyaml==5.3.1', 'pycurl', 'python-magic', - 'jinja2==2.11.2', 'osm-im', 'verboselogs', 'packaging', - 'requests==2.24.0', 'charmcraft', + "Click", + "prettytable", + "pyyaml==5.3.1", + "pycurl", + "python-magic", + "jinja2==2.11.2", + "osm-im", + "verboselogs", + "packaging", + "requests==2.24.0", + "charmcraft", ], - setup_requires=['setuptools-version-command'], - test_suite='nose.collector', + setup_requires=["setuptools-version-command"], + test_suite="nose.collector", entry_points={ - 'console_scripts': [ - 'osm = osmclient.scripts.osm:cli', + "console_scripts": [ + "osm = osmclient.scripts.osm:cli", ], }, ) -- 2.17.1