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