Interdiff:
---
 lib/cmdlib.py                            |   15 +------
 lib/masterd/instance.py                  |   61 ++++++++++++++++++++++++++++++
 test/ganeti.masterd.instance_unittest.py |   35 ++++++++++++++++-
 3 files changed, 98 insertions(+), 13 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index ed0a8ee..f3e065c 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -9030,18 +9030,9 @@ class LUExportInstance(LogicalUnit):
       # Verify target information
       for idx, disk_data in enumerate(self.op.target_node):
         try:
-          (host, port, hmac_digest, hmac_salt) = disk_data
-        except (TypeError, ValueError), err:
-          raise errors.OpPrereqError("Invalid data for disk %s: %s" %
-                                     (idx, err))
-
-        if not (host and port):
-          raise errors.OpPrereqError("Disk %s is missing destination host or"
-                                     " port")
-
-        if not utils.VerifySha1Hmac(cds, "%s:%s:%s" % (idx, host, port),
-                                    hmac_digest, salt=hmac_salt):
-          raise errors.OpPrereqError("HMAC for disk %s is wrong" % idx,
+          masterd.instance.CheckRemoteExportDiskInfo(cds, idx, disk_data)
+        except errors.GenericError, err:
+          raise errors.OpPrereqError("Target info for disk %s: %s" % (idx, 
err),
                                      errors.ECODE_INVAL)
 
     else:
diff --git a/lib/masterd/instance.py b/lib/masterd/instance.py
index a53b3ff..5e24edf 100644
--- a/lib/masterd/instance.py
+++ b/lib/masterd/instance.py
@@ -1234,3 +1234,64 @@ def CheckRemoteExportHandshake(cds, handshake):
             (constants.RIE_VERSION, version))
 
   return None
+
+
+def _GetRieDiskInfoMessage(disk_index, host, port):
+  """Returns the hashed text for import/export disk information.
+
+  @type disk_index: number
+  @param disk_index: Index of disk (included in hash)
+  @type host: string
+  @param host: Hostname
+  @type port: number
+  @param port: Daemon port
+
+  """
+  return "%s:%s:%s" % (disk_index, host, port)
+
+
+def CheckRemoteExportDiskInfo(cds, disk_index, disk_info):
+  """Verifies received disk information for an export.
+
+  @type cds: string
+  @param cds: Cluster domain secret
+  @type disk_index: number
+  @param disk_index: Index of disk (included in hash)
+  @type disk_info: sequence
+  @param disk_info: Disk information sent by remote peer
+
+  """
+  try:
+    (host, port, hmac_digest, hmac_salt) = disk_info
+  except (TypeError, ValueError), err:
+    raise errors.GenericError("Invalid data: %s" % err)
+
+  if not (host and port):
+    raise errors.GenericError("Missing destination host or port")
+
+  msg = _GetRieDiskInfoMessage(disk_index, host, port)
+
+  if not utils.VerifySha1Hmac(cds, msg, hmac_digest, salt=hmac_salt):
+    raise errors.GenericError("HMAC is wrong")
+
+  return (host, port)
+
+
+def ComputeRemoteImportDiskInfo(cds, salt, disk_index, host, port):
+  """Computes the signed disk information for a remote import.
+
+  @type cds: string
+  @param cds: Cluster domain secret
+  @type salt: string
+  @param salt: HMAC salt
+  @type disk_index: number
+  @param disk_index: Index of disk (included in hash)
+  @type host: string
+  @param host: Hostname
+  @type port: number
+  @param port: Daemon port
+
+  """
+  msg = _GetRieDiskInfoMessage(disk_index, host, port)
+  hmac_digest = utils.Sha1Hmac(cds, msg, salt=salt)
+  return (host, port, hmac_digest, salt)
diff --git a/test/ganeti.masterd.instance_unittest.py 
b/test/ganeti.masterd.instance_unittest.py
index 0c74def..06228b3 100755
--- a/test/ganeti.masterd.instance_unittest.py
+++ b/test/ganeti.masterd.instance_unittest.py
@@ -26,12 +26,14 @@ import sys
 import unittest
 
 from ganeti import constants
+from ganeti import errors
 from ganeti import utils
 from ganeti import masterd
 
 from ganeti.masterd.instance import \
   ImportExportTimeouts, _TimeoutExpired, _DiskImportExportBase, \
-  ComputeRemoteExportHandshake, CheckRemoteExportHandshake
+  ComputeRemoteExportHandshake, CheckRemoteExportHandshake, \
+  ComputeRemoteImportDiskInfo, CheckRemoteExportDiskInfo
 
 import testutils
 
@@ -86,5 +88,36 @@ class TestRieHandshake(unittest.TestCase):
     self.assert_(CheckRemoteExportHandshake(cds, hs))
 
 
+class TestRieDiskInfo(unittest.TestCase):
+  def test(self):
+    cds = "bbf46ea9a"
+    salt = "ee5ad9"
+    di = ComputeRemoteImportDiskInfo(cds, salt, 0, "node1", 1234)
+    self.assertEqual(CheckRemoteExportDiskInfo(cds, 0, di),
+                     ("node1", 1234))
+
+    for i in range(1, 100):
+      # Wrong disk index
+      self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
+                        cds, i, di)
+
+  def testCheckErrors(self):
+    cds = "0776450535a"
+    self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
+                      cds, 0, "")
+    self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
+                      cds, 0, ())
+    self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
+                      cds, 0, ("", 1, 2, 3, 4, 5))
+
+    # No host/port
+    self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
+                      cds, 0, ("", 0, "", ""))
+
+    # Wrong hash
+    self.assertRaises(errors.GenericError, CheckRemoteExportDiskInfo,
+                      cds, 0, ("nodeX", 123, "fakehash", "xyz"))
+
+
 if __name__ == "__main__":
   testutils.GanetiTestProgram()
-- 
1.7.0.4

Reply via email to