Explorar el Código

AMBARI-4940. Any artifact install should check if the artifact exists
(Eugene Chekanskiy via aonishuk)

Andrew Onischuk hace 11 años
padre
commit
7077750975

+ 18 - 7
ambari-agent/src/main/python/resource_management/core/providers/package/yumrpm.py

@@ -26,17 +26,28 @@ from resource_management.core.logger import Logger
 
 INSTALL_CMD = "/usr/bin/yum -d 0 -e 0 -y install %s"
 REMOVE_CMD = "/usr/bin/yum -d 0 -e 0 -y erase %s"
+CHECK_CMD = "rpm -q --quiet %s"
 
 class YumProvider(PackageProvider):
   def install_package(self, name):
-    cmd = INSTALL_CMD % (name)
-    Logger.info("Installing package %s ('%s')" % (name, cmd))
-    shell.checked_call(cmd)
+    if not self._check_existence(name):
+      cmd = INSTALL_CMD % (name)
+      Logger.info("Installing package %s ('%s')" % (name, cmd))
+      shell.checked_call(cmd)
+    else:
+      Logger.info("Skipping installing existent package %s" % (name))
 
   def upgrade_package(self, name):
     return self.install_package(name)
-  
+
   def remove_package(self, name):
-    cmd = REMOVE_CMD % (name)
-    Logger.info("Removing package %s ('%s')" % (name, cmd))
-    shell.checked_call(cmd)    
+    if self._check_existence(name):
+      cmd = REMOVE_CMD % (name)
+      Logger.info("Removing package %s ('%s')" % (name, cmd))
+      shell.checked_call(cmd)
+    else:
+      Logger.info("Skipping removing non-existent package %s" % (name))
+
+  def _check_existence(self, name):
+    code, out = shell.call(CHECK_CMD % name)
+    return not bool(code)

+ 17 - 6
ambari-agent/src/main/python/resource_management/core/providers/package/zypper.py

@@ -26,17 +26,28 @@ from resource_management.core.logger import Logger
 
 INSTALL_CMD = "/usr/bin/zypper --quiet install --auto-agree-with-licenses --no-confirm %s"
 REMOVE_CMD = "/usr/bin/zypper --quiet remove --no-confirm %s"
+CHECK_CMD = "rpm -q --quiet %s"
 
 class ZypperProvider(PackageProvider):
   def install_package(self, name):
-    cmd = INSTALL_CMD % (name)
-    Logger.info("Installing package %s ('%s')" % (name, cmd))
-    shell.checked_call(cmd)
+    if not self._check_existence(name):
+      cmd = INSTALL_CMD % (name)
+      Logger.info("Installing package %s ('%s')" % (name, cmd))
+      shell.checked_call(cmd)
+    else:
+      Logger.info("Skipping installing existent package %s" % (name))
 
   def upgrade_package(self, name):
     return self.install_package(name)
   
   def remove_package(self, name):
-    cmd = REMOVE_CMD % (name)
-    Logger.info("Removing package %s ('%s')" % (name, cmd))
-    shell.checked_call(cmd)
+    if self._check_existence(name):
+      cmd = REMOVE_CMD % (name)
+      Logger.info("Removing package %s ('%s')" % (name, cmd))
+      shell.checked_call(cmd)
+    else:
+      Logger.info("Skipping removing non-existent package %s" % (name))
+
+  def _check_existence(self, name):
+    code, out = shell.call(CHECK_CMD % name)
+    return not bool(code)

+ 1 - 1
ambari-agent/src/main/python/resource_management/core/shell.py

@@ -20,7 +20,7 @@ Ambari Agent
 
 """
 
-__all__ = ["checked_call"]
+__all__ = ["checked_call", "call"]
 
 import subprocess
 import pipes

+ 32 - 10
ambari-agent/src/test/python/resource_management/TestPackageResource.py

@@ -27,44 +27,66 @@ from resource_management.core import shell
 
 class TestPackageResource(TestCase):
 
+  @patch.object(shell, "call", new = MagicMock(return_value=(1, None)))
   @patch.object(shell, "checked_call")
   @patch.object(System, "os_family", new = 'redhat')
-  def test_action_install_rhel(self, shell_mock):     
+  def test_action_install_rhel(self, shell_mock):
     with Environment('/') as env:
       Package("some_package",
       )    
     shell_mock.assert_called_with("/usr/bin/yum -d 0 -e 0 -y install some_package")
-    
+
+  @patch.object(shell, "call", new = MagicMock(return_value=(1, None)))
   @patch.object(shell, "checked_call")
   @patch.object(System, "os_family", new = 'suse')
-  def test_action_install_suse(self, shell_mock):     
+  def test_action_install_suse(self, shell_mock):
     with Environment('/') as env:
       Package("some_package",
       )    
     shell_mock.assert_called_with("/usr/bin/zypper --quiet install --auto-agree-with-licenses --no-confirm some_package")
-    
-    
+
+  @patch.object(shell, "call", new = MagicMock(return_value=(0, None)))
+  @patch.object(shell, "checked_call")
+  @patch.object(System, "os_family", new = 'redhat')
+  def test_action_install_existent_rhel(self, shell_mock):
+    with Environment('/') as env:
+      Package("some_package",
+              )
+    self.assertFalse(shell_mock.mock_calls)
+
+  @patch.object(shell, "call", new = MagicMock(return_value=(0, None)))
+  @patch.object(shell, "checked_call")
+  @patch.object(System, "os_family", new = 'suse')
+  def test_action_install_existent_suse(self, shell_mock):
+    with Environment('/') as env:
+      Package("some_package",
+              )
+    self.assertFalse(shell_mock.mock_calls)
+
+  @patch.object(shell, "call", new = MagicMock(return_value=(0, None)))
   @patch.object(shell, "checked_call")
   @patch.object(System, "os_family", new = 'redhat')
-  def test_action_remove_rhel(self, shell_mock):     
+  def test_action_remove_rhel(self, shell_mock):
     with Environment('/') as env:
       Package("some_package",
               action = "remove"
       )    
     shell_mock.assert_called_with("/usr/bin/yum -d 0 -e 0 -y erase some_package")
-    
+
+  @patch.object(shell, "call", new = MagicMock(return_value=(0, None)))
   @patch.object(shell, "checked_call")
   @patch.object(System, "os_family", new = 'suse')
-  def test_action_remove_suse(self, shell_mock):     
+  def test_action_remove_suse(self, shell_mock):
     with Environment('/') as env:
       Package("some_package",
               action = "remove"
       )    
     shell_mock.assert_called_with("/usr/bin/zypper --quiet remove --no-confirm some_package")
-      
+
+  @patch.object(shell, "call", new = MagicMock(return_value=(1, None)))
   @patch.object(shell, "checked_call")
   @patch.object(System, "os_family", new = 'redhat')
-  def test_action_install_version_attr(self, shell_mock):     
+  def test_action_install_version_attr(self, shell_mock):
     with Environment('/') as env:
       Package("some_package",
               version = "3.5.0"