Add unittest for uploading file via RPC
authorMichael Hanselmann <hansmi@google.com>
Thu, 5 Jan 2012 20:12:24 +0000 (21:12 +0100)
committerMichael Hanselmann <hansmi@google.com>
Fri, 6 Jan 2012 11:34:47 +0000 (12:34 +0100)
After some preparing patches this unittest can finally be added.

Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>

lib/rpc.py
test/ganeti.rpc_unittest.py
test/mocks.py

index 954beb7..c9ac36f 100644 (file)
@@ -516,13 +516,19 @@ def _EncodeNodeToDiskDict(value):
               for name, disks in value.items())
 
 
-def _PrepareFileUpload(filename):
+def _PrepareFileUpload(getents_fn, filename):
   """Loads a file and prepares it for an upload to nodes.
 
   """
+  # TODO: Use ReadFile(preread=...) and os.fstat
   data = _Compress(utils.ReadFile(filename))
   st = os.stat(filename)
-  getents = runtime.GetEnts()
+
+  if getents_fn is None:
+    getents_fn = runtime.GetEnts
+
+  getents = getents_fn()
+
   return [filename, data, st.st_mode, getents.LookupUid(st.st_uid),
           getents.LookupGid(st.st_gid), st.st_atime, st.st_mtime]
 
@@ -569,7 +575,6 @@ _ENCODERS = {
   rpc_defs.ED_OBJECT_DICT: _ObjectToDict,
   rpc_defs.ED_OBJECT_DICT_LIST: _ObjectListToDict,
   rpc_defs.ED_NODE_TO_DISK_DICT: _EncodeNodeToDiskDict,
-  rpc_defs.ED_FILE_DETAILS: _PrepareFileUpload,
   rpc_defs.ED_COMPRESS: _Compress,
   rpc_defs.ED_FINALIZE_EXPORT_DISKS: _PrepareFinalizeExportDisks,
   rpc_defs.ED_IMPEXP_IO: _EncodeImportExportIO,
@@ -597,11 +602,14 @@ class RpcRunner(_RpcClientBase,
 
     encoders = _ENCODERS.copy()
 
-    # Add encoders requiring configuration object
     encoders.update({
+      # Encoders requiring configuration object
       rpc_defs.ED_INST_DICT: self._InstDict,
       rpc_defs.ED_INST_DICT_HVP_BEP: self._InstDictHvpBep,
       rpc_defs.ED_INST_DICT_OSP: self._InstDictOsp,
+
+      # Encoders with special requirements
+      rpc_defs.ED_FILE_DETAILS: compat.partial(_PrepareFileUpload, _getents),
       })
 
     # Resolver using configuration
index a9349a6..691c99c 100755 (executable)
@@ -25,6 +25,7 @@ import os
 import sys
 import unittest
 import random
+import tempfile
 
 from ganeti import constants
 from ganeti import compat
@@ -37,6 +38,7 @@ from ganeti import objects
 from ganeti import backend
 
 import testutils
+import mocks
 
 
 class _FakeRequestProcessor:
@@ -682,9 +684,50 @@ class TestRpcClientBase(unittest.TestCase):
         self.assertFalse(res.fail_msg)
 
 
+class _FakeConfigForRpcRunner:
+  GetAllNodesInfo = NotImplemented
+
+  def GetNodeInfo(self, name):
+    return objects.Node(name=name)
+
+
 class TestRpcRunner(unittest.TestCase):
   def testUploadFile(self):
-    runner = rpc.RpcRunner(_req_process_fn=http_proc)
+    data = 1779 * "Hello World\n"
+
+    tmpfile = tempfile.NamedTemporaryFile()
+    tmpfile.write(data)
+    tmpfile.flush()
+    st = os.stat(tmpfile.name)
+
+    def _VerifyRequest(req):
+      (uldata, ) = serializer.LoadJson(req.post_data)
+      self.assertEqual(len(uldata), 7)
+      self.assertEqual(uldata[0], tmpfile.name)
+      self.assertEqual(list(uldata[1]), list(rpc._Compress(data)))
+      self.assertEqual(uldata[2], st.st_mode)
+      self.assertEqual(uldata[3], "user%s" % os.getuid())
+      self.assertEqual(uldata[4], "group%s" % os.getgid())
+      self.assertEqual(uldata[5], st.st_atime)
+      self.assertEqual(uldata[6], st.st_mtime)
+
+      req.success = True
+      req.resp_status_code = http.HTTP_OK
+      req.resp_body = serializer.DumpJson((True, None))
+
+    http_proc = _FakeRequestProcessor(_VerifyRequest)
+    cfg = _FakeConfigForRpcRunner()
+    runner = rpc.RpcRunner(cfg, None, _req_process_fn=http_proc,
+                           _getents=mocks.FakeGetentResolver)
+
+    nodes = [
+      "node1.example.com",
+      ]
+
+    result = runner.call_upload_file(nodes, tmpfile.name)
+    self.assertEqual(len(result), len(nodes))
+    for (idx, (node, res)) in enumerate(result.items()):
+      self.assertFalse(res.fail_msg)
 
 
 if __name__ == "__main__":
index 61eafbc..3d5d68c 100644 (file)
@@ -109,3 +109,9 @@ class FakeGetentResolver:
 
     self.daemons_gid = gid
     self.admin_gid = gid
+
+  def LookupUid(self, uid):
+    return "user%s" % uid
+
+  def LookupGid(self, gid):
+    return "group%s" % gid