Revert "Remove v1 version of osmclient which was used with old NBI (pre-Release FOUR)"
[osm/osmclient.git] / osmclient / v1 / ns.py
diff --git a/osmclient/v1/ns.py b/osmclient/v1/ns.py
new file mode 100644 (file)
index 0000000..5006c1f
--- /dev/null
@@ -0,0 +1,230 @@
+# Copyright 2017 Sandvine
+#
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+"""
+OSM ns API handling
+"""
+
+from osmclient.common import utils
+from osmclient.common.exceptions import ClientException
+from osmclient.common.exceptions import NotFound
+import uuid
+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:
+            return list()
+
+        if "nsr" not in resp["nsr:ns-instance-config"]:
+            return list()
+
+        return resp["nsr:ns-instance-config"]["nsr"]
+
+    def get(self, name):
+        """Returns an ns based on name"""
+        for ns in self.list():
+            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()
+        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:
+            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",
+    ):
+        postdata = {}
+        postdata["nsr"] = list()
+        nsr = {}
+        nsr["id"] = str(uuid.uuid1())
+
+        nsd = self._client.nsd.get(nsd_name)
+
+        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
+                    )
+                )
+        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":
+            # New format for V3
+            nsr["resource-orchestrator"] = resource_orchestrator
+            nsr["datacenter"] = datacenter["name"]
+        else:
+            # Backwards Compatiility
+            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})
+
+            nsr["ssh-authorized-key"] = ssh_keys_format
+
+        ns_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"]:
+                # now find this network
+                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"
+                        ]
+
+        postdata["nsr"].append(nsr)
+
+        resp = self._http.post_cmd(
+            "api/config/{}ns-instance-config/nsr".format(
+                self._client.so_rbac_project_path
+            ),
+            postdata,
+        )
+
+        if "success" not in resp:
+            raise ClientException(
+                "failed to create ns: {} nsd: {} result: {}".format(
+                    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
+            )
+        )
+
+    def get_field(self, ns_name, field):
+        nsr = self.get(ns_name)
+        if nsr is None:
+            raise NotFound("failed to retrieve ns {}".format(ns_name))
+
+        if field in nsr:
+            return nsr[field]
+
+        nsopdata = self.get_opdata(nsr["id"])
+
+        if field in nsopdata["nsr:nsr"]:
+            return nsopdata["nsr:nsr"][field]
+
+        raise NotFound("failed to find {} in ns {}".format(field, ns_name))
+
+    def _terminate(self, ns_name):
+        ns = self.get(ns_name)
+        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"]
+            )
+        )
+
+    def delete(self, ns_name, wait=True):
+        vnfs = self.get_field(ns_name, "constituent-vnfr-ref")
+
+        resp = self._terminate(ns_name)
+        if "success" not in resp:
+            raise ClientException("failed to delete ns {}".format(ns_name))
+
+        # helper method to check if pkg exists
+        def check_not_exists(func):
+            try:
+                func()
+                return False
+            except NotFound:
+                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))
+        ):
+            raise ClientException("ns {} failed to delete".format(ns_name))
+
+    def get_monitoring(self, ns_name):
+        ns = self.get(ns_name)
+        mon_list = {}
+        if ns is None:
+            return mon_list
+
+        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"]
+
+        return mon_list