Change in vdsm[master]: api: Move DynamicBridge to vdsmapi schema processing

agl at us.ibm.com agl at us.ibm.com
Fri Feb 15 19:15:45 UTC 2013


Adam Litke has uploaded a new change for review.

Change subject: api: Move DynamicBridge to vdsmapi schema processing
......................................................................

api: Move DynamicBridge to vdsmapi schema processing

Signed-off-by: Adam Litke <agl at us.ibm.com>
Change-Id: I0bbcc2475a40749c959eade157f6030b2c2f5e71
---
M tests/apiTests.py
M vdsm/clientIF.py
M vdsm_api/Bridge.py
M vdsm_api/jsonrpc/__init__.py
4 files changed, 29 insertions(+), 59 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/07/12107/1

diff --git a/tests/apiTests.py b/tests/apiTests.py
index 7ad8a1f..5275391 100644
--- a/tests/apiTests.py
+++ b/tests/apiTests.py
@@ -27,7 +27,6 @@
 from contextlib import closing
 
 from testrunner import VdsmTestCase as TestCaseBase
-from vdsm import constants
 import BindingJsonRpc
 import jsonrpc
 import apiData
@@ -110,21 +109,6 @@
     sys.modules['API'] = _newAPI
 
 
-def findSchema():
-    """
-    Find the API schema file whether we are running tests from the source dir
-    or from the tests install location
-    """
-    scriptdir = os.path.dirname(__file__)
-    localpath = os.path.join(scriptdir, '../vdsm_api/vdsmapi-schema.json')
-    installedpath = os.path.join(constants.P_VDSM, 'vdsmapi-schema.json')
-    for f in localpath, installedpath:
-        if os.access(f, os.R_OK):
-            return f
-    raise Exception("Unable to find schema in %s or %s",
-                    localpath, installedpath)
-
-
 def setUpModule():
     """
     Set up the environment for all tests:
@@ -140,12 +124,11 @@
     handler.setLevel(logging.INFO)
     log.addHandler(handler)
 
-    schema = findSchema()
     createFakeAPI()
 
     # Bridge imports the API module so we must set up the fake API first
     import Bridge
-    bridge = Bridge.DynamicBridge(schema)
+    bridge = Bridge.DynamicBridge()
 
     # Support parallel testing.  Try hard to find an open port to use
     port = getFreePort()
diff --git a/vdsm/clientIF.py b/vdsm/clientIF.py
index 841e962..ef9a19b 100644
--- a/vdsm/clientIF.py
+++ b/vdsm/clientIF.py
@@ -153,11 +153,10 @@
     def _loadBindingJsonRpc(self):
         from BindingJsonRpc import BindingJsonRpc
         from Bridge import DynamicBridge
-        schema = os.path.join(constants.P_VDSM, 'vdsmapi-schema.json')
         ip = self._getServerIP(config.get('addresses', 'management_ip'))
         port = config.getint('addresses', 'json_port')
         conf = [('tcp', {"ip": ip, "port": port})]
-        self.bindings['json'] = BindingJsonRpc(DynamicBridge(schema), conf)
+        self.bindings['json'] = BindingJsonRpc(DynamicBridge(), conf)
 
     def _prepareBindings(self):
         self.bindings = {}
diff --git a/vdsm_api/Bridge.py b/vdsm_api/Bridge.py
index 8fade0f..cc3f227 100644
--- a/vdsm_api/Bridge.py
+++ b/vdsm_api/Bridge.py
@@ -29,8 +29,8 @@
 
 
 class DynamicBridge(object):
-    def __init__(self, schema):
-        self._parseSchema(schema)
+    def __init__(self):
+        self.api = vdsmapi.get_api()
 
     def dispatch(self, name, argobj):
         methodName = name.replace('.', '_')
@@ -60,30 +60,13 @@
         except KeyError:
             raise VdsmError(5, "Response is missing '%s' member" % member)
 
-    def _parseSchema(self, schema):
-        self.commands = {}
-        self.classes = {}
-        self.types = {}
-        with open(schema) as f:
-            symbols = vdsmapi.parse_schema(f)
-            for s in symbols:
-                if 'command' in s:
-                    key = "%s_%s" % (s['command']['class'],
-                                     s['command']['name'])
-                    self.commands[key] = s
-                elif 'class' in s:
-                    cls = s['class']
-                    self.classes[cls] = s
-                elif 'type' in s:
-                    t = s['type']
-                    self.types[t] = s
-
     def __getattr__(self, attr):
-        if attr in self.commands:
+        try:
             className, methodName = attr.split('_')
-            return partial(self._dynamicMethod, className, methodName)
-        else:
+            self.api['commands'][className][methodName]
+        except (KeyError, ValueError):
             raise AttributeError("Attribute not found '%s'" % attr)
+        return partial(self._dynamicMethod, className, methodName)
 
     def _convertClassName(self, name):
         """
