瀏覽代碼

AMBARI-12909: Existence of empty package folder in stack definition breaks the service (Nahappan Somasundaram via jluniya)

Jayush Luniya 9 年之前
父節點
當前提交
d145dd6dca

+ 9 - 3
ambari-agent/src/main/python/ambari_agent/FileCache.py

@@ -145,9 +145,15 @@ class FileCache():
           download_url = self.build_download_url(server_url_prefix,
           download_url = self.build_download_url(server_url_prefix,
                                                  subdirectory, self.ARCHIVE_NAME)
                                                  subdirectory, self.ARCHIVE_NAME)
           membuffer = self.fetch_url(download_url)
           membuffer = self.fetch_url(download_url)
-          self.invalidate_directory(full_path)
-          self.unpack_archive(membuffer, full_path)
-          self.write_hash_sum(full_path, remote_hash)
+          # extract only when the archive is not zero sized
+          if (membuffer.getvalue().strip()):
+            self.invalidate_directory(full_path)
+            self.unpack_archive(membuffer, full_path)
+            self.write_hash_sum(full_path, remote_hash)
+          else:
+            logger.warn("Skipping empty archive: {0}. "
+                        "Expected archive was not found. Cached copy will be used.".format(download_url))
+            pass
         # Finally consider cache directory up-to-date
         # Finally consider cache directory up-to-date
         self.uptodate_paths.append(full_path)
         self.uptodate_paths.append(full_path)
     except CachingException, e:
     except CachingException, e:

+ 26 - 0
ambari-agent/src/test/python/ambari_agent/TestFileCache.py

@@ -233,6 +233,32 @@ class TestFileCache(TestCase):
                                   "server_url_prefix")
                                   "server_url_prefix")
     self.assertEquals(res, path)
     self.assertEquals(res, path)
 
 
+    # Test empty archive
+    fetch_url_mock.reset_mock()
+    build_download_url_mock.reset_mock()
+    read_hash_sum_mock.reset_mock()
+    invalidate_directory_mock.reset_mock()
+    unpack_archive_mock.reset_mock()
+    fileCache.reset()
+
+    fetch_url_mock.side_effect = None
+    membuffer_empty = MagicMock()
+    membuffer_empty.getvalue.return_value.strip.return_value = ""
+    fetch_url_mock.return_value = membuffer_empty # Remote hash and content
+    read_hash_sum_mock.return_value = "hash2" # Local hash
+
+    res = fileCache.provide_directory("cache_path", "subdirectory",
+                                      "server_url_prefix")
+    self.assertTrue(fetch_url_mock.return_value.strip() != read_hash_sum_mock.return_value.strip())
+    self.assertEquals(build_download_url_mock.call_count, 2)
+    self.assertEquals(fetch_url_mock.call_count, 2)
+    self.assertFalse(invalidate_directory_mock.called)
+    self.assertFalse(unpack_archive_mock.called)
+    self.assertFalse(write_hash_sum_mock.called)
+    self.assertEquals(pprint.pformat(fileCache.uptodate_paths), pprint.pformat([path]))
+    self.assertEquals(res, path)
+    pass
+
 
 
   def test_build_download_url(self):
   def test_build_download_url(self):
     fileCache = FileCache(self.config)
     fileCache = FileCache(self.config)

+ 8 - 4
ambari-server/src/main/python/ambari_server/resourceFilesKeeper.py

@@ -141,17 +141,17 @@ class ResourceFilesKeeper():
     except Exception, err:
     except Exception, err:
       raise KeeperException("Can not list common services: {0}".format(str(err)))
       raise KeeperException("Can not list common services: {0}".format(str(err)))
 
 
-
   def update_directory_archive(self, directory):
   def update_directory_archive(self, directory):
     """
     """
     If hash sum for directory is not present or differs from saved value,
     If hash sum for directory is not present or differs from saved value,
     recalculates hash sum and creates directory archive
     recalculates hash sum and creates directory archive
     """
     """
+    skip_empty_directory = True
     cur_hash = self.count_hash_sum(directory)
     cur_hash = self.count_hash_sum(directory)
     saved_hash = self.read_hash_sum(directory)
     saved_hash = self.read_hash_sum(directory)
     if cur_hash != saved_hash:
     if cur_hash != saved_hash:
       if not self.nozip:
       if not self.nozip:
-        self.zip_directory(directory)
+        self.zip_directory(directory, skip_empty_directory)
       self.write_hash_sum(directory, cur_hash)
       self.write_hash_sum(directory, cur_hash)
 
 
 
 
@@ -216,14 +216,18 @@ class ResourceFilesKeeper():
       raise KeeperException("Can not write to file {0} : {1}".format(hash_file,
       raise KeeperException("Can not write to file {0} : {1}".format(hash_file,
                                                                    str(err)))
                                                                    str(err)))
 
 
-
-  def zip_directory(self, directory):
+  def zip_directory(self, directory, skip_if_empty = False):
     """
     """
     Packs entire directory into zip file. Hash file is also packaged
     Packs entire directory into zip file. Hash file is also packaged
     into archive
     into archive
     """
     """
     self.dbg_out("creating archive for directory {0}".format(directory))
     self.dbg_out("creating archive for directory {0}".format(directory))
     try:
     try:
+      if skip_if_empty:
+        if not os.listdir(directory):
+          self.dbg_out("Empty directory. Skipping archive creation for {0}".format(directory))
+          return
+
       zf = zipfile.ZipFile(os.path.join(directory, self.ARCHIVE_NAME), "w")
       zf = zipfile.ZipFile(os.path.join(directory, self.ARCHIVE_NAME), "w")
       abs_src = os.path.abspath(directory)
       abs_src = os.path.abspath(directory)
       for root, dirs, files in os.walk(directory):
       for root, dirs, files in os.walk(directory):

+ 10 - 0
ambari-server/src/test/python/TestResourceFilesKeeper.py

@@ -349,6 +349,16 @@ class TestResourceFilesKeeper(TestCase):
       except Exception, e:
       except Exception, e:
         self.fail('Unexpected exception thrown:' + str(e))
         self.fail('Unexpected exception thrown:' + str(e))
 
 
+    # Test skip zipping of an empty directory
+    with patch("os.listdir") as os_listdir_mock:
+      os_listdir_mock.return_value = False # Empty dir
+      try:
+        skip_empty_directory = True
+        resource_files_keeper.zip_directory("empty-to-directory", skip_empty_directory)
+        self.assertTrue(os_listdir_mock.called)
+      except Exception, e:
+        self.fail('Unexpected exception thrown: ' + str(e))
+    pass
 
 
   def test_is_ignored(self):
   def test_is_ignored(self):
     resource_files_keeper = ResourceFilesKeeper(self.TEST_RESOURCES_DIR, self.DUMMY_UNCHANGEABLE_PACKAGE)
     resource_files_keeper = ResourceFilesKeeper(self.TEST_RESOURCES_DIR, self.DUMMY_UNCHANGEABLE_PACKAGE)