You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2013/04/04 18:56:59 UTC

svn commit: r1464631 - in /incubator/ambari/trunk: ./ ambari-agent/src/main/python/ambari_agent/ ambari-agent/src/test/python/

Author: smohanty
Date: Thu Apr  4 16:56:59 2013
New Revision: 1464631

URL: http://svn.apache.org/r1464631
Log:
AMBARI-1784. MapReduce service damaging after hadoop installation with ustom MapReduce user which contains symbol '-'. (smohanty)

Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/AmbariConfig.py
    incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/LiveStatus.py
    incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/StatusCheck.py
    incubator/ambari/trunk/ambari-agent/src/test/python/TestStatusCheck.py

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1464631&r1=1464630&r2=1464631&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Thu Apr  4 16:56:59 2013
@@ -549,6 +549,9 @@ Trunk (unreleased changes):
 
  BUG FIXES
 
+ AMBARI-1784. MapReduce service damaging after hadoop installation with 
+ custom MapReduce user which contains symbol '-'. (smohanty)
+
  AMBARI-1774. Ambari does not push the config updates to the client/gateway 
  node. (swagle)
 

Modified: incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/AmbariConfig.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/AmbariConfig.py?rev=1464631&r1=1464630&r2=1464631&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/AmbariConfig.py (original)
+++ incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/AmbariConfig.py Thu Apr  4 16:56:59 2013
@@ -130,19 +130,19 @@ serviceStates = {
 }
 
 servicesToPidNames = {
-  'NAMENODE': 'hadoop-[A-Za-z0-9_]+-namenode.pid$',
-  'SECONDARY_NAMENODE': 'hadoop-[A-Za-z0-9_]+-secondarynamenode.pid$',
-  'DATANODE': 'hadoop-[A-Za-z0-9_]+-datanode.pid$',
-  'JOBTRACKER': 'hadoop-[A-Za-z0-9_]+-jobtracker.pid$',
-  'TASKTRACKER': 'hadoop-[A-Za-z0-9_]+-tasktracker.pid$',
+  'NAMENODE': 'hadoop-{USER}-namenode.pid$',
+  'SECONDARY_NAMENODE': 'hadoop-{USER}-secondarynamenode.pid$',
+  'DATANODE': 'hadoop-{USER}-datanode.pid$',
+  'JOBTRACKER': 'hadoop-{USER}-jobtracker.pid$',
+  'TASKTRACKER': 'hadoop-{USER}-tasktracker.pid$',
   'OOZIE_SERVER': 'oozie.pid',
   'ZOOKEEPER_SERVER': 'zookeeper_server.pid',
   'TEMPLETON_SERVER': 'templeton.pid',
   'NAGIOS_SERVER': 'nagios.pid',
   'GANGLIA_SERVER': 'gmetad.pid',
   'GANGLIA_MONITOR': 'gmond.pid',
-  'HBASE_MASTER': 'hbase-[A-Za-z0-9_]+-master.pid',
-  'HBASE_REGIONSERVER': 'hbase-[A-Za-z0-9_]+-regionserver.pid',
+  'HBASE_MASTER': 'hbase-{USER}-master.pid',
+  'HBASE_REGIONSERVER': 'hbase-{USER}-regionserver.pid',
   'HCATALOG_SERVER': 'webhcat.pid',
   'KERBEROS_SERVER': 'kadmind.pid',
   'HIVE_SERVER': 'hive-server.pid',
@@ -150,6 +150,8 @@ servicesToPidNames = {
   'MYSQL_SERVER': 'mysqld.pid'
 }
 
+linuxUserPattern = '[A-Za-z0-9_-]*[$]?'
+
 pidPathesVars = [
   {'var' : 'hadoop_pid_dir_prefix',
    'defaultValue' : '/var/run/hadoop'},

Modified: incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/LiveStatus.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/LiveStatus.py?rev=1464631&r1=1464630&r2=1464631&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/LiveStatus.py (original)
+++ incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/LiveStatus.py Thu Apr  4 16:56:59 2013
@@ -109,7 +109,7 @@ class LiveStatus:
   # Live status was stripped from heartbeat after revision e1718dd
   def build(self):
     global SERVICES, COMPONENTS, LIVE_STATUS, DEAD_STATUS
-    statusCheck = StatusCheck(AmbariConfig.servicesToPidNames, AmbariConfig.pidPathesVars, self.globalConfig)
+    statusCheck = StatusCheck(AmbariConfig.servicesToPidNames, AmbariConfig.pidPathesVars, self.globalConfig, AmbariConfig.linuxUserPattern)
     livestatus = None
     for component in self.COMPONENTS:
       if component["serviceName"] == self.service and component["componentName"] == self.component:

Modified: incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/StatusCheck.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/StatusCheck.py?rev=1464631&r1=1464630&r2=1464631&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/StatusCheck.py (original)
+++ incubator/ambari/trunk/ambari-agent/src/main/python/ambari_agent/StatusCheck.py Thu Apr  4 16:56:59 2013
@@ -24,6 +24,7 @@ import logging.handlers
 import sys
 import os
 import re
+import string
 
 logger = logging.getLogger()
 
@@ -62,7 +63,7 @@ class StatusCheck:
     except Exception as e:
         logger.error("Error while filling directories values " + str(e))
         
-  def __init__(self, serviceToPidDict, pidPathesVars, globalConfig):
+  def __init__(self, serviceToPidDict, pidPathesVars, globalConfig, linuxUserPattern):
 
     self.serToPidDict = serviceToPidDict
     self.pidPathesVars = pidPathesVars
@@ -70,12 +71,16 @@ class StatusCheck:
     self.sh = shellRunner()
     self.pidFilesDict = {}
     self.globalConfig = globalConfig
+    self.linuxUserPattern = linuxUserPattern
     
     self.fillDirValues()
     
     for pidPath in self.pidPathes:
       self.listFiles(pidPath)
 
+    for service, pid in self.serToPidDict.items():
+      self.serToPidDict[service] = string.replace(pid, '{USER}', self.linuxUserPattern)
+
   def getIsLive(self, pidPath):
 
     if not pidPath:

Modified: incubator/ambari/trunk/ambari-agent/src/test/python/TestStatusCheck.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-agent/src/test/python/TestStatusCheck.py?rev=1464631&r1=1464630&r2=1464631&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-agent/src/test/python/TestStatusCheck.py (original)
+++ incubator/ambari/trunk/ambari-agent/src/test/python/TestStatusCheck.py Thu Apr  4 16:56:59 2013
@@ -17,78 +17,83 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 See the License for the specific language governing permissions and
 limitations under the License.
 '''
-import tempfile
-import shutil
+import string
+import random
 import os
 from unittest import TestCase
 from ambari_agent.StatusCheck import StatusCheck
-import subprocess
-import signal
-from shell import shellRunner
+import AmbariConfig
+import logging
+from mock.mock import patch, Mock
 
 
-MAPPING_FILE_NAME='map.dict'
+USERNAME_LENGTH=10
+USERNAME_CHARS=string.ascii_uppercase +string.ascii_lowercase + string.digits + '-_'
+
+PID_DIR='/pids_dir'
 
 COMPONENT_LIVE = 'LIVE_COMPONENT'
-COMPONENT_LIVE_PID = 'live_comp.pid'
-COMPONENT_LIVE_CMD='''
-while [ 1==1 ]
-do
-   echo ok
-done
-'''
+COMPONENT_LIVE_PID = 'live_{USER}_comp.pid'
 
 COMPONENT_DEAD = 'DEAD_COMPONENT'
-COMPONENT_DEAD_PID = 'dead_comp.pid'
-DEAD_PID=0
-
+COMPONENT_DEAD_PID = 'dead_{USER}_comp.pid'
 
 class TestStatusCheck(TestCase):
 
+  logger = logging.getLogger()
+
+  def generateUserName(self):
+    return ''.join(random.choice(USERNAME_CHARS) for x in range(USERNAME_LENGTH))
+
   def setUp(self):
 
-    self.tmpdir = tempfile.mkdtemp()
+    self.pidPathesVars = [
+      {'var' : '',
+      'defaultValue' : PID_DIR}
+    ]
+
     self.serviceToPidDict = {
       COMPONENT_LIVE : COMPONENT_LIVE_PID,
       COMPONENT_DEAD : COMPONENT_DEAD_PID
     }
 
-    self.pidPathesVars = [
-      {'var' : '',
-      'defaultValue' : self.tmpdir}
-    ]
+    live_user = self.generateUserName()
+    self.logger.info('Live user: ' + live_user)
+    self.live_pid_file_name = string.replace(COMPONENT_LIVE_PID, '{USER}', live_user)
+    self.live_pid_full_path = PID_DIR + os.sep + self.live_pid_file_name
+
+    dead_user = self.generateUserName()
+    self.logger.info('Dead user: ' + live_user)
+    self.dead_pid_file_name = string.replace(COMPONENT_DEAD_PID, '{USER}', dead_user)
+    self.dead_pid_full_path = PID_DIR + os.sep + self.dead_pid_file_name
 
-    self.sh = shellRunner()
-    
-    #Launch eternal process
-    p = subprocess.Popen([COMPONENT_LIVE_CMD], stdout=subprocess.PIPE, 
-                         stderr=subprocess.PIPE, shell=True, close_fds=True)
-
-
-    #Write pid of live process to file
-    live_pid_file = open(self.tmpdir + os.sep + COMPONENT_LIVE_PID, 'w')
-    self.live_pid = p.pid
-    live_pid_file.write(str(self.live_pid))
-    live_pid_file.close()
-
-    #Write pid of dead process to file
-    dead_pid_file = open(self.tmpdir + os.sep + COMPONENT_DEAD_PID, 'w')
-    dead_pid_file.write(str(DEAD_PID))
-    dead_pid_file.close()
+    self.pidFilesDict = {self.live_pid_file_name : self.live_pid_full_path,
+                         self.dead_pid_file_name : self.dead_pid_full_path}
 
-    #Init status checker
-    self.statusCheck = StatusCheck(self.serviceToPidDict,self.pidPathesVars,{})
+    self.is_live_values = {self.live_pid_full_path : True,
+                      self.dead_pid_full_path : False}
 
+    
   # Ensure that status checker return True for running process
-  def test_live(self):
-    status = self.statusCheck.getStatus(COMPONENT_LIVE)
+  @patch.object(StatusCheck, 'getIsLive')
+  def test_live(self, get_is_live_mock):
+
+    statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,{},AmbariConfig.linuxUserPattern)
+
+    statusCheck.pidFilesDict = self.pidFilesDict
+    
+    get_is_live_mock.side_effect = lambda pid_path : self.is_live_values[pid_path]
+    
+    status = statusCheck.getStatus(COMPONENT_LIVE)
     self.assertEqual(status, True)
 
   # Ensure that status checker return False for dead process
-  def test_dead(self):
-    status = self.statusCheck.getStatus(COMPONENT_DEAD)
-    self.assertEqual(status, False)
+  @patch.object(StatusCheck, 'getIsLive')
+  def test_dead(self, get_is_live_mock):
+    statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,{},AmbariConfig.linuxUserPattern)
 
-  def tearDown(self):
-    os.kill(self.live_pid, signal.SIGKILL)
-    shutil.rmtree(self.tmpdir)
+    statusCheck.pidFilesDict = self.pidFilesDict
+    
+    get_is_live_mock.side_effect = lambda pid_path : self.is_live_values[pid_path]
+    status = statusCheck.getStatus(COMPONENT_DEAD)
+    self.assertEqual(status, False)