Use setUp/tearDown for tests using temporary files.
[ganeti-local] / test / ganeti.utils_unittest.py
index 40e9d79..a270745 100755 (executable)
@@ -29,16 +29,31 @@ import os.path
 import md5
 import socket
 import shutil
+import re
 
 import ganeti
 from ganeti import constants
+from ganeti import utils
 from ganeti.utils import IsProcessAlive, Lock, Unlock, RunCmd, \
      RemoveFile, CheckDict, MatchNameComponent, FormatUnit, \
      ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
-     ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles
+     ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \
+     SetEtcHostsEntry, RemoveEtcHostsEntry
 from ganeti.errors import LockError, UnitParseError
 
 
+class GanetiTestCase(unittest.TestCase):
+  def assertFileContent(self, file_name, content):
+    """Checks the content of a file.
+
+    """
+    handle = open(file_name, 'r')
+    try:
+      self.assertEqual(handle.read(), content)
+    finally:
+      handle.close()
+
+
 class TestIsProcessAlive(unittest.TestCase):
   """Testing case for IsProcessAlive"""
   def setUp(self):
@@ -320,7 +335,8 @@ class TestParseUnit(unittest.TestCase):
     for sep in ('', ' ', '   ', "\t", "\t "):
       for suffix, scale in TestParseUnit.SCALES:
         for func in (lambda x: x, str.lower, str.upper):
-          self.assertEqual(ParseUnit('1024' + sep + func(suffix)), 1024 * scale)
+          self.assertEqual(ParseUnit('1024' + sep + func(suffix)),
+                           1024 * scale)
 
   def testInvalidInput(self):
     for sep in ('-', '_', ',', 'a'):
@@ -331,102 +347,145 @@ class TestParseUnit(unittest.TestCase):
       self.assertRaises(UnitParseError, ParseUnit, '1,3' + suffix)
 
 
-class TestSshKeys(unittest.TestCase):
+class TestSshKeys(GanetiTestCase):
   """Test case for the AddAuthorizedKey function"""
 
   KEY_A = 'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a'
   KEY_B = ('command="/usr/bin/fooserver -t --verbose",from="1.2.3.4" '
            'ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b')
 
-  # NOTE: The MD5 sums below were calculated after manually
-  #       checking the output files.
-
-  def writeTestFile(self):
-    (fd, tmpname) = tempfile.mkstemp(prefix = 'ganeti-test')
-    f = os.fdopen(fd, 'w')
+  def setUp(self):
+    (fd, self.tmpname) = tempfile.mkstemp(prefix='ganeti-test')
     try:
-      f.write(TestSshKeys.KEY_A)
-      f.write("\n")
-      f.write(TestSshKeys.KEY_B)
-      f.write("\n")
-    finally:
-      f.close()
+      handle = os.fdopen(fd, 'w')
+      try:
+        handle.write("%s\n" % TestSshKeys.KEY_A)
+        handle.write("%s\n" % TestSshKeys.KEY_B)
+      finally:
+        handle.close()
+    except:
+      utils.RemoveFile(self.tmpname)
+      raise
 
-    return tmpname
+  def tearDown(self):
+    utils.RemoveFile(self.tmpname)
+    del self.tmpname
 
   def testAddingNewKey(self):
-    tmpname = self.writeTestFile()
-    try:
-      AddAuthorizedKey(tmpname, 'ssh-dss AAAAB3NzaC1kc3MAAACB root@test')
+    AddAuthorizedKey(self.tmpname, 'ssh-dss AAAAB3NzaC1kc3MAAACB root@test')
 
-      f = open(tmpname, 'r')
-      try:
-        self.assertEqual(md5.new(f.read(8192)).hexdigest(),
-                         'ccc71523108ca6e9d0343797dc3e9f16')
-      finally:
-        f.close()
-    finally:
-      os.unlink(tmpname)
+    self.assertFileContent(self.tmpname,
+      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
+      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
+      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
+      "ssh-dss AAAAB3NzaC1kc3MAAACB root@test\n")
 
   def testAddingAlmostButNotCompletlyTheSameKey(self):
-    tmpname = self.writeTestFile()
-    try:
-      AddAuthorizedKey(tmpname,
-          'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test')
+    AddAuthorizedKey(self.tmpname,
+        'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test')
 
