SDN Accounts refactoring
[osm/SO.git] / common / python / rift / mano / sdn / accounts.py
diff --git a/common/python/rift/mano/sdn/accounts.py b/common/python/rift/mano/sdn/accounts.py
new file mode 100644 (file)
index 0000000..d539ead
--- /dev/null
@@ -0,0 +1,157 @@
+
+# 
+#   Copyright 2017 RIFT.IO Inc
+#
+#   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.
+#
+
+import sys
+import asyncio
+from gi import require_version
+require_version('RwTypes', '1.0')
+require_version('RwsdnalYang', '1.0')
+require_version('RwSdnYang', '1.0')
+
+from gi.repository import (
+        RwTypes,
+        RwsdnalYang,
+        RwSdnYang,
+        )
+import rw_peas
+
+if sys.version_info < (3, 4, 4):
+    asyncio.ensure_future = asyncio.async
+
+
+class PluginLoadingError(Exception):
+    pass
+
+
+class SDNAccountCalError(Exception):
+    pass
+
+
+class SDNAccount(object):
+    def __init__(self, log, rwlog_hdl, account_msg):
+        self._log = log
+        self._account_msg = account_msg.deep_copy()
+
+        self._sdn_plugin = None
+        self._engine = None
+
+        self._sdn = self.plugin.get_interface("Topology")
+        self._sdn.init(rwlog_hdl)
+
+        self._status = RwsdnalYang.SDNAccount_ConnectionStatus(
+                status="unknown",
+                details="Connection status lookup not started"
+                )
+
+        self._validate_task = None
+
+    @property
+    def plugin(self):
+        if self._sdn_plugin is None:
+            try:
+                self._sdn_plugin = rw_peas.PeasPlugin(
+                        getattr(self._account_msg, self.account_type).plugin_name,
+                        'RwSdn-1.0',
+                        )
+
+            except AttributeError as e:
+                raise PluginLoadingError(str(e))
+
+            self._engine, _, _ = self._sdn_plugin()
+
+        return self._sdn_plugin
+
+    def _wrap_status_fn(self, fn, *args, **kwargs):
+        ret = fn(*args, **kwargs)
+        rw_status = ret[0]
+        if rw_status != RwTypes.RwStatus.SUCCESS:
+            msg = "%s returned %s" % (fn.__name__, str(rw_status))
+            self._log.error(msg)
+            raise SDNAccountCalError(msg)
+
+        # If there was only one other return value besides rw_status, then just
+        # return that element.  Otherwise return the rest of the return values
+        # as a list.
+        return ret[1] if len(ret) == 2 else ret[1:]
+
+    @property
+    def sdn(self):
+        return self._sdn
+
+    @property
+    def name(self):
+        return self._account_msg.name
+
+    @property
+    def account_msg(self):
+        return self._account_msg
+
+    @property
+    def sdnal_account_msg(self):
+        return RwsdnalYang.SDNAccount.from_dict(
+                self.account_msg.as_dict(),
+                ignore_missing_keys=True,
+                )
+
+    def sdn_account_msg(self, account_dict):
+        self._account_msg = RwSdnYang.SDNAccount.from_dict(account_dict)
+
+    @property
+    def account_type(self):
+        return self._account_msg.account_type
+
+    @property
+    def connection_status(self):
+        return self._status
+
+    def update_from_cfg(self, cfg):
+        self._log.debug("Updating parent SDN Account to %s", cfg)
+
+        raise NotImplementedError("Update SDN account not yet supported")
+
+
+    @asyncio.coroutine
+    def validate_sdn_account_credentials(self, loop):
+        self._log.debug("Validating SDN Account credentials %s", self._account_msg)
+        self._status = RwSdnYang.SDNAccount_ConnectionStatus(
+                status="validating",
+                details="SDN account connection validation in progress"
+                )
+        rwstatus, status = yield from loop.run_in_executor(
+                None,
+                self._sdn.validate_sdn_creds,
+                self.sdnal_account_msg,
+                )
+        if rwstatus == RwTypes.RwStatus.SUCCESS:
+            self._status = RwSdnYang.SDNAccount_ConnectionStatus.from_dict(status.as_dict())
+        else:
+            self._status = RwSdnYang.SDNAccount_ConnectionStatus(
+                    status="failure",
+                    details="Error when calling SDNAL validate SDN creds"
+                    )
+
+        self._log.info("Got SDN account validation response: %s", self._status)
+
+    def start_validate_credentials(self, loop):
+        if self._validate_task is not None:
+            self._validate_task.cancel()
+            self._validate_task = None
+
+        self._validate_task = asyncio.ensure_future(
+                self.validate_sdn_account_credentials(loop),
+                loop=loop
+                )