Browse Source

AMBARI-5184. Create repo files for Ubuntu based on the urls that are passed from the stack defn. (aonishuk)

Andrew Onischuk 11 years ago
parent
commit
1f8f6de2c9

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

@@ -69,7 +69,15 @@ class System(object):
     In case cannot detect --> Fail
     """
     return OSCheck().get_os_version()
-    
+  
+  @lazy_property
+  def os_release_name(self):
+    """
+    For Ubuntu 12.04:
+    precise
+    """
+    return OSCheck().get_os_release_name()
+                       
   @lazy_property
   def os_type(self):
     """

+ 3 - 1
ambari-agent/src/main/python/resource_management/libraries/providers/__init__.py

@@ -22,10 +22,13 @@ Ambari Agent
 
 PROVIDERS = dict(
   redhat=dict(
+    Repository="resource_management.libraries.providers.repository.RhelSuseRepositoryProvider",
   ),
   suse=dict(
+    Repository="resource_management.libraries.providers.repository.RhelSuseRepositoryProvider",
   ),
   debian=dict(
+    Repository="resource_management.libraries.providers.repository.DebianRepositoryProvider",
   ),
   default=dict(
     ExecuteHadoop="resource_management.libraries.providers.execute_hadoop.ExecuteHadoopProvider",
@@ -33,7 +36,6 @@ PROVIDERS = dict(
     XmlConfig="resource_management.libraries.providers.xml_config.XmlConfigProvider",
     PropertiesFile="resource_management.libraries.providers.properties_file.PropertiesFileProvider",
     MonitorWebserver="resource_management.libraries.providers.monitor_webserver.MonitorWebserverProvider",
-    Repository="resource_management.libraries.providers.repository.RepositoryProvider",
     HdfsDirectory="resource_management.libraries.providers.hdfs_directory.HdfsDirectoryProvider",
     CopyFromLocal="resource_management.libraries.providers.copy_from_local.CopyFromLocalProvider"
   ),

+ 43 - 2
ambari-agent/src/main/python/resource_management/libraries/providers/repository.py

@@ -20,9 +20,13 @@ Ambari Agent
 
 """
 
+import os
+import filecmp
+import tempfile
+from common_functions import OSCheck
 from resource_management import *
 
-class RepositoryProvider(Provider):
+class RhelSuseRepositoryProvider(Provider):
   def action_create(self):
     with Environment.get_instance_copy() as env:
       repo_file_name = self.resource.repo_file_name
@@ -49,4 +53,41 @@ gpgcheck=0""", repo_id=self.resource.repo_id, repo_file_name=self.resource.repo_
 repos_dirs = {
   'redhat': '/etc/yum.repos.d',
   'suse': '/etc/zypp/repos.d'
-}
+}
+
+
+class DebianRepositoryProvider(Provider):
+  package_type = "deb"
+  repo_dir = "/etc/apt/sources.list.d"
+  update_cmd = 'apt-get update -o Dir::Etc::sourcelist="sources.list.d/{repo_file_name}" -o APT::Get::List-Cleanup="0"'
+
+  def action_create(self):
+    with Environment.get_instance_copy() as env:
+      with tempfile.NamedTemporaryFile() as tmpf:
+        File(tmpf.name,
+          content = InlineTemplate("{{package_type}} {{base_url}} {{relase_name}} {{components}}", 
+              package_type=self.package_type, base_url=self.resource.base_url, relase_name=env.system.os_release_name, components=' '.join(self.resource.components))
+        )
+        
+        repo_file_name = format("{repo_file_name}.list",repo_file_name = self.resource.repo_file_name)
+        repo_file_path = format("{repo_dir}/{repo_file_name}", repo_dir = self.repo_dir)
+        
+        if not os.path.isfile(repo_file_path) or not filecmp.cmp(tmpf.name, repo_file_path):
+          File(repo_file_path,
+               content = StaticFile(tmpf.name)
+          )
+          
+          # this is time expensive
+          Execute(format(self.update_cmd))
+  
+  def action_remove(self):
+    with Environment.get_instance_copy() as env:
+      repo_file_name = format("{repo_file_name}.list",repo_file_name = self.resource.repo_file_name)
+      repo_file_path = format("{repo_dir}/{repo_file_name}", repo_dir = self.repo_dir)
+      
+      if os.path.isfile(repo_file_path):
+        File(repo_file_path,
+             action = "delete")
+        
+        # this is time expensive
+        Execute(format(self.update_cmd))

+ 1 - 0
ambari-agent/src/main/python/resource_management/libraries/resources/repository.py

@@ -30,5 +30,6 @@ class Repository(Resource):
   base_url = ResourceArgument()
   mirror_list = ResourceArgument()
   repo_file_name = ResourceArgument()
+  components = ForcedListArgument(default=[]) # ubuntu specific
 
   actions = Resource.actions + ["create","remove"]

+ 93 - 7
ambari-agent/src/test/python/resource_management/TestRepositoryResource.py

@@ -16,14 +16,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 '''
 
+import os
+import tempfile
 from unittest import TestCase
-from mock.mock import patch
+from mock.mock import patch, MagicMock
 
 from resource_management import *
-from resource_management.libraries.providers.repository \
-    import RepositoryProvider
-from resource_management.libraries.resources.repository \
-    import Repository
 
 
 class TestRepositoryResource(TestCase):
@@ -86,8 +84,96 @@ name={{repo_file_name}}
 {% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %}
 path=/
 enabled=1
-gpgcheck=0""", template)
-
+gpgcheck=0""", template)   
+    
+    
+    @patch.object(tempfile, "NamedTemporaryFile")
+    @patch("resource_management.libraries.providers.repository.Execute")
+    @patch("resource_management.libraries.providers.repository.File")
+    @patch("os.path.isfile", new=MagicMock(return_value=True))
+    @patch("filecmp.cmp", new=MagicMock(return_value=False))
+    @patch.object(System, "os_release_name", new='precise')        
+    @patch.object(System, "os_family", new='debian')
+    def test_create_repo_debian_repo_exists(self, file_mock, execute_mock, tempfile_mock):
+      tempfile_mock.return_value = MagicMock(spec=file)
+      tempfile_mock.return_value.__enter__.return_value.name = "/tmp/1.txt"
+      
+      with Environment('/') as env:
+          Repository('HDP',
+                     base_url='http://download.base_url.org/rpm/',
+                     repo_file_name='HDP',
+                     components = ['a','b','c']
+          )
+      
+      template_item = file_mock.call_args_list[0]
+      template_name = template_item[0][0]
+      template_content = template_item[1]['content'].get_content()
+      
+      self.assertEquals(template_name, '/tmp/1.txt')
+      self.assertEquals(template_content, 'deb http://download.base_url.org/rpm/ precise a b c\n')
+      
+      copy_item = str(file_mock.call_args_list[1])
+      self.assertEqual(copy_item, "call('/etc/apt/sources.list.d/HDP.list', content=StaticFile('/tmp/1.txt'))")
+      
+      execute_command_item = execute_mock.call_args_list[0][0][0]
+      self.assertEqual(execute_command_item, 'apt-get update -o Dir::Etc::sourcelist="sources.list.d/HDP.list" -o APT::Get::List-Cleanup="0"')
+
+    @patch.object(tempfile, "NamedTemporaryFile")
+    @patch("resource_management.libraries.providers.repository.Execute")
+    @patch("resource_management.libraries.providers.repository.File")
+    @patch("os.path.isfile", new=MagicMock(return_value=True))
+    @patch("filecmp.cmp", new=MagicMock(return_value=True))
+    @patch.object(System, "os_release_name", new='precise')        
+    @patch.object(System, "os_family", new='debian')
+    def test_create_repo_debian_doesnt_repo_exist(self, file_mock, execute_mock, tempfile_mock):
+      tempfile_mock.return_value = MagicMock(spec=file)
+      tempfile_mock.return_value.__enter__.return_value.name = "/tmp/1.txt"
+      
+      with Environment('/') as env:
+          Repository('HDP',
+                     base_url='http://download.base_url.org/rpm/',
+                     repo_file_name='HDP',
+                     components = ['a','b','c']
+          )
+      
+      template_item = file_mock.call_args_list[0]
+      template_name = template_item[0][0]
+      template_content = template_item[1]['content'].get_content()
+      
+      self.assertEquals(template_name, '/tmp/1.txt')
+      self.assertEquals(template_content, 'deb http://download.base_url.org/rpm/ precise a b c\n')
+      
+      self.assertEqual(file_mock.call_count, 1)
+      self.assertEqual(execute_mock.call_count, 0)
+      
+    
+    @patch("os.path.isfile", new=MagicMock(return_value=True))
+    @patch.object(System, "os_family", new='debian')
+    @patch("resource_management.libraries.providers.repository.Execute")
+    @patch("resource_management.libraries.providers.repository.File")
+    def test_remove_repo_debian_repo_exist(self, file_mock, execute_mock):
+      with Environment('/') as env:
+          Repository('HDP',
+                     action = "remove",
+                     repo_file_name='HDP'
+          )
+          
+      self.assertEqual(str(file_mock.call_args), "call('/etc/apt/sources.list.d/HDP.list', action='delete')")
+      self.assertEqual(execute_mock.call_args[0][0], 'apt-get update -o Dir::Etc::sourcelist="sources.list.d/HDP.list" -o APT::Get::List-Cleanup="0"')
+
+    @patch("os.path.isfile", new=MagicMock(return_value=False))
+    @patch.object(System, "os_family", new='debian')
+    @patch("resource_management.libraries.providers.repository.Execute")
+    @patch("resource_management.libraries.providers.repository.File")
+    def test_remove_repo_debian_repo_doenst_exist(self, file_mock, execute_mock):
+      with Environment('/') as env:
+          Repository('HDP',
+                     action = "remove",
+                     repo_file_name='HDP'
+          )
+          
+      self.assertEqual(file_mock.call_count, 0)
+      self.assertEqual(execute_mock.call_count, 0)
 
     @patch.object(System, "os_family", new='redhat')
     @patch("resource_management.libraries.providers.repository.File")