Standardize Formatting 33/10533/1
authorbeierlm <mark.beierl@canonical.com>
Tue, 23 Mar 2021 20:26:45 +0000 (16:26 -0400)
committerbeierlm <mark.beierl@canonical.com>
Tue, 23 Mar 2021 20:26:45 +0000 (16:26 -0400)
Nothing but whitespace change.  Reformatted using Black.

Change-Id: I1afd579ede0dd49f2d104d4f4bc470a4ac8cbba8
Signed-off-by: beierlm <mark.beierl@canonical.com>
42 files changed:
osmclient/client.py
osmclient/common/http.py
osmclient/common/package_tool.py
osmclient/common/test/test_utils.py
osmclient/common/utils.py
osmclient/common/wait.py
osmclient/scripts/osm.py
osmclient/sol005/client.py
osmclient/sol005/http.py
osmclient/sol005/k8scluster.py
osmclient/sol005/ns.py
osmclient/sol005/nsd.py
osmclient/sol005/nsi.py
osmclient/sol005/nst.py
osmclient/sol005/osmrepo.py
osmclient/sol005/package.py
osmclient/sol005/pdud.py
osmclient/sol005/project.py
osmclient/sol005/repo.py
osmclient/sol005/role.py
osmclient/sol005/sdncontroller.py
osmclient/sol005/user.py
osmclient/sol005/vim.py
osmclient/sol005/vnf.py
osmclient/sol005/vnfd.py
osmclient/sol005/wim.py
osmclient/v1/client.py
osmclient/v1/key.py
osmclient/v1/ns.py
osmclient/v1/nsd.py
osmclient/v1/package.py
osmclient/v1/tests/test_ns.py
osmclient/v1/tests/test_nsd.py
osmclient/v1/tests/test_package.py
osmclient/v1/tests/test_vnf.py
osmclient/v1/tests/test_vnfd.py
osmclient/v1/utils.py
osmclient/v1/vca.py
osmclient/v1/vim.py
osmclient/v1/vnf.py
osmclient/v1/vnfd.py
setup.py

index 56570b4..fe64f1c 100644 (file)
@@ -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:
index b67b594..fa5eae7 100644 (file)
@@ -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
index 473ff3d..e3dbd1a 100644 (file)
@@ -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:
index 7134662..5ba03f4 100644 (file)
@@ -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
+        )
index 94bd72f..aed7d29 100644 (file)
@@ -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()
index bb9a82a..d3f673c 100644 (file)
@@ -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)
index c434fe8..603d373 100755 (executable)
@@ -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=<VENDOR>&nsd-ref=<NSD_NAME>
        --filter  nsd.constituent-vnfd.vnfd-id-ref=<VNFD_NAME>
     """
+
     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=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>'+
-                   '[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_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=<NAME>,mgmt=<true|false>,ip-address=<IP_ADDRESS>"
+    + "[,type=<overlay|underlay>][,mac-address=<MAC_ADDRESS>][,vim-network-name=<VIM_NET_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()
-
index 00c50cb..495c425 100644 (file)
@@ -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)
index 9a7bc6e..4234fc8 100644 (file)
@@ -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()
index 4ac2e48..0b99a37 100644 (file)
@@ -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))
-
index b551868..d457cbd 100644 (file)
@@ -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))
-
index 59c6d29..7c29252 100644 (file)
@@ -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)
index 20065b7..999959e 100644 (file)
@@ -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)
-
index 214a79d..19092b2 100644 (file)
@@ -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)
-
index aa2a5f0..6ccc061 100644 (file)
@@ -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
+                )
index 622fb86..1fa0e24 100644 (file)
@@ -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:
index aa4bf69..df5bad1 100644 (file)
@@ -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)
-
index ed781fa..3658772 100644 (file)
@@ -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))
-
index cc82402..6e6e927 100644 (file)
@@ -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))
-
index 2544a7b..46158d7 100644 (file)
@@ -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))
-
index 5b85ef4..3d4b7f7 100644 (file)
@@ -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))
-
index d28514e..d6c1e16 100644 (file)
@@ -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))
-
index fa17dfc..f2a11e6 100644 (file)
@@ -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))
-
index edae358..f7c20d9 100644 (file)
@@ -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:
index e32ac83..4542d56 100644 (file)
@@ -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)
index 5da3941..2466113 100644 (file)
@@ -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))
-
index ba765e1..cad9c94 100644 (file)
@@ -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"
index a0dcef9..4e51b78 100644 (file)
@@ -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()
index e6b747f..5006c1f 100644 (file)
@@ -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
index 52c5772..527a45f 100644 (file)
@@ -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))
index b7a2d97..f1a4bf4 100644 (file)
@@ -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")
index 19fc58f..616b8a4 100644 (file)
@@ -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",
+        )
index b0b5492..6f0255e 100644 (file)
@@ -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")
index 5211b12..2f0362c 100644 (file)
@@ -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"
+        )
index 69aca68..40b4648 100644 (file)
@@ -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"
+        )
index cd98888..f069742 100644 (file)
@@ -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")
index f4baef8..092f193 100644 (file)
@@ -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()
index adac986..d2f17c6 100644 (file)
@@ -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))
index 849f6dc..35266aa 100644 (file)
@@ -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"]
index 46ff3af..5db0240 100644 (file)
@@ -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
index dd3b117..e43475d 100644 (file)
@@ -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))
index 22b5a54..e9b09bd 100644 (file)
--- a/setup.py
+++ b/setup.py
 #    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",
         ],
     },
 )