summaryrefslogtreecommitdiff
path: root/ambari-agent
diff options
context:
space:
mode:
authorMahadev Konar <mahadev@apache.org>2012-11-07 08:19:54 +0000
committerMahadev Konar <mahadev@apache.org>2012-11-07 08:19:54 +0000
commitc2264fedc1ca9ed27ba56513823fc52fea400230 (patch)
tree37e9d376a67c9a3126a0668e8ae6a8ac30b8445b /ambari-agent
parenta12bb10131ca66e48e524500092695ecdcc86fea (diff)
AMBARI-970. Add additional Ganglia metrics and JMX properties. (Tom Beerbower via mahadev)
git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/branches/AMBARI-666@1406491 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'ambari-agent')
-rw-r--r--ambari-agent/src/main/puppet/modules/hdp-repos/manifests/init.pp21
-rw-r--r--ambari-agent/src/main/puppet/modules/hdp-repos/manifests/process_repo.pp41
-rw-r--r--ambari-agent/src/main/puppet/modules/hdp-repos/templates/repo.erb27
-rw-r--r--ambari-agent/src/main/puppet/modules/hdp/manifests/params.pp6
-rw-r--r--ambari-agent/src/main/python/ambari_agent/Grep.py44
-rw-r--r--ambari-agent/src/main/python/ambari_agent/imports.txt1
-rw-r--r--ambari-agent/src/main/python/ambari_agent/manifestGenerator.py48
-rw-r--r--ambari-agent/src/main/python/ambari_agent/puppetExecutor.py22
-rw-r--r--ambari-agent/src/main/python/ambari_agent/test.json17
-rw-r--r--ambari-agent/src/test/python/TestConnectionRetries.py17
-rw-r--r--ambari-agent/src/test/python/TestGrep.py101
-rw-r--r--ambari-agent/src/test/python/dummy_puppet_output_error.txt45
-rw-r--r--ambari-agent/src/test/python/dummy_puppet_output_good.txt47
13 files changed, 420 insertions, 17 deletions
diff --git a/ambari-agent/src/main/puppet/modules/hdp-repos/manifests/init.pp b/ambari-agent/src/main/puppet/modules/hdp-repos/manifests/init.pp
new file mode 100644
index 0000000000..e005cab414
--- /dev/null
+++ b/ambari-agent/src/main/puppet/modules/hdp-repos/manifests/init.pp
@@ -0,0 +1,21 @@
+#
+#
+# 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 hdp-repos() {}
diff --git a/ambari-agent/src/main/puppet/modules/hdp-repos/manifests/process_repo.pp b/ambari-agent/src/main/puppet/modules/hdp-repos/manifests/process_repo.pp
new file mode 100644
index 0000000000..75cb99c5b4
--- /dev/null
+++ b/ambari-agent/src/main/puppet/modules/hdp-repos/manifests/process_repo.pp
@@ -0,0 +1,41 @@
+#
+#
+# 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 hdp-repos::process_repo(
+ $os_type,
+ $repo_id,
+ $base_url,
+ $repo_name
+) inherits hdp-hadoop::params
+{
+ debug("Getting repo path for os: $hdp_os_type")
+
+ $repo_path = $repos_paths[$hdp_os_type]
+
+ if hdp_is_empty($repo_path) {
+ hdp_fail("There is no repo path for os: $hdp_os_type in hdp::params")
+ }
+
+ file{$repo_name:
+ path => "$repo_path/$repo_name.repo",
+ ensure => file,
+ content => template("hdp-repos/repo.erb")
+ }
+}
diff --git a/ambari-agent/src/main/puppet/modules/hdp-repos/templates/repo.erb b/ambari-agent/src/main/puppet/modules/hdp-repos/templates/repo.erb
new file mode 100644
index 0000000000..b8f9b9fcda
--- /dev/null
+++ b/ambari-agent/src/main/puppet/modules/hdp-repos/templates/repo.erb
@@ -0,0 +1,27 @@
+#
+#
+# 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.
+#
+#
+#
+[<%=repo_id%>]
+name=<%=repo_name %>
+baseurl=<%=base_url %>
+enabled=1
+
+
diff --git a/ambari-agent/src/main/puppet/modules/hdp/manifests/params.pp b/ambari-agent/src/main/puppet/modules/hdp/manifests/params.pp
index bac3ef0e8f..8b4c9c4253 100644
--- a/ambari-agent/src/main/puppet/modules/hdp/manifests/params.pp
+++ b/ambari-agent/src/main/puppet/modules/hdp/manifests/params.pp
@@ -351,6 +351,12 @@ class hdp::params()
$hcat_server_host = hdp_default("hive_server_host")
$hcat_mysql_host = hdp_default("hive_mysql_host")
+
+ $repos_paths =
+ {
+ centos6 => '/etc/yum.repos.d'
+ }
+
}
###### snmp
diff --git a/ambari-agent/src/main/python/ambari_agent/Grep.py b/ambari-agent/src/main/python/ambari_agent/Grep.py
new file mode 100644
index 0000000000..0aee035a25
--- /dev/null
+++ b/ambari-agent/src/main/python/ambari_agent/Grep.py
@@ -0,0 +1,44 @@
+class Grep:
+
+ def __init__(self):
+ pass
+
+ def grep(self, string, phrase, before, after):
+ """
+ Tries to find the last occurence of phrase in a given string. String should consist of lines,
+ separated by line separators. String trim is performed before search.
+ If occurence is found, grep () takes not more than 'before' lines above and 'after' lines below.
+ If phrase is not found, returns None. Search is not case sensitive, regexps are not supported.
+ """
+ stripped_string = string.strip()
+ lines = stripped_string.splitlines(True)
+ last_occurence = None
+ for index in range(len(lines)):
+ line = lines[index]
+ if phrase.lower() in line.lower():
+ last_occurence = index
+ if last_occurence is None:
+ return None
+ bound_a = before
+ if last_occurence < before:
+ bound_a = last_occurence
+ result = None
+ if (len(lines) - last_occurence) < after:
+ result = lines[last_occurence - bound_a :]
+ else:
+ result = lines[last_occurence - bound_a : last_occurence + after + 1]
+ return "".join(result).strip()
+
+
+ def tail(self, string, n):
+ """
+ Copies last n lines from string to result. Also, string trim is performed.
+ """
+ stripped_string = string.strip()
+ lines = stripped_string.splitlines(True)
+ if len(lines) <= n:
+ return stripped_string
+ else:
+ length = len(lines)
+ tailed = lines[length - n:]
+ return "".join(tailed)
diff --git a/ambari-agent/src/main/python/ambari_agent/imports.txt b/ambari-agent/src/main/python/ambari_agent/imports.txt
index ea49b991a2..64d16194d6 100644
--- a/ambari-agent/src/main/python/ambari_agent/imports.txt
+++ b/ambari-agent/src/main/python/ambari_agent/imports.txt
@@ -10,3 +10,4 @@ hdp-hive/manifests/*.pp
hdp-hcat/manifests/*.pp
hdp-mysql/manifests/*.pp
hdp-monitor-webserver/manifests/*.pp
+hdp-repos/manifests/*.pp
diff --git a/ambari-agent/src/main/python/ambari_agent/manifestGenerator.py b/ambari-agent/src/main/python/ambari_agent/manifestGenerator.py
index 55b678390c..3c05cd217b 100644
--- a/ambari-agent/src/main/python/ambari_agent/manifestGenerator.py
+++ b/ambari-agent/src/main/python/ambari_agent/manifestGenerator.py
@@ -22,6 +22,10 @@ import json
import os.path
import logging
from uuid import getnode as get_mac
+from shell import shellRunner
+
+REPO_INFO_DIR="repos_info"
+PUPPET_EXT=".pp"
logger = logging.getLogger()
@@ -79,7 +83,7 @@ def generateManifest(parsedJson, fileName, modulesdir):
writeNodes(manifest, clusterHostInfo)
#writing params from map
- writeParams(manifest, params)
+ writeParams(manifest, params, modulesdir)
xmlConfigurations = {}
@@ -131,12 +135,14 @@ def writeNodes(outputFile, clusterHostInfo):
outputFile.write(']\n')
#write params
-def writeParams(outputFile, params):
+def writeParams(outputFile, params, modulesdir):
for paramName in params.iterkeys():
# todo handle repo information properly
if paramName == 'repo_info':
+ processRepo(params[paramName],modulesdir)
continue
+
param = params[paramName]
if type(param) is dict:
@@ -201,8 +207,10 @@ def writeTasks(outputFile, roles):
serviceStatesFile.close()
outputFile.write('node /default/ {\n ')
+
writeStages(outputFile, len(roles) + 1)
stageNum = 1
+
outputFile.write('class {\'hdp\': stage => ' + str(stageNum) + '}\n')
stageNum = stageNum + 1
@@ -248,8 +256,41 @@ def writeStages(outputFile, numStages):
arrow = ' -> '
outputFile.write('\n')
-
+def processRepo(repoInfoList, modulesdir):
+
+ if not os.path.exists(REPO_INFO_DIR):
+ os.makedirs(REPO_INFO_DIR)
+
+ for repo in repoInfoList:
+
+ repoFile = open(REPO_INFO_DIR + os.sep + repo['repo_id'] + PUPPET_EXT, 'w+')
+ writeImports(repoFile, modulesdir, inputFileName='imports.txt')
+ repoFile.write('node /default/ {')
+ repoFile.write('class{ "hdp-repos::process_repo" : ' + ' os_type => "' + repo['os_type'] +
+ '", repo_id => "' + repo['repo_id'] + '", base_url => "' + repo['base_url'] +
+ '", repo_name => "' + repo['repo_name'] + '" }' )
+ repoFile.write('}')
+ repoFile.close()
+
+
+def installRepos():
+ sh = shellRunner()
+ agentdir = os.getcwd()
+ confdir = os.path.abspath(agentdir + ".." + os.sep + ".." +
+ os.sep + ".." + os.sep + "puppet")
+
+ for repo in os.listdir(REPO_INFO_DIR):
+ if not repo.endswith(PUPPET_EXT):
+ continue
+ logfile = repo + '_log.log'
+ res = sh.run(['puppet apply', '--confdir=' + confdir, REPO_INFO_DIR + os.sep + repo,
+ '--logdest=' + agentdir + os.sep + REPO_INFO_DIR + os.sep + logfile])
+ if res['exitCode'] == 0:
+ logger.info('Repository ' + repo + ' was installed')
+ else:
+ logger.error('Repository ' + repo + ' wasn''t installed. Please find detailed info in logfile:' + logfile)
+
def main():
logging.basicConfig(level=logging.DEBUG)
#test code
@@ -262,6 +303,7 @@ def main():
parsedJson = json.loads(inputJsonStr)
generateManifest(parsedJson, 'site.pp', modulesdir)
+ installRepos()
if __name__ == '__main__':
main()
diff --git a/ambari-agent/src/main/python/ambari_agent/puppetExecutor.py b/ambari-agent/src/main/python/ambari_agent/puppetExecutor.py
index 071db4cdd3..b9a84b4391 100644
--- a/ambari-agent/src/main/python/ambari_agent/puppetExecutor.py
+++ b/ambari-agent/src/main/python/ambari_agent/puppetExecutor.py
@@ -23,10 +23,21 @@ import logging
import subprocess
from manifestGenerator import generateManifest
import pprint
+from Grep import Grep
logger = logging.getLogger()
class puppetExecutor:
+
+ # How many lines from command output send to server
+ OUTPUT_LAST_LINES = 10
+ # How many lines from command error output send to server (before Err phrase)
+ ERROR_LAST_LINES_BEFORE = 10
+ # How many lines from command error output send to server (after Err phrase)
+ ERROR_LAST_LINES_AFTER = 30
+
+ NO_ERROR = "none"
+
""" Class that executes the commands that come from the server using puppet.
This is the class that provides the pluggable point for executing the puppet"""
@@ -60,6 +71,7 @@ class puppetExecutor:
def runCommand(self, command):
result = {}
taskId = 0;
+ grep = Grep()
if command.has_key("taskId"):
taskId = command['taskId']
@@ -81,9 +93,9 @@ class puppetExecutor:
stderr=subprocess.PIPE,
env=puppetEnv)
stderr_out = puppet.communicate()
- error = "none"
+ error = self.NO_ERROR
returncode = 0
- if (puppet.returncode != 0 and puppet.returncode != 2) :
+ if puppet.returncode != 0 and puppet.returncode != 2:
returncode = puppet.returncode
error = stderr_out[1]
logging.error("Error running puppet: \n" + stderr_out[1])
@@ -92,8 +104,10 @@ class puppetExecutor:
puppetOutput = stderr_out[0]
logger.info("Output from puppet :\n" + puppetOutput)
result["exitcode"] = returncode
-
- result["stdout"] = "Output"
+ if error == self.NO_ERROR:
+ result["stdout"] = grep.tail(puppetOutput, self.OUTPUT_LAST_LINES)
+ else:
+ result["stdout"] = grep.grep(puppetOutput, "err", self.ERROR_LAST_LINES_BEFORE, self.ERROR_LAST_LINES_AFTER)
logger.info("ExitCode : " + str(result["exitcode"]))
return result
diff --git a/ambari-agent/src/main/python/ambari_agent/test.json b/ambari-agent/src/main/python/ambari_agent/test.json
index 789dfc3f93..7e449302bc 100644
--- a/ambari-agent/src/main/python/ambari_agent/test.json
+++ b/ambari-agent/src/main/python/ambari_agent/test.json
@@ -14,7 +14,22 @@
"java32_home" : "/usr/jdk64/jdk1.6.0_31",
"java64_home" : "/usr/jdk64/jdk1.6.0_31",
-"jdk_bins" : { "32" : "jdk-6u31-linux-x64.bin", "64" : "jdk-6u31-linux-x64.bin" }
+"jdk_bins" : { "32" : "jdk-6u31-linux-x64.bin", "64" : "jdk-6u31-linux-x64.bin" },
+"repo_info" :[
+{
+ "base_url":"http://public-repo-1.hortonworks.com/HDP-1.1.1.16/repos/centos5",
+ "os_type":"centos5",
+ "repo_id":"HDP-1.1.1.16_TEST",
+ "repo_name":"HDP_TEST"
+}
+,
+{
+ "base_url":"http://public-repo-1.hortonworks.com/HDP-UTILS-1.1.0.15/repos/centos5",
+ "os_type":"centos5",
+ "repo_id":"HDP-UTILS-1.1.0.15_TEST",
+ "repo_name":"HDP-UTILS_TEST"
+}]
+
},
diff --git a/ambari-agent/src/test/python/TestConnectionRetries.py b/ambari-agent/src/test/python/TestConnectionRetries.py
index 3db36c05c3..9f27c4a279 100644
--- a/ambari-agent/src/test/python/TestConnectionRetries.py
+++ b/ambari-agent/src/test/python/TestConnectionRetries.py
@@ -31,10 +31,9 @@ import socket
import os
import logging
from ambari_agent.Controller import Controller
-import logging
NON_EXISTING_DOMAIN = 'non-existing-domain43342432.com'
-BAD_URL = 'http://www.iana.org/domains/ex222ample/'
+BAD_URL = 'http://localhost:54222/badurl/'
class TestConnectionRetries(TestCase):
@@ -54,20 +53,20 @@ class TestConnectionRetries(TestCase):
def test_registration_retries(self):
netutil = NetUtil()
- netutil.CONNECT_SERVER_RETRY_INTERVAL_SEC=0.1
+ netutil.CONNECT_SERVER_RETRY_INTERVAL_SEC=0.05
retries = netutil.try_to_connect(BAD_URL, 3)
self.assertEquals(retries, 3)
def test_infinit_registration_retries(self):
netutil = NetUtil()
- netutil.CONNECT_SERVER_RETRY_INTERVAL_SEC=0.1
+ netutil.CONNECT_SERVER_RETRY_INTERVAL_SEC=0.05
thread = Thread(target = netutil.try_to_connect, args = (BAD_URL, -1))
thread.start()
- time.sleep(0.5)
+ time.sleep(0.25)
# I have to stop the thread anyway, so I'll check results later
threadWasAlive = thread.isAlive()
netutil.DEBUG_STOP_RETRIES_FLAG = True
- time.sleep(1)
+ time.sleep(0.5)
# Checking results before thread stop
self.assertEquals(threadWasAlive, True, "Thread should still be retrying to connect")
# Checking results after thread stop
@@ -75,8 +74,8 @@ class TestConnectionRetries(TestCase):
def test_heartbeat_retries(self):
netutil = NetUtil()
- netutil.HEARTBEAT_IDDLE_INTERVAL_SEC=0.1
- netutil.HEARTBEAT_NOT_IDDLE_INTERVAL_SEC=0.1
+ netutil.HEARTBEAT_IDDLE_INTERVAL_SEC=0.05
+ netutil.HEARTBEAT_NOT_IDDLE_INTERVAL_SEC=0.05
#building heartbeat object
testsPath = os.path.dirname(os.path.realpath(__file__))
dictPath = testsPath + os.sep + '..' + os.sep + '..' + os.sep + 'main' + os.sep + 'python' + os.sep + 'ambari_agent' + os.sep + 'servicesToPidNames.dict'
@@ -104,7 +103,7 @@ class TestConnectionRetries(TestCase):
# Checking results before thread stop
self.assertEquals(threadWasAlive, True, "Heartbeat should be alive now")
self.assertEquals(successfull_heartbits0, 0, "Heartbeat should not have any success")
- self.assertGreater(heartbeat_retries0, 1, "Heartbeat should retry connecting")
+ self.assertEquals(heartbeat_retries0 > 1, True, "Heartbeat should retry connecting")
# Checking results after thread stop
self.assertEquals(thread.isAlive(), False, "Heartbeat should stop now")
self.assertEquals(controller.DEBUG_SUCCESSFULL_HEARTBEATS, 0, "Heartbeat should not have any success")
diff --git a/ambari-agent/src/test/python/TestGrep.py b/ambari-agent/src/test/python/TestGrep.py
new file mode 100644
index 0000000000..622a0640cf
--- /dev/null
+++ b/ambari-agent/src/test/python/TestGrep.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
+
+from unittest import TestCase
+from Grep import Grep
+import socket
+import os
+import logging
+
+class TestGrep(TestCase):
+
+ logger = logging.getLogger()
+ string_good = None
+ string_bad = None
+ grep = Grep()
+
+ def setUp(self):
+ self.string_good = open('dummy_puppet_output_good.txt', 'r').read().replace("\n", os.linesep)
+ self.string_bad = open('dummy_puppet_output_error.txt', 'r').read().replace("\n", os.linesep)
+ pass
+
+ def test_grep_many_lines(self):
+ fragment = self.grep.grep(self.string_bad, "err", 1000, 1000)
+ desired = self.string_bad.strip()
+ self.assertEquals(fragment, desired, "Grep grep function should return all lines if there are less lines than n")
+
+
+ def test_grep_few_lines(self):
+ fragment = self.grep.grep(self.string_bad, "Err", 3, 3)
+ desired = """
+debug: /Schedule[never]: Skipping device resources because running on a host
+debug: Exec[command_good](provider=posix): Executing 'wget e432423423xample.com/badurl444111'
+debug: Executing 'wget e432423423xample.com/badurl444111'
+err: /Stage[main]//Exec[command_good]/returns: change from notrun to 0 failed: wget e432423423xample.com/badurl444111 returned 4 instead of one of [0] at /root/puppet-learn/2-bad.pp:5
+debug: /Schedule[weekly]: Skipping device resources because running on a host
+debug: /Schedule[puppet]: Skipping device resources because running on a host
+debug: Finishing transaction 70171639726240
+""".strip()
+ self.assertEquals(fragment, desired, "Grep grep function should return only last 3 lines of file")
+
+ def test_grep_no_result(self):
+ fragment = self.grep.grep(self.string_good, "Err", 3, 3)
+ desired = None
+ self.assertEquals(fragment, desired, 'Grep grep function should return None if result is not found')
+
+ def test_grep_empty_string(self):
+ fragment = self.grep.grep("", "Err", 1000, 1000)
+ desired = None
+ self.assertEquals(fragment, desired, 'Grep grep function should return None for empty string')
+
+ def test_grep_all(self):
+ fragment = self.grep.grep(self.string_bad, "Err", 35, 9)
+ desired = self.string_bad.strip()
+ self.assertEquals(fragment, desired, 'Grep grep function contains bug in index arithmetics')
+
+
+ def test_tail_many_lines(self):
+ fragment = self.grep.tail(self.string_good, 1000)
+ desired = self.string_good.strip()
+ self.assertEquals(fragment, desired, "Grep tail function should return all lines if there are less lines than n")
+
+ def test_tail_few_lines(self):
+ fragment = self.grep.tail(self.string_good, 3)
+ desired = """
+debug: Finishing transaction 70060456663980
+debug: Received report to process from ambari-dmi.cybervisiontech.com.ua
+debug: Processing report from ambari-dmi.cybervisiontech.com.ua with processor Puppet::Reports::Store
+""".strip()
+ self.assertEquals(fragment, desired, "Grep tail function should return only last 3 lines of file")
+
+ def test_tail_no_lines(self):
+ fragment = self.grep.tail("", 3)
+ desired = ''
+ self.assertEquals(fragment, desired, 'Grep tail function should return "" for empty string')
+
+ def test_tail_all(self):
+ fragment = self.grep.tail("", 47)
+ desired = ''
+ self.assertEquals(fragment, desired, 'Grep tail function contains bug in index arithmetics')
+
+ def tearDown(self):
+ pass
+
+
diff --git a/ambari-agent/src/test/python/dummy_puppet_output_error.txt b/ambari-agent/src/test/python/dummy_puppet_output_error.txt
new file mode 100644
index 0000000000..1c7f93e286
--- /dev/null
+++ b/ambari-agent/src/test/python/dummy_puppet_output_error.txt
@@ -0,0 +1,45 @@
+debug: Creating default schedules
+debug: Puppet::Type::User::ProviderDirectoryservice: file /usr/bin/dscl does not exist
+debug: Puppet::Type::User::ProviderUser_role_add: file roledel does not exist
+debug: Puppet::Type::User::ProviderPw: file pw does not exist
+debug: Failed to load library 'ldap' for feature 'ldap'
+debug: Puppet::Type::User::ProviderLdap: feature ldap is missing
+debug: /File[/var/lib/puppet/state/graphs]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/ssl/crl.pem]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/ssl/private_keys]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/resources.txt]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/ssl/certificate_requests]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/ssl/certs]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/state.yaml]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/client_data]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/facts]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/state]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl/private]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/last_run_report.yaml]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/lib]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl/public_keys]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/client_yaml]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl/certs/ca.pem]: Autorequiring File[/var/lib/puppet/ssl/certs]
+debug: /File[/var/lib/puppet/clientbucket]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/state/last_run_summary.yaml]: Autorequiring File[/var/lib/puppet/state]
+debug: Finishing transaction 70171638648540
+debug: Loaded state in 0.00 seconds
+debug: Loaded state in 0.00 seconds
+info: Applying configuration version '1352127563'
+debug: /Schedule[daily]: Skipping device resources because running on a host
+debug: /Schedule[monthly]: Skipping device resources because running on a host
+debug: /Schedule[hourly]: Skipping device resources because running on a host
+debug: /Schedule[never]: Skipping device resources because running on a host
+debug: Exec[command_good](provider=posix): Executing 'wget e432423423xample.com/badurl444111'
+debug: Executing 'wget e432423423xample.com/badurl444111'
+err: /Stage[main]//Exec[command_good]/returns: change from notrun to 0 failed: wget e432423423xample.com/badurl444111 returned 4 instead of one of [0] at /root/puppet-learn/2-bad.pp:5
+debug: /Schedule[weekly]: Skipping device resources because running on a host
+debug: /Schedule[puppet]: Skipping device resources because running on a host
+debug: Finishing transaction 70171639726240
+debug: Storing state
+debug: Stored state in 0.01 seconds
+notice: Finished catalog run in 0.23 seconds
+debug: Finishing transaction 70171638871060
+debug: Received report to process from ambari-dmi.cybervisiontech.com.ua
+debug: Processing report from ambari-dmi.cybervisiontech.com.ua with processor Puppet::Reports::Store
diff --git a/ambari-agent/src/test/python/dummy_puppet_output_good.txt b/ambari-agent/src/test/python/dummy_puppet_output_good.txt
new file mode 100644
index 0000000000..dce3ca933f
--- /dev/null
+++ b/ambari-agent/src/test/python/dummy_puppet_output_good.txt
@@ -0,0 +1,47 @@
+debug: Creating default schedules
+debug: Puppet::Type::User::ProviderDirectoryservice: file /usr/bin/dscl does not exist
+debug: Puppet::Type::User::ProviderUser_role_add: file roledel does not exist
+debug: Puppet::Type::User::ProviderPw: file pw does not exist
+debug: Failed to load library 'ldap' for feature 'ldap'
+debug: Puppet::Type::User::ProviderLdap: feature ldap is missing
+debug: /File[/var/lib/puppet/ssl/certs/ca.pem]: Autorequiring File[/var/lib/puppet/ssl/certs]
+debug: /File[/var/lib/puppet/ssl/public_keys]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/ssl/crl.pem]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/last_run_report.yaml]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/ssl/certificate_requests]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/last_run_summary.yaml]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/client_data]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/state]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl/private]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/graphs]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/ssl]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/state/state.yaml]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/client_yaml]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/facts]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl/private_keys]: Autorequiring File[/var/lib/puppet/ssl]
+debug: /File[/var/lib/puppet/state/resources.txt]: Autorequiring File[/var/lib/puppet/state]
+debug: /File[/var/lib/puppet/clientbucket]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/lib]: Autorequiring File[/var/lib/puppet]
+debug: /File[/var/lib/puppet/ssl/certs]: Autorequiring File[/var/lib/puppet/ssl]
+debug: Finishing transaction 70060456464420
+debug: Loaded state in 0.00 seconds
+debug: Loaded state in 0.00 seconds
+info: Applying configuration version '1352127399'
+debug: /Schedule[daily]: Skipping device resources because running on a host
+debug: /Schedule[monthly]: Skipping device resources because running on a host
+debug: /Schedule[hourly]: Skipping device resources because running on a host
+debug: /Schedule[never]: Skipping device resources because running on a host
+debug: Exec[command_good](provider=posix): Executing 'wget example.com'
+debug: Executing 'wget example.com'
+notice: /Stage[main]//Exec[command_good]/returns: executed successfully
+debug: /Stage[main]//Exec[command_good]: The container Class[Main] will propagate my refresh event
+debug: /Schedule[weekly]: Skipping device resources because running on a host
+debug: /Schedule[puppet]: Skipping device resources because running on a host
+debug: Class[Main]: The container Stage[main] will propagate my refresh event
+debug: Finishing transaction 70060457541680
+debug: Storing state
+debug: Stored state in 0.01 seconds
+notice: Finished catalog run in 0.59 seconds
+debug: Finishing transaction 70060456663980
+debug: Received report to process from ambari-dmi.cybervisiontech.com.ua
+debug: Processing report from ambari-dmi.cybervisiontech.com.ua with processor Puppet::Reports::Store \ No newline at end of file