You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2014/11/14 03:20:09 UTC
[27/29] ambari git commit: AMBARI-8269. Merge branch-windows-dev
changes to trunk. (Jayush Luniya via yusaku)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/main/python/ambari_agent/StatusCheck.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/StatusCheck.py b/ambari-agent/src/main/python/ambari_agent/StatusCheck.py
index 2b64989..7feadb6 100644
--- a/ambari-agent/src/main/python/ambari_agent/StatusCheck.py
+++ b/ambari-agent/src/main/python/ambari_agent/StatusCheck.py
@@ -54,7 +54,7 @@ class StatusCheck:
def fillDirValues(self):
try:
- for pidVar in self.pidPathesVars:
+ for pidVar in self.pidPathVars:
pidVarName = pidVar['var']
pidDefaultvalue = pidVar['defaultValue']
if self.globalConfig.has_key(pidVarName):
@@ -64,11 +64,11 @@ 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, pidPathVars, globalConfig,
servicesToLinuxUser):
self.serToPidDict = serviceToPidDict.copy()
- self.pidPathesVars = pidPathesVars
+ self.pidPathVars = pidPathVars
self.pidPathes = []
self.sh = shellRunner()
self.pidFilesDict = {}
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/main/python/ambari_agent/hostname.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/hostname.py b/ambari-agent/src/main/python/ambari_agent/hostname.py
index 9fbe145..caf7600 100644
--- a/ambari-agent/src/main/python/ambari_agent/hostname.py
+++ b/ambari-agent/src/main/python/ambari_agent/hostname.py
@@ -44,11 +44,11 @@ def hostname(config):
if (0 == osStat.returncode and 0 != len(out.strip())):
cached_hostname = out.strip()
else:
- cached_hostname = socket.getfqdn()
+ cached_hostname = socket.getfqdn().lower()
except:
- cached_hostname = socket.getfqdn()
+ cached_hostname = socket.getfqdn().lower()
except:
- cached_hostname = socket.getfqdn()
+ cached_hostname = socket.getfqdn().lower()
return cached_hostname
@@ -81,7 +81,7 @@ def public_hostname(config):
handle.close()
cached_public_hostname = str
except Exception, e:
- cached_public_hostname = socket.getfqdn()
+ cached_public_hostname = socket.getfqdn().lower()
return cached_public_hostname
def main(argv=None):
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/main/python/ambari_agent/main.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/main.py b/ambari-agent/src/main/python/ambari_agent/main.py
index 622e86f..e43d901 100644
--- a/ambari-agent/src/main/python/ambari_agent/main.py
+++ b/ambari-agent/src/main/python/ambari_agent/main.py
@@ -25,60 +25,45 @@ import sys
import traceback
import os
import time
+import platform
import ConfigParser
import ProcessHelper
from Controller import Controller
-from AmbariConfig import AmbariConfig
+import AmbariConfig
from NetUtil import NetUtil
from PingPortListener import PingPortListener
import hostname
from DataCleaner import DataCleaner
import socket
-
logger = logging.getLogger()
+
formatstr = "%(levelname)s %(asctime)s %(filename)s:%(lineno)d - %(message)s"
agentPid = os.getpid()
-config = AmbariConfig()
+config = AmbariConfig.AmbariConfig()
configFile = config.CONFIG_FILE
two_way_ssl_property = config.TWO_WAY_SSL_PROPERTY
-if 'AMBARI_LOG_DIR' in os.environ:
- logfile = os.environ['AMBARI_LOG_DIR'] + "/ambari-agent.log"
-else:
- logfile = "/var/log/ambari-agent/ambari-agent.log"
-
-def signal_handler(signum, frame):
- #we want the handler to run only for the agent process and not
- #for the children (e.g. namenode, etc.)
- if os.getpid() != agentPid:
- os._exit(0)
- logger.info('signal received, exiting.')
- ProcessHelper.stopAgent()
-
-def debug(sig, frame):
- """Interrupt running process, and provide a python prompt for
- interactive debugging."""
- d={'_frame':frame} # Allow access to frame object.
- d.update(frame.f_globals) # Unless shadowed by global
- d.update(frame.f_locals)
-
- message = "Signal received : entering python shell.\nTraceback:\n"
- message += ''.join(traceback.format_stack(frame))
- logger.info(message)
+IS_WINDOWS = platform.system() == "Windows"
+if IS_WINDOWS:
+ from HeartbeatHandlers_windows import bind_signal_handlers
+else:
+ from HeartbeatStopHandler_linux import bind_signal_handlers
+ from HeartbeatStopHandler_linux import signal_handler
+ from HeartbeatStopHandler_linux import debug
def setup_logging(verbose):
formatter = logging.Formatter(formatstr)
- rotateLog = logging.handlers.RotatingFileHandler(logfile, "a", 10000000, 25)
+ rotateLog = logging.handlers.RotatingFileHandler(AmbariConfig.AmbariConfig.getLogFile(), "a", 10000000, 25)
rotateLog.setFormatter(formatter)
logger.addHandler(rotateLog)
if verbose:
- logging.basicConfig(format=formatstr, level=logging.DEBUG, filename=logfile)
+ logging.basicConfig(format=formatstr, level=logging.DEBUG, filename=AmbariConfig.AmbariConfig.getLogFile())
logger.setLevel(logging.DEBUG)
logger.info("loglevel=logging.DEBUG")
else:
- logging.basicConfig(format=formatstr, level=logging.INFO, filename=logfile)
+ logging.basicConfig(format=formatstr, level=logging.INFO, filename=AmbariConfig.AmbariConfig.getLogFile())
logger.setLevel(logging.INFO)
logger.info("loglevel=logging.INFO")
@@ -89,35 +74,30 @@ def update_log_level(config):
loglevel = config.get('agent', 'loglevel')
if loglevel is not None:
if loglevel == 'DEBUG':
- logging.basicConfig(format=formatstr, level=logging.DEBUG, filename=logfile)
+ logging.basicConfig(format=formatstr, level=logging.DEBUG, filename=AmbariConfig.AmbariConfig.getLogFile())
logger.setLevel(logging.DEBUG)
logger.info("Newloglevel=logging.DEBUG")
else:
- logging.basicConfig(format=formatstr, level=logging.INFO, filename=logfile)
+ logging.basicConfig(format=formatstr, level=logging.INFO, filename=AmbariConfig.AmbariConfig.getLogFile())
logger.setLevel(logging.INFO)
logger.debug("Newloglevel=logging.INFO")
except Exception, err:
logger.info("Default loglevel=DEBUG")
-def bind_signal_handlers():
- signal.signal(signal.SIGINT, signal_handler)
- signal.signal(signal.SIGTERM, signal_handler)
- signal.signal(signal.SIGUSR1, debug)
-
-
# ToDo: move that function inside AmbariConfig
def resolve_ambari_config():
global config
+ configPath = os.path.abspath(AmbariConfig.AmbariConfig.getConfigFile())
+
try:
- if os.path.exists(configFile):
- config.read(configFile)
+ if os.path.exists(configPath):
+ config.read(configPath)
else:
- raise Exception("No config found, use default")
+ raise Exception("No config found at {0}, use default".format(configPath))
except Exception, err:
logger.warn(err)
- return config
def perform_prestart_checks(expected_hostname):
@@ -137,16 +117,21 @@ def perform_prestart_checks(expected_hostname):
logger.error(msg)
sys.exit(1)
# Check if there is another instance running
- if os.path.isfile(ProcessHelper.pidfile):
+ if os.path.isfile(ProcessHelper.pidfile) and not IS_WINDOWS:
print("%s already exists, exiting" % ProcessHelper.pidfile)
sys.exit(1)
# check if ambari prefix exists
- elif not os.path.isdir(config.get("agent", "prefix")):
+ elif config.has_option('agent', 'prefix') and not os.path.isdir(os.path.abspath(config.get('agent', 'prefix'))):
msg = "Ambari prefix dir %s does not exists, can't continue" \
% config.get("agent", "prefix")
logger.error(msg)
print(msg)
sys.exit(1)
+ elif not config.has_option('agent', 'prefix'):
+ msg = "Ambari prefix dir %s not configured, can't continue"
+ logger.error(msg)
+ print(msg)
+ sys.exit(1)
def daemonize():
@@ -207,7 +192,9 @@ def reset_agent(options):
os._exit(0)
-def main():
+# event - event, that will be passed to Controller and NetUtil to make able to interrupt loops form outside process
+# we need this for windows os, where no sigterm available
+def main(heartbeat_stop_callback=None):
global config
parser = OptionParser()
parser.add_option("-v", "--verbose", dest="verbose", action="store_true", help="verbose log output", default=False)
@@ -222,7 +209,7 @@ def main():
default_cfg = {'agent': {'prefix': '/home/ambari'}}
config.load(default_cfg)
- bind_signal_handlers()
+ bind_signal_handlers(agentPid)
if (len(sys.argv) > 1) and sys.argv[1] == 'stop':
stop_agent()
@@ -231,16 +218,18 @@ def main():
reset_agent(sys.argv)
# Check for ambari configuration file.
- config = resolve_ambari_config()
+ resolve_ambari_config()
# Starting data cleanup daemon
data_cleaner = None
- if int(config.get('agent', 'data_cleanup_interval')) > 0:
+ if config.has_option('agent', 'data_cleanup_interval') and int(config.get('agent','data_cleanup_interval')) > 0:
data_cleaner = DataCleaner(config)
data_cleaner.start()
perform_prestart_checks(expected_hostname)
- daemonize()
+
+ if not IS_WINDOWS:
+ daemonize()
# Starting ping port listener
try:
@@ -264,15 +253,19 @@ def main():
logger.warn("Unable to determine the IP address of the Ambari server '%s'", server_hostname)
# Wait until server is reachable
- netutil = NetUtil()
- netutil.try_to_connect(server_url, -1, logger)
-
- # Launch Controller communication
- controller = Controller(config)
- controller.start()
- controller.join()
- stop_agent()
+ netutil = NetUtil(heartbeat_stop_callback)
+ retries, connected = netutil.try_to_connect(server_url, -1, logger)
+ # Ambari Agent was stopped using stop event
+ if connected:
+ # Launch Controller communication
+ controller = Controller(config, heartbeat_stop_callback)
+ controller.start()
+ controller.join()
+ if not IS_WINDOWS:
+ stop_agent()
logger.info("finished")
if __name__ == "__main__":
- main()
+ heartbeat_stop_callback = bind_signal_handlers(agentPid)
+
+ main(heartbeat_stop_callback)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/main/python/ambari_agent/security.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/security.py b/ambari-agent/src/main/python/ambari_agent/security.py
index bc101b8..46eddca 100644
--- a/ambari-agent/src/main/python/ambari_agent/security.py
+++ b/ambari-agent/src/main/python/ambari_agent/security.py
@@ -27,12 +27,12 @@ import json
import pprint
import traceback
import hostname
+import platform
logger = logging.getLogger()
-GEN_AGENT_KEY = "openssl req -new -newkey rsa:1024 -nodes -keyout %(keysdir)s/%(hostname)s.key\
- -subj /OU=%(hostname)s/\
- -out %(keysdir)s/%(hostname)s.csr"
+GEN_AGENT_KEY = 'openssl req -new -newkey rsa:1024 -nodes -keyout "%(keysdir)s'+os.sep+'%(hostname)s.key" '\
+ '-subj /OU=%(hostname)s/ -out "%(keysdir)s'+os.sep+'%(hostname)s.csr"'
class VerifiedHTTPSConnection(httplib.HTTPSConnection):
@@ -141,30 +141,30 @@ class CachedHTTPSConnection:
class CertificateManager():
def __init__(self, config):
self.config = config
- self.keysdir = self.config.get('security', 'keysdir')
+ self.keysdir = os.path.abspath(self.config.get('security', 'keysdir'))
self.server_crt = self.config.get('security', 'server_crt')
self.server_url = 'https://' + self.config.get('server', 'hostname') + ':' \
+ self.config.get('server', 'url_port')
def getAgentKeyName(self):
- keysdir = self.config.get('security', 'keysdir')
+ keysdir = os.path.abspath(self.config.get('security', 'keysdir'))
return keysdir + os.sep + hostname.hostname(self.config) + ".key"
def getAgentCrtName(self):
- keysdir = self.config.get('security', 'keysdir')
+ keysdir = os.path.abspath(self.config.get('security', 'keysdir'))
return keysdir + os.sep + hostname.hostname(self.config) + ".crt"
def getAgentCrtReqName(self):
- keysdir = self.config.get('security', 'keysdir')
+ keysdir = os.path.abspath(self.config.get('security', 'keysdir'))
return keysdir + os.sep + hostname.hostname(self.config) + ".csr"
def getSrvrCrtName(self):
- keysdir = self.config.get('security', 'keysdir')
+ keysdir = os.path.abspath(self.config.get('security', 'keysdir'))
return keysdir + os.sep + "ca.crt"
def checkCertExists(self):
- s = self.config.get('security', 'keysdir') + os.sep + "ca.crt"
+ s = os.path.abspath(self.config.get('security', 'keysdir')) + os.sep + "ca.crt"
server_crt_exists = os.path.exists(s)
@@ -240,10 +240,14 @@ class CertificateManager():
def genAgentCrtReq(self):
generate_script = GEN_AGENT_KEY % {'hostname': hostname.hostname(self.config),
- 'keysdir': self.config.get('security', 'keysdir')}
+ 'keysdir' : os.path.abspath(self.config.get('security', 'keysdir'))}
logger.info(generate_script)
- p = subprocess.Popen([generate_script], shell=True, stdout=subprocess.PIPE)
- p.communicate()
+ if platform.system() == 'Windows':
+ p = subprocess.Popen(generate_script, stdout=subprocess.PIPE)
+ p.communicate()
+ else:
+ p = subprocess.Popen([generate_script], shell=True, stdout=subprocess.PIPE)
+ p.communicate()
def initSecurity(self):
self.checkCertExists()
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/main/python/ambari_agent/shell.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/shell.py b/ambari-agent/src/main/python/ambari_agent/shell.py
index 4081bb0..df6f0ca 100644
--- a/ambari-agent/src/main/python/ambari_agent/shell.py
+++ b/ambari-agent/src/main/python/ambari_agent/shell.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+# !/usr/bin/env python
'''
Licensed to the Apache Software Foundation (ASF) under one
@@ -29,26 +29,79 @@ import time
import traceback
import AmbariConfig
import pprint
+import platform
-try:
+if platform.system() != "Windows":
+ try:
import pwd
-except ImportError:
+ except ImportError:
import winpwd as pwd
-global serverTracker
-serverTracker = {}
logger = logging.getLogger()
+shellRunner = None
threadLocal = threading.local()
-gracefull_kill_delay = 5 # seconds between SIGTERM and SIGKILL
-tempFiles = []
+gracefull_kill_delay = 5 # seconds between SIGTERM and SIGKILL
+
+tempFiles = []
+
+
def noteTempFile(filename):
tempFiles.append(filename)
+
def getTempFiles():
return tempFiles
-def kill_process_with_children(parent_pid):
+
+class _dict_to_object:
+ def __init__(self, entries):
+ self.__dict__.update(entries)
+
+ def __getitem__(self, item):
+ return self.__dict__[item]
+
+
+# windows specific code
+def _kill_process_with_children_windows(parent_pid):
+ shellRunner().run(["taskkill", "/T", "/PID", "{0}".format(parent_pid)])
+
+
+class shellRunnerWindows:
+ # Run any command
+ def run(self, script, user=None):
+ logger.warn("user argument ignored on windows")
+ code = 0
+ if not isinstance(script, list):
+ cmd = " "
+ cmd = cmd.join(script)
+ else:
+ cmd = script
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, shell=False)
+ out, err = p.communicate()
+ code = p.wait()
+ logger.debug("Exitcode for %s is %d" % (cmd, code))
+ return {'exitCode': code, 'output': out, 'error': err}
+
+ def runPowershell(self, file=None, script_block=None, args=[]):
+ logger.warn("user argument ignored on windows")
+ code = 0
+ cmd = None
+ if file:
+ cmd = ['powershell', '-WindowStyle', 'Hidden', '-File', file] + args
+ elif script_block:
+ cmd = ['powershell', '-WindowStyle', 'Hidden', '-Command', script_block] + args
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, shell=False)
+ out, err = p.communicate()
+ code = p.wait()
+ logger.debug("Exitcode for %s is %d" % (cmd, code))
+ return _dict_to_object({'exitCode': code, 'output': out, 'error': err})
+
+
+#linux specific code
+def _kill_process_with_children_linux(parent_pid):
def kill_tree_function(pid, signal):
'''
Kills process tree starting from a given pid.
@@ -58,15 +111,17 @@ def kill_process_with_children(parent_pid):
# a given PID and then passes list of "kill -<SIGNAL> PID" commands to 'sh'
# shell.
CMD = """ps xf | awk -v PID=""" + str(pid) + \
- """ ' $1 == PID { P = $1; next } P && /_/ { P = P " " $1;""" + \
- """K=P } P && !/_/ { P="" } END { print "kill -""" \
- + str(signal) + """ "K }' | sh """
+ """ ' $1 == PID { P = $1; next } P && /_/ { P = P " " $1;""" + \
+ """K=P } P && !/_/ { P="" } END { print "kill -""" \
+ + str(signal) + """ "K }' | sh """
process = subprocess.Popen(CMD, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
process.communicate()
- run_kill_function(kill_tree_function, parent_pid)
-def run_kill_function(kill_function, pid):
+ _run_kill_function(kill_tree_function, parent_pid)
+
+
+def _run_kill_function(kill_function, pid):
try:
kill_function(pid, signal.SIGTERM)
except Exception, e:
@@ -81,17 +136,19 @@ def run_kill_function(kill_function, pid):
logger.error("Failed to send SIGKILL to PID %d. Process exited?" % (pid))
logger.error("Reported error: " + repr(e))
-def changeUid():
+
+def _changeUid():
try:
os.setuid(threadLocal.uid)
except Exception:
logger.warn("can not switch user for running command.")
-class shellRunner:
+
+class shellRunnerLinux:
# Run any command
def run(self, script, user=None):
try:
- if user!=None:
+ if user != None:
user = pwd.getpwnam(user)[2]
else:
user = os.getuid()
@@ -101,12 +158,28 @@ class shellRunner:
code = 0
cmd = " "
cmd = cmd.join(script)
- p = subprocess.Popen(cmd, preexec_fn=changeUid, stdout=subprocess.PIPE,
+ p = subprocess.Popen(cmd, preexec_fn=_changeUid, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True, close_fds=True)
out, err = p.communicate()
code = p.wait()
- logger.debug("Exitcode for %s is %d" % (cmd,code))
+ logger.debug("Exitcode for %s is %d" % (cmd, code))
return {'exitCode': code, 'output': out, 'error': err}
- def getServerTracker(self):
- return serverTracker
\ No newline at end of file
+
+def kill_process_with_children(parent_pid):
+ if platform.system() == "Windows":
+ _kill_process_with_children_windows(parent_pid)
+ else:
+ _kill_process_with_children_linux(parent_pid)
+
+def changeUid():
+ if not platform.system() == "Windows":
+ try:
+ os.setuid(threadLocal.uid)
+ except Exception:
+ logger.warn("can not switch user for running command.")
+
+if platform.system() == "Windows":
+ shellRunner = shellRunnerWindows
+else:
+ shellRunner = shellRunnerLinux
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/packages/windows.xml
----------------------------------------------------------------------
diff --git a/ambari-agent/src/packages/windows.xml b/ambari-agent/src/packages/windows.xml
new file mode 100644
index 0000000..1abca20
--- /dev/null
+++ b/ambari-agent/src/packages/windows.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd">
+ <!--This 'all' id is not appended to the produced bundle because we do this:
+ http://maven.apache.org/plugins/maven-assembly-plugin/faq.html#required-classifiers
+ -->
+ <id>windows-dist</id>
+ <formats>
+ <format>dir</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/python/ambari_agent</directory>
+ <outputDirectory>/sbin/ambari_agent</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/../ambari-common/src/main/python/resource_management</directory>
+ <outputDirectory>/sbin/resource_management</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/../ambari-common/src/main/python/ambari_commons</directory>
+ <outputDirectory>/sbin/ambari_commons</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/../ambari-common/src/main/python/ambari_jinja2/ambari_jinja2</directory>
+ <outputDirectory>/sbin/ambari_jinja2</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/conf/windows</directory>
+ <outputDirectory>/</outputDirectory>
+ <excludes>
+ <exclude>service_wrapper.py</exclude>
+ <exclude>createservice.ps1</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/conf/windows</directory>
+ <outputDirectory>/sbin</outputDirectory>
+ <includes>
+ <include>service_wrapper.py</include>
+ <include>createservice.ps1</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>${target.cache.dir}</directory>
+ <outputDirectory>/cache</outputDirectory>
+ </fileSet>
+ <!--empty directory-->
+ <fileSet>
+ <directory>./</directory>
+ <outputDirectory>/keys</outputDirectory>
+ <excludes>
+ <exclude>*/**</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+ <files>
+ <file>
+ <source>${project.basedir}/../version</source>
+ <outputDirectory>data</outputDirectory>
+ <filtered>true</filtered>
+ </file>
+ </files>
+</assembly>
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestAlerts.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestAlerts.py b/ambari-agent/src/test/python/ambari_agent/TestAlerts.py
index 9bbcf3b..d3e4583 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestAlerts.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestAlerts.py
@@ -18,9 +18,10 @@ See the License for the specific language governing permissions and
limitations under the License.
'''
+from stacks.utils.RMFTestCase import *
+import os
import socket
import sys
-import os
from ambari_agent.AlertSchedulerHandler import AlertSchedulerHandler
from ambari_agent.alerts.collector import AlertCollector
@@ -429,12 +430,12 @@ class TestAlerts(TestCase):
ash = AlertSchedulerHandler(test_file_path, test_stack_path, test_host_scripts_path)
ash.start()
-
+
self.assertEquals(1, ash.get_job_count())
ash.reschedule()
self.assertEquals(1, ash.get_job_count())
-
-
+
+
def test_alert_collector_purge(self):
json = { "name": "namenode_process",
"service": "HDFS",
@@ -466,13 +467,13 @@ class TestAlerts(TestCase):
self.assertEquals(6, pa.interval())
res = pa.collect()
-
+
self.assertTrue(collector.alerts()[0] is not None)
self.assertEquals('CRITICAL', collector.alerts()[0]['state'])
-
+
collector.remove_by_uuid('c1f73191-4481-4435-8dae-fd380e4c0be1')
self.assertEquals(0,len(collector.alerts()))
-
+
def test_disabled_definitions(self):
test_file_path = os.path.join('ambari_agent', 'dummy_files')
@@ -509,24 +510,23 @@ class TestAlerts(TestCase):
pa = PortAlert(json, json['source'])
ash.schedule_definition(pa)
-
+
self.assertEquals(2, ash.get_job_count())
-
+
json['enabled'] = False
pa = PortAlert(json, json['source'])
ash.schedule_definition(pa)
-
+
# verify disabled alert not scheduled
self.assertEquals(2, ash.get_job_count())
-
+
json['enabled'] = True
pa = PortAlert(json, json['source'])
ash.schedule_definition(pa)
-
+
# verify enabled alert was scheduled
self.assertEquals(3, ash.get_job_count())
-
def test_immediate_alert(self):
test_file_path = os.path.join('ambari_agent', 'dummy_files')
test_stack_path = os.path.join('ambari_agent', 'dummy_files')
@@ -538,10 +538,10 @@ class TestAlerts(TestCase):
self.assertEquals(1, ash.get_job_count())
self.assertEquals(0, len(ash._collector.alerts()))
- execution_commands = [ {
+ execution_commands = [ {
"clusterName": "c1",
- "hostName": "c6401.ambari.apache.org",
- "alertDefinition": {
+ "hostName": "c6401.ambari.apache.org",
+ "alertDefinition": {
"name": "namenode_process",
"service": "HDFS",
"component": "NAMENODE",
@@ -565,7 +565,7 @@ class TestAlerts(TestCase):
}
}
} ]
-
+
# execute the alert immediately and verify that the collector has the result
ash.execute_alert(execution_commands)
self.assertEquals(1, len(ash._collector.alerts()))
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestCertGeneration.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestCertGeneration.py b/ambari-agent/src/test/python/ambari_agent/TestCertGeneration.py
index 8e01707..c724c31 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestCertGeneration.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestCertGeneration.py
@@ -45,4 +45,3 @@ class TestCertGeneration(TestCase):
def tearDown(self):
shutil.rmtree(self.tmpdir)
-
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestController.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestController.py b/ambari-agent/src/test/python/ambari_agent/TestController.py
index 72b0cea..240d808 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestController.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestController.py
@@ -385,7 +385,7 @@ class TestController(unittest.TestCase):
hearbeat = MagicMock()
self.controller.heartbeat = hearbeat
-
+ event_mock.return_value = False
dumpsMock.return_value = "data"
sendRequest = MagicMock(name="sendRequest")
@@ -512,7 +512,7 @@ class TestController(unittest.TestCase):
response["restartAgent"] = "false"
self.controller.heartbeatWithServer()
- sleepMock.assert_called_with(
+ event_mock.assert_any_call(timeout=
self.controller.netutil.MINIMUM_INTERVAL_BETWEEN_HEARTBEATS)
# Check that server continues to heartbeat after connection errors
@@ -533,7 +533,7 @@ class TestController(unittest.TestCase):
self.controller.heartbeatWithServer()
self.assertTrue(sendRequest.call_count > 5)
- sleepMock.assert_called_with(
+ event_mock.assert_called_with(timeout=
self.controller.netutil.MINIMUM_INTERVAL_BETWEEN_HEARTBEATS)
sys.stdout = sys.__stdout__
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py b/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
index 5f426e6..24ee259 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py
@@ -95,7 +95,8 @@ class TestCustomServiceOrchestrator(TestCase):
'clusterHostInfo':{'namenode_host' : ['1'],
'slave_hosts' : ['0', '1'],
'all_hosts' : ['h1.hortonworks.com', 'h2.hortonworks.com'],
- 'all_ping_ports': ['8670:0,1']}
+ 'all_ping_ports': ['8670:0,1']},
+ 'hostLevelParams':{}
}
decompress_cluster_host_info_mock.return_value = {'namenode_host' : ['h2.hortonworks.com'],
@@ -315,15 +316,15 @@ class TestCustomServiceOrchestrator(TestCase):
self.assertTrue(os.path.exists(err))
os.remove(out)
os.remove(err)
-
+
from ambari_agent.StackVersionsFileHandler import StackVersionsFileHandler
-
+
@patch("shell.kill_process_with_children")
@patch.object(FileCache, "__init__")
@patch.object(CustomServiceOrchestrator, "resolve_script_path")
@patch.object(CustomServiceOrchestrator, "resolve_hook_script_path")
@patch.object(StackVersionsFileHandler, "read_stack_version")
- def test_cancel_backgound_command(self, read_stack_version_mock, resolve_hook_script_path_mock, resolve_script_path_mock, FileCache_mock,
+ def test_cancel_backgound_command(self, read_stack_version_mock, resolve_hook_script_path_mock, resolve_script_path_mock, FileCache_mock,
kill_process_with_children_mock):
FileCache_mock.return_value = None
FileCache_mock.cache_dir = MagicMock()
@@ -334,9 +335,9 @@ class TestCustomServiceOrchestrator(TestCase):
cfg.set('agent', 'tolerate_download_failures', 'true')
cfg.set('agent', 'prefix', '.')
cfg.set('agent', 'cache_dir', 'background_tasks')
-
+
actionQueue = ActionQueue(cfg, dummy_controller)
-
+
dummy_controller.actionQueue = actionQueue
orchestrator = CustomServiceOrchestrator(cfg, dummy_controller)
orchestrator.file_cache = MagicMock()
@@ -344,42 +345,42 @@ class TestCustomServiceOrchestrator(TestCase):
return ""
orchestrator.file_cache.get_service_base_dir = f
actionQueue.customServiceOrchestrator = orchestrator
-
+
import TestActionQueue
import copy
-
+
TestActionQueue.patch_output_file(orchestrator.python_executor)
orchestrator.python_executor.prepare_process_result = MagicMock()
orchestrator.dump_command_to_json = MagicMock()
-
+
lock = threading.RLock()
complete_done = threading.Condition(lock)
-
+
complete_was_called = {}
def command_complete_w(process_condenced_result, handle):
with lock:
complete_was_called['visited']= ''
complete_done.wait(3)
-
- actionQueue.on_background_command_complete_callback = TestActionQueue.wraped(actionQueue.on_background_command_complete_callback, command_complete_w, None)
+
+ actionQueue.on_background_command_complete_callback = TestActionQueue.wraped(actionQueue.on_background_command_complete_callback, command_complete_w, None)
execute_command = copy.deepcopy(TestActionQueue.TestActionQueue.background_command)
actionQueue.put([execute_command])
actionQueue.processBackgroundQueueSafeEmpty()
-
- time.sleep(.1)
-
+
+ time.sleep(.1)
+
orchestrator.cancel_command(19,'')
self.assertTrue(kill_process_with_children_mock.called)
kill_process_with_children_mock.assert_called_with(33)
-
+
with lock:
complete_done.notifyAll()
with lock:
self.assertTrue(complete_was_called.has_key('visited'))
-
+
time.sleep(.1)
-
+
runningCommand = actionQueue.commandStatuses.get_command_status(19)
self.assertTrue(runningCommand is not None)
self.assertEqual(runningCommand['status'], ActionQueue.FAILED_STATUS)
@@ -501,12 +502,12 @@ class TestCustomServiceOrchestrator(TestCase):
}
dummy_controller = MagicMock()
orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
-
+
import TestActionQueue
TestActionQueue.patch_output_file(orchestrator.python_executor)
orchestrator.python_executor.condenseOutput = MagicMock()
orchestrator.dump_command_to_json = MagicMock()
-
+
ret = orchestrator.runCommand(command, "out.txt", "err.txt")
self.assertEqual(ret['exitcode'], 777)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestHostname.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestHostname.py b/ambari-agent/src/test/python/ambari_agent/TestHostname.py
index 7d1f3c6..993a9d1 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestHostname.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestHostname.py
@@ -34,7 +34,7 @@ class TestHostname(TestCase):
hostname.cached_hostname = None
hostname.cached_public_hostname = None
config = AmbariConfig()
- self.assertEquals(hostname.hostname(config), socket.getfqdn(),
+ self.assertEquals(hostname.hostname(config), socket.getfqdn().lower(),
"hostname should equal the socket-based hostname")
pass
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestMain.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestMain.py b/ambari-agent/src/test/python/ambari_agent/TestMain.py
index f930c4a..bb75bac 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestMain.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestMain.py
@@ -52,23 +52,22 @@ class TestMain(unittest.TestCase):
sys.stdout = sys.__stdout__
+ @patch("ambari_agent.HeartbeatStopHandler_linux")
@patch("os._exit")
@patch("os.getpid")
@patch.object(ProcessHelper, "stopAgent")
- def test_signal_handler(self, stopAgent_mock, os_getpid_mock, os_exit_mock):
+ def test_signal_handler(self, stopAgent_mock, os_getpid_mock, os_exit_mock, heartbeat_handler_mock):
# testing exit of children
main.agentPid = 4444
os_getpid_mock.return_value = 5555
main.signal_handler("signum", "frame")
- self.assertTrue(os_exit_mock.called)
-
+ heartbeat_handler_mock.set_stop.assert_called()
os_exit_mock.reset_mock()
# testing exit of main process
os_getpid_mock.return_value = main.agentPid
main.signal_handler("signum", "frame")
- self.assertFalse(os_exit_mock.called)
- self.assertTrue(stopAgent_mock.called)
+ heartbeat_handler_mock.set_stop.assert_called()
@patch.object(main.logger, "addHandler")
@@ -122,7 +121,7 @@ class TestMain(unittest.TestCase):
@patch("signal.signal")
def test_bind_signal_handlers(self, signal_mock):
- main.bind_signal_handlers()
+ main.bind_signal_handlers(os.getpid())
# Check if on SIGINT/SIGTERM agent is configured to terminate
signal_mock.assert_any_call(signal.SIGINT, main.signal_handler)
signal_mock.assert_any_call(signal.SIGTERM, main.signal_handler)
@@ -269,7 +268,7 @@ class TestMain(unittest.TestCase):
@patch.object(main, "setup_logging")
@patch.object(main, "bind_signal_handlers")
@patch.object(main, "stop_agent")
- @patch.object(main, "resolve_ambari_config")
+ @patch.object(AmbariConfig, "getConfigFile")
@patch.object(main, "perform_prestart_checks")
@patch.object(main, "daemonize")
@patch.object(main, "update_log_level")
@@ -285,21 +284,25 @@ class TestMain(unittest.TestCase):
def test_main(self, ping_port_init_mock, ping_port_start_mock, data_clean_init_mock,data_clean_start_mock,
parse_args_mock, join_mock, start_mock, Controller_init_mock, try_to_connect_mock,
update_log_level_mock, daemonize_mock, perform_prestart_checks_mock,
- resolve_ambari_config_mock, stop_mock, bind_signal_handlers_mock,
+ ambari_config_mock,
+ stop_mock, bind_signal_handlers_mock,
setup_logging_mock, socket_mock):
data_clean_init_mock.return_value = None
Controller_init_mock.return_value = None
ping_port_init_mock.return_value = None
options = MagicMock()
parse_args_mock.return_value = (options, MagicMock)
-
+ try_to_connect_mock.return_value = (0, True)
+ # use default unix config
+ ambari_config_mock.return_value = os.path.abspath("../../../conf/unix/ambari-agent.ini")
#testing call without command-line arguments
+
main.main()
self.assertTrue(setup_logging_mock.called)
self.assertTrue(bind_signal_handlers_mock.called)
self.assertTrue(stop_mock.called)
- self.assertTrue(resolve_ambari_config_mock.called)
+ #self.assertTrue(resolve_ambari_config_mock.called)
self.assertTrue(perform_prestart_checks_mock.called)
self.assertTrue(daemonize_mock.called)
self.assertTrue(update_log_level_mock.called)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestNetUtil.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestNetUtil.py b/ambari-agent/src/test/python/ambari_agent/TestNetUtil.py
index 474548f..255da88 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestNetUtil.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestNetUtil.py
@@ -21,6 +21,7 @@ limitations under the License.
from ambari_agent import NetUtil
from mock.mock import MagicMock, patch
import unittest
+import threading
class TestNetUtil(unittest.TestCase):
@@ -51,15 +52,17 @@ class TestNetUtil(unittest.TestCase):
@patch("time.sleep")
- def test_try_to_connect(self, sleepMock):
-
+ @patch.object(threading._Event, "wait")
+ def test_try_to_connect(self, event_mock,
+ sleepMock):
+ event_mock.return_value = False
netutil = NetUtil.NetUtil()
checkURL = MagicMock(name="checkURL")
checkURL.return_value = True, "test"
netutil.checkURL = checkURL
# one successful get
- self.assertEqual(0, netutil.try_to_connect("url", 10))
+ self.assertEqual((0, True), netutil.try_to_connect("url", 10))
# got successful after N retries
gets = [[True, ""], [False, ""], [False, ""]]
@@ -67,9 +70,9 @@ class TestNetUtil(unittest.TestCase):
def side_effect(*args):
return gets.pop()
checkURL.side_effect = side_effect
- self.assertEqual(2, netutil.try_to_connect("url", 10))
+ self.assertEqual((2, True), netutil.try_to_connect("url", 10))
# max retries
checkURL.side_effect = None
checkURL.return_value = False, "test"
- self.assertEqual(5, netutil.try_to_connect("url", 5))
+ self.assertEqual((5,False), netutil.try_to_connect("url", 5))
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/ambari_agent/TestStatusCheck.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestStatusCheck.py b/ambari-agent/src/test/python/ambari_agent/TestStatusCheck.py
index 50657d8..a872e7f 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestStatusCheck.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestStatusCheck.py
@@ -47,7 +47,7 @@ class TestStatusCheck(TestCase):
def setUp(self):
- self.pidPathesVars = [
+ self.pidPathVars = [
{'var' : '',
'defaultValue' : PID_DIR}
]
@@ -84,7 +84,7 @@ class TestStatusCheck(TestCase):
@patch.object(StatusCheck, 'getIsLive')
def test_live(self, get_is_live_mock):
- statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
self.assertTrue(StatusCheck.USER_PATTERN in self.serviceToPidDict[COMPONENT_LIVE])
@@ -108,11 +108,11 @@ class TestStatusCheck(TestCase):
logger_info_mock.side_effect = my_side_effect
# call this three times
- statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
- statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
- statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
# logged not more then once
self.assert_(TestStatusCheck.timesLogged <= 1, "test_dont_relog_serToPidDict logged more then once")
@@ -129,7 +129,7 @@ class TestStatusCheck(TestCase):
self.pidFilesDict[one_more_pid_file_name] = one_more_pid_full_path
self.is_live_values[one_more_pid_full_path] = False
- statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
statusCheck.pidFilesDict = self.pidFilesDict
@@ -149,7 +149,7 @@ class TestStatusCheck(TestCase):
badServiceToPidDict = self.serviceToPidDict.copy()
badServiceToPidDict['BAD_COMPONENT'] = 'prefix' + StatusCheck.USER_PATTERN
- statusCheck = StatusCheck(badServiceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(badServiceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
statusCheck.pidFilesDict = self.pidFilesDict
@@ -162,7 +162,7 @@ class TestStatusCheck(TestCase):
# Ensure that status checker return False for dead process
@patch.object(StatusCheck, 'getIsLive')
def test_dead(self, get_is_live_mock):
- statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathesVars,
+ statusCheck = StatusCheck(self.serviceToPidDict, self.pidPathVars,
self.globalConfig, self.servicesToLinuxUser)
statusCheck.pidFilesDict = self.pidFilesDict
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/resource_management/TestContentSources.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestContentSources.py b/ambari-agent/src/test/python/resource_management/TestContentSources.py
index 1c5e8a8..d09df44 100644
--- a/ambari-agent/src/test/python/resource_management/TestContentSources.py
+++ b/ambari-agent/src/test/python/resource_management/TestContentSources.py
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
'''
-
+from stacks.utils.RMFTestCase import *
from unittest import TestCase
from mock.mock import patch, MagicMock
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/resource_management/TestDirectoryResource.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestDirectoryResource.py b/ambari-agent/src/test/python/resource_management/TestDirectoryResource.py
index 866486e..5a63891 100644
--- a/ambari-agent/src/test/python/resource_management/TestDirectoryResource.py
+++ b/ambari-agent/src/test/python/resource_management/TestDirectoryResource.py
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
'''
-
+from stacks.utils.RMFTestCase import *
from unittest import TestCase
from mock.mock import patch, MagicMock
import os
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/resource_management/TestExecuteHadoopResource.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestExecuteHadoopResource.py b/ambari-agent/src/test/python/resource_management/TestExecuteHadoopResource.py
index d2ef71c..f5308d1 100644
--- a/ambari-agent/src/test/python/resource_management/TestExecuteHadoopResource.py
+++ b/ambari-agent/src/test/python/resource_management/TestExecuteHadoopResource.py
@@ -15,6 +15,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'''
+
+from stacks.utils.RMFTestCase import *
import os
from unittest import TestCase
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/resource_management/TestExecuteResource.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestExecuteResource.py b/ambari-agent/src/test/python/resource_management/TestExecuteResource.py
index f974b92..8423eec 100644
--- a/ambari-agent/src/test/python/resource_management/TestExecuteResource.py
+++ b/ambari-agent/src/test/python/resource_management/TestExecuteResource.py
@@ -16,6 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
'''
+from stacks.utils.RMFTestCase import *
from unittest import TestCase
from mock.mock import patch, MagicMock, call
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/resource_management/TestMonitorWebserverResource.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestMonitorWebserverResource.py b/ambari-agent/src/test/python/resource_management/TestMonitorWebserverResource.py
index 533ecaa..d5b2c42 100644
--- a/ambari-agent/src/test/python/resource_management/TestMonitorWebserverResource.py
+++ b/ambari-agent/src/test/python/resource_management/TestMonitorWebserverResource.py
@@ -16,6 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
'''
+from stacks.utils.RMFTestCase import *
from unittest import TestCase
from mock.mock import patch, MagicMock
from resource_management import *
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/resource_management/TestSubstituteVars.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestSubstituteVars.py b/ambari-agent/src/test/python/resource_management/TestSubstituteVars.py
index b3623cd..9e42f92 100644
--- a/ambari-agent/src/test/python/resource_management/TestSubstituteVars.py
+++ b/ambari-agent/src/test/python/resource_management/TestSubstituteVars.py
@@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'''
+
+from stacks.utils.RMFTestCase import *
from unittest import TestCase, main
from resource_management.libraries.functions.substitute_vars import substitute_vars
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-agent/src/test/python/unitTests.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/unitTests.py b/ambari-agent/src/test/python/unitTests.py
index 082e1a1..83b6bdf 100644
--- a/ambari-agent/src/test/python/unitTests.py
+++ b/ambari-agent/src/test/python/unitTests.py
@@ -23,7 +23,8 @@ import doctest
from os.path import dirname, split, isdir
import logging.handlers
import logging
-from random import shuffle
+#TODO Add an option to randomize the tests' execution
+#from random import shuffle
LOG_FILE_NAME='tests.log'
SELECTED_PREFIX = "_"
@@ -55,7 +56,8 @@ def all_tests_suite():
for directory in os.listdir(src_dir):
if os.path.isdir(directory):
files_list += os.listdir(src_dir + os.sep + directory)
- shuffle(files_list)
+ #TODO Add an option to randomize the tests' execution
+ #shuffle(files_list)
tests_list = []
logger.info('------------------------TESTS LIST:-------------------------------------')
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-client/groovy-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/pom.xml b/ambari-client/groovy-client/pom.xml
index fbedbd1..cc823de 100644
--- a/ambari-client/groovy-client/pom.xml
+++ b/ambari-client/groovy-client/pom.xml
@@ -87,6 +87,7 @@
<artifactId>apache-rat-plugin</artifactId>
<configuration>
<excludes>
+ <exclude>**/*.iml</exclude>
<exclude>src/main/resources/blueprints/**</exclude>
<exclude>src/test/resources/**</exclude>
</excludes>
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-client/python-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-client/python-client/pom.xml b/ambari-client/python-client/pom.xml
index 74fc0f5..e16bbc2 100644
--- a/ambari-client/python-client/pom.xml
+++ b/ambari-client/python-client/pom.xml
@@ -75,7 +75,7 @@
<executions>
<execution>
<configuration>
- <executable>${project.basedir}/../../ambari-common/src/main/unix/ambari-python-wrap</executable>
+ <executable>python</executable>
<workingDirectory>src/test/python</workingDirectory>
<arguments>
<argument>unitTests.py</argument>
@@ -93,7 +93,7 @@
</execution>
<execution>
<configuration>
- <executable>${project.basedir}/../../ambari-common/src/main/unix/ambari-python-wrap</executable>
+ <executable>python</executable>
<workingDirectory>target/python-client-${project.version}</workingDirectory>
<arguments>
<argument>${project.basedir}/src/main/python/setup.py</argument>
@@ -115,7 +115,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
- <version>2.0.1</version>
+ <version>2.1-alpha-2</version>
<executions>
<execution>
<phase>none</phase>
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/ambari_service.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/ambari_service.py b/ambari-common/src/main/python/ambari_commons/ambari_service.py
new file mode 100644
index 0000000..8418e74
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/ambari_service.py
@@ -0,0 +1,79 @@
+'''
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+'''
+
+import os
+
+import win32service
+
+from ambari_commons.os_windows import WinService
+
+
+AMBARI_VERSION_VAR = "AMBARI_VERSION_VAR"
+
+ENV_PYTHON_PATH = "PYTHONPATH"
+
+
+class AmbariService(WinService):
+ _svc_name_ = "Ambari Service"
+ _svc_display_name_ = "Ambari Service"
+ _svc_description_ = "Ambari Service"
+
+ # Sets the current dir and adjusts the PYTHONPATH env variable before calling SvcDoRun()
+ def SvcRun(self):
+ self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
+
+ import servicemanager
+
+ parser = self._InitOptionsParser()
+ (self.options, args) = parser.parse_args()
+
+ try:
+ is_debugging = servicemanager.Debugging()
+ except:
+ is_debugging = False
+
+ if not is_debugging:
+ # Save the current dir, or the script dir if none set (typical for services)
+ script_path = os.path.dirname(__file__.replace('/', os.sep))
+ # the script resides in the sbin/ambari_commons subdir
+ self.options.current_dir = os.path.normpath(script_path + "\\..\\..")
+ os.chdir(self.options.current_dir)
+
+ python_path = os.path.normpath(script_path + "\\..")
+
+ #update the environment vars: set PYTHONPATH = $script_dir\sbin;%PYTHONPATH%
+ if os.environ.has_key(ENV_PYTHON_PATH):
+ python_path += os.pathsep + os.environ[ENV_PYTHON_PATH]
+ os.environ[ENV_PYTHON_PATH] = python_path
+
+ self.SvcDoRun()
+ pass
+
+ # Call during initialization to implement standard service versioning
+ @classmethod
+ def _AdjustServiceVersion(cls):
+ if os.environ.has_key(AMBARI_VERSION_VAR):
+ ambariVer = os.environ[AMBARI_VERSION_VAR]
+ else:
+ ambariVer = "1.3.0-SNAPSHOT"
+ AmbariService._svc_display_name_ += "-" + ambariVer
+ AmbariService._svc_description_ += " v" + ambariVer
+
+ # Override to customize the command-line arguments
+ def _InitOptionsParser(self):
+ pass
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/exceptions.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/exceptions.py b/ambari-common/src/main/python/ambari_commons/exceptions.py
new file mode 100644
index 0000000..c5ed85d
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/exceptions.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+'''
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+'''
+
+class FatalException(Exception):
+ def __init__(self, code, reason):
+ self.code = code
+ self.reason = reason
+
+ def __str__(self):
+ return repr("Fatal exception: %s, exit code %s" % (self.reason, self.code))
+
+
+class NonFatalException(Exception):
+ def __init__(self, reason):
+ self.reason = reason
+
+ def __str__(self):
+ return repr("NonFatal exception: %s" % self.reason)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/inet_utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/inet_utils.py b/ambari-common/src/main/python/ambari_commons/inet_utils.py
new file mode 100644
index 0000000..2a54cb6
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/inet_utils.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+'''
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+'''
+
+import os
+import sys
+import urllib2
+
+from exceptions import *
+from logging_utils import *
+
+def download_file(link, destination, chunk_size=16 * 1024):
+ print_info_msg("Downloading {0} to {1}".format(link, destination))
+ if os.path.exists(destination):
+ print_warning_msg("File {0} already exists, assuming it was downloaded before".format(destination))
+ return
+
+ force_download_file(link, destination, chunk_size)
+
+
+def download_progress(file_name, downloaded_size, blockSize, totalSize):
+ percent = int(downloaded_size * 100 / totalSize)
+ status = "\r" + file_name
+
+ if totalSize < blockSize:
+ status += "... %d%%" % (100)
+ else:
+ status += "... %d%% (%.1f MB of %.1f MB)" % (
+ percent, downloaded_size / 1024 / 1024.0, totalSize / 1024 / 1024.0)
+ sys.stdout.write(status)
+ sys.stdout.flush()
+
+
+def find_range_components(meta):
+ file_size = 0
+ seek_pos = 0
+ hdr_range = meta.getheaders("Content-Range")
+ if len(hdr_range) > 0:
+ range_comp1 = hdr_range[0].split('/')
+ if len(range_comp1) > 1:
+ range_comp2 = range_comp1[0].split(' ') #split away the "bytes" prefix
+ if len(range_comp2) == 0:
+ raise FatalException(12, 'Malformed Content-Range response header: "{}".' % hdr_range)
+ range_comp3 = range_comp2[1].split('-')
+ seek_pos = int(range_comp3[0])
+ if range_comp1[1] != '*': #'*' == unknown length
+ file_size = int(range_comp1[1])
+
+ if file_size == 0:
+ #Try the old-fashioned way
+ hdrLen = meta.getheaders("Content-Length")
+ if len(hdrLen) == 0:
+ raise FatalException(12, "Response header doesn't contain Content-Length. Chunked Transfer-Encoding is not supported for now.")
+ file_size = int(hdrLen[0])
+
+ return (file_size, seek_pos)
+
+
+def force_download_file(link, destination, chunk_size = 16 * 1024, progress_func = download_progress):
+ request = urllib2.Request(link)
+
+ if os.path.exists(destination) and not os.path.isfile(destination):
+ #Directory specified as target? Must be a mistake. Bail out, don't assume anything.
+ err = 'Download target {} is a directory.' % destination
+ raise FatalException(1, err)
+
+ (dest_path, file_name) = os.path.split(destination)
+
+ temp_dest = destination + ".tmpdownload"
+ partial_size = 0
+
+ if os.path.exists(temp_dest):
+ #Support for resuming downloads, in case the process is killed while downloading a file
+ # set resume range
+ # See http://stackoverflow.com/questions/6963283/python-urllib2-resume-download-doesnt-work-when-network-reconnects
+ partial_size = os.stat(temp_dest).st_size
+ if partial_size > chunk_size:
+ #Re-download the last chunk, to minimize the possibilities of file corruption
+ resume_pos = partial_size - chunk_size
+ request.add_header("Range", "bytes=%s-" % resume_pos)
+ else:
+ #Make sure the full dir structure is in place, otherwise file open will fail
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+
+ response = urllib2.urlopen(request)
+ (file_size, seek_pos) = find_range_components(response.info())
+
+ print_info_msg("Downloading to: %s Bytes: %s" % (destination, file_size))
+
+ if partial_size < file_size:
+ if seek_pos == 0:
+ #New file, create it
+ open_mode = 'wb'
+ else:
+ #Resuming download of an existing file
+ open_mode = 'rb+' #rb+ doesn't create the file, using wb to create it
+ f = open(temp_dest, open_mode)
+
+ try:
+ #Resume the download from where it left off
+ if seek_pos > 0:
+ f.seek(seek_pos)
+
+ file_size_dl = seek_pos
+ while True:
+ buffer = response.read(chunk_size)
+ if not buffer:
+ break
+
+ file_size_dl += len(buffer)
+ f.write(buffer)
+
+ progress_func(file_name, file_size_dl, chunk_size, file_size)
+ finally:
+ f.close()
+
+ sys.stdout.write('\n')
+ sys.stdout.flush()
+
+ print_info_msg("Finished downloading {0} to {1}".format(link, destination))
+
+ downloaded_size = os.stat(temp_dest).st_size
+ if downloaded_size != file_size:
+ err = 'Size of downloaded file {} is {} bytes, it is probably damaged or incomplete' % (destination, downloaded_size)
+ raise FatalException(1, err)
+
+ # when download is complete -> mv temp_dest destination
+ if os.path.exists(destination):
+ #Windows behavior: rename fails if the destination file exists
+ os.unlink(destination)
+ os.rename(temp_dest, destination)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/logging_utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/logging_utils.py b/ambari-common/src/main/python/ambari_commons/logging_utils.py
new file mode 100644
index 0000000..9d45fdb
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/logging_utils.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+'''
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+'''
+
+VERBOSE = False
+SILENT = False
+DEBUG_MODE = False
+
+# terminal styles
+BOLD_ON = '\033[1m'
+BOLD_OFF = '\033[0m'
+
+#
+# Prints an "info" messsage.
+#
+def print_info_msg(msg):
+ if VERBOSE:
+ print("INFO: " + msg)
+
+#
+# Prints an "error" messsage.
+#
+def print_error_msg(msg):
+ print("ERROR: " + msg)
+
+#
+# Prints a "warning" messsage.
+#
+def print_warning_msg(msg, bold=False):
+ if bold:
+ print(BOLD_ON + "WARNING: " + msg + BOLD_OFF)
+ else:
+ print("WARNING: " + msg)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/os_check.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/os_check.py b/ambari-common/src/main/python/ambari_commons/os_check.py
index 78cf784..03e94c4 100644
--- a/ambari-common/src/main/python/ambari_commons/os_check.py
+++ b/ambari-common/src/main/python/ambari_commons/os_check.py
@@ -36,16 +36,40 @@ def linux_distribution():
PYTHON_VER = sys.version_info[0] * 10 + sys.version_info[1]
if PYTHON_VER < 26:
- linux_distribution = platform.dist()
+ (distname, version, id) = platform.dist()
elif os.path.exists('/etc/redhat-release'):
- linux_distribution = platform.dist()
+ (distname, version, id) = platform.dist()
else:
- linux_distribution = platform.linux_distribution()
+ (distname, version, id) = platform.linux_distribution()
- return linux_distribution
+ return (platform.system(), os.name, distname, version, id)
+def windows_distribution():
+ from os_windows import get_windows_version
+
+ # Only support Windows Server 64 bit
+ (win_release, win_version, win_csd, win_ptype) = platform.win32_ver()
+
+ if win_version.startswith("6.2."):
+ # win32_ver() doesn't work correctly for Windows Server 2012 R2 and Windows 8.1
+ (win_ver_major, win_ver_minor, win_ver_build) = get_windows_version()
+ if win_ver_major == 6 and win_ver_minor == 3:
+ win_release = "2012ServerR2"
+ win_version = "%d.%d.%d" % (win_ver_major, win_ver_minor, win_ver_build)
+
+ #if win_version
+ return (platform.system(), os.name, "win" + win_release, win_version, win_ptype)
class OS_CONST_TYPE(type):
+ # os platforms
+ LINUX_OS = 'linux'
+ WINDOWS_OS = 'windows'
+
+ # os families
+ REDHAT_FAMILY = 'redhat'
+ DEBIAN_FAMILY = 'debian'
+ SUSE_FAMILY = 'suse'
+ WINSRV_FAMILY = 'winsrv'
# Declare here os type mapping
OS_FAMILY_COLLECTION = []
@@ -58,7 +82,8 @@ class OS_CONST_TYPE(type):
Initialize internal data structures from file
"""
try:
- f = open(os.path.join(RESOURCES_DIR, OSFAMILY_JSON_RESOURCE))
+ fpath = os.path.join(RESOURCES_DIR, OSFAMILY_JSON_RESOURCE)
+ f = open(fpath)
json_data = json.load(f)
f.close()
for family in json_data:
@@ -69,7 +94,7 @@ class OS_CONST_TYPE(type):
'os_list': json_data[family][JSON_OS_TYPE]
}]
except:
- raise Exception("Couldn't load '%s' file" % OSFAMILY_JSON_RESOURCE)
+ raise Exception("Couldn't load '%s' file" % fpath)
def __init__(cls, name, bases, dct):
cls.initialize_data()
@@ -89,17 +114,45 @@ class OS_CONST_TYPE(type):
return name[:-7]
raise Exception("Unknown class property '%s'" % name)
+def get_os_distribution():
+ if platform.system() == 'Windows':
+ dist = windows_distribution()
+ else:
+ if platform.system() == 'Mac':
+ raise Exception("MacOS not supported. Exiting...")
+ else:
+ # Linux
+ # Read content from /etc/*-release file
+ # Full release name
+ dist = linux_distribution()
+ return dist
class OSConst:
__metaclass__ = OS_CONST_TYPE
class OSCheck:
+ _dist = get_os_distribution()
+
+ @staticmethod
+ def get_os_os():
+ """
+ Return values:
+ windows, linux
+
+ In case cannot detect - exit.
+ """
+ # Read content from /etc/*-release file
+ # Full release name
+ os_os = OSCheck._dist[0].lower()
+
+ return os_os
@staticmethod
def get_os_type():
"""
Return values:
+ win2008server, win2012server,
redhat, fedora, centos, oraclelinux, ascendos,
amazon, xenserver, oel, ovs, cloudlinux, slc, scientific, psbm,
ubuntu, debian, sles, sled, opensuse, suse ... and others
@@ -108,8 +161,7 @@ class OSCheck:
"""
# Read content from /etc/*-release file
# Full release name
- dist = linux_distribution()
- operatingSystem = dist[0].lower()
+ operatingSystem = OSCheck._dist[2].lower()
# special cases
if os.path.exists('/etc/oracle-release'):
@@ -147,10 +199,7 @@ class OSCheck:
In case cannot detect raises exception.
"""
- # Read content from /etc/*-release file
- # Full release name
- dist = linux_distribution()
- dist = dist[1]
+ dist = OSCheck._dist[3]
if dist:
return dist
@@ -173,8 +222,7 @@ class OSCheck:
In case cannot detect raises exception.
"""
- dist = linux_distribution()
- dist = dist[2].lower()
+ dist = OSCheck._dist[4].lower()
if dist:
return dist
@@ -226,6 +274,48 @@ class OSCheck:
return False
@staticmethod
+ def is_windows_family():
+ """
+ Return true if it is so or false if not
+
+ This is safe check for windows family, doesn't generate exception
+ """
+ try:
+ if OSCheck.get_os_family() == OSConst.WINSRV_FAMILY:
+ return True
+ except Exception:
+ pass
+ return False
+
+ @staticmethod
+ def is_linux_os():
+ """
+ Return true if it is so or false if not
+
+ This is safe check for linux os, doesn't generate exception
+ """
+ try:
+ if OSCheck.get_os_os() == OSConst.LINUX_OS:
+ return True
+ except Exception:
+ pass
+ return False
+
+ @staticmethod
+ def is_windows_os():
+ """
+ Return true if it is so or false if not
+
+ This is safe check for windows os, doesn't generate exception
+ """
+ try:
+ if OSCheck.get_os_os() == OSConst.WINDOWS_OS:
+ return True
+ except Exception:
+ pass
+ return False
+
+ @staticmethod
def is_redhat7():
"""
Return true if it is so or false if not
@@ -238,4 +328,10 @@ class OSCheck:
return True
except Exception:
pass
- return False
\ No newline at end of file
+ return False
+
+# OS info
+OS_VERSION = OSCheck().get_os_major_version()
+OS_TYPE = OSCheck.get_os_type()
+OS_FAMILY = OSCheck.get_os_family()
+OS_OS = OSCheck.get_os_os()
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/os_linux.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/os_linux.py b/ambari-common/src/main/python/ambari_commons/os_linux.py
new file mode 100644
index 0000000..38f3fb9
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/os_linux.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+'''
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+'''
+import getpass
+
+import os
+import pwd
+import shlex
+import subprocess
+
+from logging_utils import *
+
+
+NR_CHMOD_CMD = 'chmod {0} {1} {2}'
+NR_CHOWN_CMD = 'chown {0} {1} {2}'
+
+ULIMIT_CMD = "ulimit -n"
+
+
+def run_os_command(cmd):
+ print_info_msg('about to run command: ' + str(cmd))
+ if type(cmd) == str:
+ cmd = shlex.split(cmd)
+ process = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE
+ )
+ (stdoutdata, stderrdata) = process.communicate()
+ return process.returncode, stdoutdata, stderrdata
+
+def os_change_owner(filePath, user):
+ uid = pwd.getpwnam(user).pw_uid
+ gid = pwd.getpwnam(user).pw_gid
+ os.chown(filePath, uid, gid)
+
+def os_is_root():
+ '''
+ Checks effective UUID
+ Returns True if a program is running under root-level privileges.
+ '''
+ return os.geteuid() == 0
+
+def os_set_file_permissions(file, mod, recursive, user):
+ WARN_MSG = "Command {0} returned exit code {1} with message: {2}"
+ if recursive:
+ params = " -R "
+ else:
+ params = ""
+ command = NR_CHMOD_CMD.format(params, mod, file)
+ retcode, out, err = run_os_command(command)
+ if retcode != 0:
+ print_warning_msg(WARN_MSG.format(command, file, err))
+ command = NR_CHOWN_CMD.format(params, user, file)
+ retcode, out, err = run_os_command(command)
+ if retcode != 0:
+ print_warning_msg(WARN_MSG.format(command, file, err))
+
+def os_set_open_files_limit(maxOpenFiles):
+ command = "%s %s" % (ULIMIT_CMD, str(maxOpenFiles))
+ run_os_command(command)
+
+
+def os_getpass(prompt):
+ return getpass.unix_getpass(prompt)
http://git-wip-us.apache.org/repos/asf/ambari/blob/8de3425f/ambari-common/src/main/python/ambari_commons/os_utils.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_commons/os_utils.py b/ambari-common/src/main/python/ambari_commons/os_utils.py
new file mode 100644
index 0000000..9ea423f
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/os_utils.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+'''
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+'''
+
+import shutil
+import string
+
+from os_check import *
+
+if OSCheck.is_windows_os():
+ from os_windows import *
+else:
+ # MacOS not supported
+ from os_linux import *
+
+from logging_utils import *
+from exceptions import FatalException
+
+
+def is_valid_filepath(filepath):
+ if not filepath or not os.path.exists(filepath) or os.path.isdir(filepath):
+ print 'Invalid path, please provide the absolute file path.'
+ return False
+ else:
+ return True
+
+def quote_path(filepath):
+ if(filepath.find(' ') != -1):
+ filepath_ret = '"' + filepath + '"'
+ else:
+ filepath_ret = filepath
+ return filepath_ret
+
+def search_file(filename, search_path, pathsep=os.pathsep):
+ """ Given a search path, find file with requested name """
+ for path in string.split(search_path, pathsep):
+ candidate = os.path.join(path, filename)
+ if os.path.exists(candidate):
+ return os.path.abspath(candidate)
+ return None
+
+def copy_file(src, dest_file):
+ try:
+ shutil.copyfile(src, dest_file)
+ except Exception, e:
+ err = "Can not copy file {0} to {1} due to: {2} . Please check file " \
+ "permissions and free disk space.".format(src, dest_file, e.message)
+ raise FatalException(1, err)
+
+def copy_files(files, dest_dir):
+ if os.path.isdir(dest_dir):
+ for filepath in files:
+ shutil.copy(filepath, dest_dir)
+ return 0
+ else:
+ return -1
+
+def remove_file(filePath):
+ if os.path.exists(filePath):
+ try:
+ os.remove(filePath)
+ except Exception, e:
+ print_warning_msg('Unable to remove file: ' + str(e))
+ return 1
+ pass
+ return 0
+
+def set_file_permissions(file, mod, user, recursive):
+ if os.path.exists(file):
+ os_set_file_permissions(file, mod, recursive, user)
+ else:
+ print_info_msg("File %s does not exist" % file)
+
+def is_root():
+ return os_is_root()
+
+# Proxy to the os implementation
+def change_owner(filePath, user):
+ os_change_owner(filePath, user)
+
+# Proxy to the os implementation
+def set_open_files_limit(maxOpenFiles):
+ os_set_open_files_limit(maxOpenFiles)
+
+def get_password(prompt):
+ return os_getpass(prompt)
\ No newline at end of file