-      f = open(tmpname, 'r')
-      try:
-        self.assertEqual(md5.new(f.read(8192)).hexdigest(),
-                         'f2c939d57addb5b3a6846884be896b46')
-      finally:
-        f.close()
-    finally:
-      os.unlink(tmpname)
+    self.assertFileContent(self.tmpname,
+      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
+      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
+      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
+      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test\n")
 
   def testAddingExistingKeyWithSomeMoreSpaces(self):
-    tmpname = self.writeTestFile()
-    try:
-      AddAuthorizedKey(tmpname,
-          'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
+    AddAuthorizedKey(self.tmpname,
+        'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
 
-      f = open(tmpname, 'r')
-      try:
-        self.assertEqual(md5.new(f.read(8192)).hexdigest(),
-                         '4e612764808bd46337eb0f575415fc30')
-      finally:
-        f.close()
-    finally:
-      os.unlink(tmpname)
+    self.assertFileContent(self.tmpname,
+      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
+      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
+      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
 
   def testRemovingExistingKeyWithSomeMoreSpaces(self):
-    tmpname = self.writeTestFile()
-    try:
-      RemoveAuthorizedKey(tmpname,
-          'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
+    RemoveAuthorizedKey(self.tmpname,
+        'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
 
-      f = open(tmpname, 'r')
-      try:
-        self.assertEqual(md5.new(f.read(8192)).hexdigest(),
-                         '77516d987fca07f70e30b830b3e4f2ed')
-      finally:
-        f.close()
-    finally:
-      os.unlink(tmpname)
+    self.assertFileContent(self.tmpname,
+      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
+      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
 
   def testRemovingNonExistingKey(self):
-    tmpname = self.writeTestFile()
-    try:
-      RemoveAuthorizedKey(tmpname,
-          'ssh-dss  AAAAB3Nsdfj230xxjxJjsjwjsjdjU   root@test')
+    RemoveAuthorizedKey(self.tmpname,
+        'ssh-dss  AAAAB3Nsdfj230xxjxJjsjwjsjdjU   root@test')
+
+    self.assertFileContent(self.tmpname,
+      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
+      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
+      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
 
-      f = open(tmpname, 'r')
+
+class TestEtcHosts(GanetiTestCase):
+  """Test functions modifying /etc/hosts"""
+
+  def setUp(self):
+    (fd, self.tmpname) = tempfile.mkstemp(prefix='ganeti-test')
+    try:
+      handle = os.fdopen(fd, 'w')
       try:
-        self.assertEqual(md5.new(f.read(8192)).hexdigest(),
-                         '4e612764808bd46337eb0f575415fc30')
+        handle.write('# This is a test file for /etc/hosts\n')
+        handle.write('127.0.0.1\tlocalhost\n')
+        handle.write('192.168.1.1 router gw\n')
       finally:
-        f.close()
-    finally:
-      os.unlink(tmpname)
+        handle.close()
+    except:
+      utils.RemoveFile(self.tmpname)
+      raise
+
+  def tearDown(self):
+    utils.RemoveFile(self.tmpname)
+    del self.tmpname
+
+  def testSettingNewIp(self):
+    SetEtcHostsEntry(self.tmpname, '1.2.3.4', 'myhost.domain.tld', ['myhost'])
+
+    self.assertFileContent(self.tmpname,
+      "# This is a test file for /etc/hosts\n"
+      "127.0.0.1\tlocalhost\n"
+      "192.168.1.1 router gw\n"
+      "1.2.3.4\tmyhost.domain.tld myhost\n")
+
+  def testSettingExistingIp(self):
+    SetEtcHostsEntry(self.tmpname, '192.168.1.1', 'myhost.domain.tld',
+                     ['myhost'])
+
+    self.assertFileContent(self.tmpname,
+      "# This is a test file for /etc/hosts\n"
+      "127.0.0.1\tlocalhost\n"
+      "192.168.1.1\tmyhost.domain.tld myhost\n")
+
+  def testRemovingExistingHost(self):
+    RemoveEtcHostsEntry(self.tmpname, 'router')
+
+    self.assertFileContent(self.tmpname,
+      "# This is a test file for /etc/hosts\n"
+      "127.0.0.1\tlocalhost\n"
+      "192.168.1.1 gw\n")
+
+  def testRemovingSingleExistingHost(self):
+    RemoveEtcHostsEntry(self.tmpname, 'localhost')
+
+    self.assertFileContent(self.tmpname,
+      "# This is a test file for /etc/hosts\n"
+      "192.168.1.1 router gw\n")
+
+  def testRemovingNonExistingHost(self):
+    RemoveEtcHostsEntry(self.tmpname, 'myhost')
+
+    self.assertFileContent(self.tmpname,
+      "# This is a test file for /etc/hosts\n"
+      "127.0.0.1\tlocalhost\n"
+      "192.168.1.1 router gw\n")
+
+  def testRemovingAlias(self):
+    RemoveEtcHostsEntry(self.tmpname, 'gw')
+
+    self.assertFileContent(self.tmpname,
+      "# This is a test file for /etc/hosts\n"
+      "127.0.0.1\tlocalhost\n"
+      "192.168.1.1 router\n")
 
 
 class TestShellQuoting(unittest.TestCase):
@@ -539,5 +598,15 @@ class TestListVisibleFiles(unittest.TestCase):
     self._test(files, expected)
 
 
+class TestNewUUID(unittest.TestCase):
+  """Test case for NewUUID"""
+
+  _re_uuid = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-'
+                        '[a-f0-9]{4}-[a-f0-9]{12}$')
+
+  def runTest(self):
+    self.failUnless(self._re_uuid.match(utils.NewUUID()))
+
+
 if __name__ == '__main__':
   unittest.main()