@@ -97,7 +80,7 @@
         except KeyError:
             return name
 
-    def _getMethodArgs(self, className, cmd, argObj):
+    def _getMethodArgs(self, className, methodName, argObj):
         """
         An internal API call currently looks like:
 
@@ -109,10 +92,11 @@
         them from here.  For any given method, the method_args are obtained by
         chopping off the ctor_args from the beginning of argObj.
         """
-        className = self._convertClassName(className)
         # Get the full argument list
-        allArgs = self.commands[cmd].get('data', {}).keys()
+        sym = self.api['commands'][className][methodName]
+        allArgs = sym.get('data', {}).keys()
 
+        className = self._convertClassName(className)
         # Get the list of ctor_args
         ctorArgs = getattr(API, className).ctorArgs
 
@@ -149,7 +133,7 @@
         symName = self._symNameFilter(symName)
 
         try:
-            symbol = self.types[symTypeName]
+            symbol = self.api['types'][symTypeName]
         except KeyError:
             return
 
@@ -167,16 +151,17 @@
                 if k in item:
                     self._typeFixup(k, v, item[k])
 
-    def _fixupArgs(self, cmd, args):
-        argInfo = zip(self.commands[cmd].get('data', {}).items(), args)
+    def _fixupArgs(self, className, methodName, args):
+        argDef = self.api['commands'][className][methodName].get('data', {})
+        argInfo = zip(argDef.items(), args)
         for typeInfo, val in argInfo:
             argName, argType = typeInfo
-            if argType not in self.types:
+            if argType not in self.api['types']:
                 continue
             self._typeFixup(argName, argType, val)
 
-    def _fixupRet(self, cmd, result):
-        retType = self.commands[cmd].get('returns', None)
+    def _fixupRet(self, className, methodName, result):
+        retType = self.api['commands'][className][methodName].get('returns')
         if retType is not None:
             self._typeFixup('return', retType, result)
         return result
@@ -189,17 +174,19 @@
 
         return kwargs
 
-    def _getArgList(self, cmd):
-        return self.commands[cmd].get('data', {}).keys()
+    def _getArgList(self, className, methodName):
+        sym = self.api['commands'][className][methodName]
+        return sym.get('data', {}).keys()
 
     def _dynamicMethod(self, className, methodName, *args, **kwargs):
-        cmd = '%s_%s' % (className, methodName)
-        argobj = self._nameArgs(args, kwargs, self._getArgList(cmd))
+        argobj = self._nameArgs(args, kwargs,
+                                self._getArgList(className, methodName))
         api = self._getApiInstance(className, argobj)
-        methodArgs = self._getMethodArgs(className, cmd, argobj)
-        self._fixupArgs(cmd, methodArgs)
+        methodArgs = self._getMethodArgs(className, methodName, argobj)
+        self._fixupArgs(className, methodName, methodArgs)
 
         # Call the override function (if given).  Otherwise, just call directly
+        cmd = '%s_%s' % (className, methodName)
         fn = command_info.get(cmd, {}).get('call')
         if fn:
             result = fn(api, argobj)
@@ -217,7 +204,7 @@
             ret = retfield(result)
         else:
             ret = self._getResult(result, retfield)
-        return self._fixupRet(cmd, ret)
+        return self._fixupRet(className, methodName, ret)
 
 
 def Host_getStorageRepoStats_Ret(ret):
diff --git a/vdsm_api/jsonrpc/__init__.py b/vdsm_api/jsonrpc/__init__.py
index 49e8788..03cbf2e 100644
--- a/vdsm_api/jsonrpc/__init__.py
+++ b/vdsm_api/jsonrpc/__init__.py
@@ -226,6 +226,7 @@
             except JsonRpcError as e:
                 ctx.sendReply(None, e)
             except Exception as e:
+                self.log.error("Unexpected exception", exc_info=True)
                 ctx.sendReply(None, JsonRpcInternalError(str(e)))
             else:
                 return ctx.sendReply(res, None)


--
To view, visit http://gerrit.ovirt.org/12107
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0bbcc2475a40749c959eade157f6030b2c2f5e71
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <agl at us.ibm.com>


More information about the vdsm-patches mailing list