You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2014/12/02 18:28:45 UTC
[29/30] ambari git commit: AMBARI-5707. Replace Ganglia with high
performant and pluggable Metrics System. (swagle)
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/application_metric_map.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/application_metric_map.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/application_metric_map.py
new file mode 100644
index 0000000..1be6fa2
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/application_metric_map.py
@@ -0,0 +1,130 @@
+#!/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 logging
+import json
+from threading import RLock
+
+logger = logging.getLogger()
+
+class ApplicationMetricMap:
+ """
+ A data structure to buffer metrics in memory.
+ The in-memory dict stores metrics as shown below:
+ { application_id : { metric_id : { timestamp : metric_value } } }
+ application_id => uniquely identify the metrics for an application / host.
+ metric_id => identify the metric
+ timestamp => collection time
+ metric_value => numeric value
+ """
+
+
+ def __init__(self, hostname, ip_address):
+ self.hostname = hostname
+ self.ip_address = ip_address
+ self.lock = RLock()
+ self.app_metric_map = {}
+ pass
+
+ def put_metric(self, application_id, metric_id_to_value_map, timestamp):
+ with self.lock:
+ for metric_name, value in metric_id_to_value_map.iteritems():
+
+ metric_map = self.app_metric_map.get(application_id)
+ if not metric_map:
+ metric_map = { metric_name : { timestamp : value } }
+ self.app_metric_map[ application_id ] = metric_map
+ else:
+ metric_id_map = metric_map.get(metric_name)
+ if not metric_id_map:
+ metric_id_map = { timestamp : value }
+ metric_map[ metric_name ] = metric_id_map
+ else:
+ metric_map[ metric_name ].update( { timestamp : value } )
+ pass
+ pass
+ pass
+
+ def delete_application_metrics(self, app_id):
+ del self.app_metric_map[ app_id ]
+ pass
+
+ def flatten(self, application_id = None):
+ """
+ Return flatten dict to caller in json format.
+ Json format:
+ {"metrics":[{"hostname":"a","metricname":"b","appid":"c",
+ "instanceid":"d","starttime":"e","metrics":{"t":"v"}}]}
+ """
+ with self.lock:
+ timeline_metrics = { "metrics" : [] }
+ local_metric_map = {}
+
+ if application_id:
+ if self.app_metric_map.has_key(application_id):
+ local_metric_map = { application_id : self.app_metric_map[application_id] }
+ else:
+ logger.info("application_id: {0}, not present in the map.".format(application_id))
+ else:
+ local_metric_map = self.app_metric_map.copy()
+ pass
+
+ for appId, metrics in local_metric_map.iteritems():
+ for metricId, metricData in dict(metrics).iteritems():
+ # Create a timeline metric object
+ timeline_metric = {
+ "hostname" : self.hostname,
+ "metricname" : metricId,
+ "appid" : "HOST",
+ "instanceid" : "",
+ "starttime" : self.get_start_time(appId, metricId),
+ "metrics" : metricData
+ }
+ timeline_metrics[ "metrics" ].append( timeline_metric )
+ pass
+ pass
+ return json.dumps(timeline_metrics) if len(timeline_metrics[ "metrics" ]) > 0 else None
+ pass
+
+ def get_start_time(self, app_id, metric_id):
+ with self.lock:
+ if self.app_metric_map.has_key(app_id):
+ if self.app_metric_map.get(app_id).has_key(metric_id):
+ metrics = self.app_metric_map.get(app_id).get(metric_id)
+ return min(metrics.iterkeys())
+ pass
+
+ def format_app_id(self, app_id, instance_id = None):
+ return app_id + "_" + instance_id if instance_id else app_id
+ pass
+
+ def get_app_id(self, app_id):
+ return app_id.split("_")[0]
+ pass
+
+ def get_instance_id(self, app_id):
+ parts = app_id.split("_")
+ return parts[1] if len(parts) > 1 else ''
+ pass
+
+ def clear(self):
+ with self.lock:
+ self.app_metric_map.clear()
+ pass
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/config_reader.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/config_reader.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/config_reader.py
new file mode 100644
index 0000000..daabf37
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/config_reader.py
@@ -0,0 +1,127 @@
+#!/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 ConfigParser
+import StringIO
+import json
+import os
+
+config = ConfigParser.RawConfigParser()
+CONFIG_FILE_PATH = "/etc/ambari-metrics-monitor/conf/metric_monitor.ini"
+METRIC_FILE_PATH = "/etc/ambari-metrics-monitor/conf/metric_groups.conf"
+
+config_content = """
+[default]
+debug_level = INFO
+metrics_server = host:port
+enable_time_threshold = false
+enable_value_threshold = false
+
+[emitter]
+send_interval = 60
+
+[collector]
+collector_sleep_interval = 5
+max_queue_size = 5000
+"""
+
+metric_group_info = """
+{
+ "host_metric_groups": {
+ "cpu_info": {
+ "collect_every": "15",
+ "metrics": [
+ {
+ "name": "cpu_user",
+ "value_threshold": "1.0"
+ }
+ ]
+ },
+ "disk_info": {
+ "collect_every": "30",
+ "metrics": [
+ {
+ "name": "disk_free",
+ "value_threshold": "5.0"
+ }
+ ]
+ },
+ "network_info": {
+ "collect_every": "20",
+ "metrics": [
+ {
+ "name": "bytes_out",
+ "value_threshold": "128"
+ }
+ ]
+ }
+ },
+ "process_metric_groups": {
+ "": {
+ "collect_every": "15",
+ "metrics": []
+ }
+ }
+}
+"""
+
+class Configuration:
+
+ def __init__(self):
+ global config_content
+ self.config = ConfigParser.RawConfigParser()
+ if os.path.exists(CONFIG_FILE_PATH):
+ self.config.read(CONFIG_FILE_PATH)
+ else:
+ self.config.readfp(StringIO.StringIO(config_content))
+ pass
+ if os.path.exists(METRIC_FILE_PATH):
+ self.metric_groups = json.load(open(METRIC_FILE_PATH))
+ else:
+ print 'No metric configs found at {0}'.format(METRIC_FILE_PATH)
+ pass
+
+ def getConfig(self):
+ return self.config
+
+ def getMetricGroupConfig(self):
+ return self.metric_groups
+
+ def get(self, section, key, default=None):
+ try:
+ value = self.config.get(section, key)
+ except:
+ return default
+ return value
+
+ def get_send_interval(self):
+ return int(self.get("emitter", "send_interval", 60))
+
+ def get_collector_sleep_interval(self):
+ return int(self.get("collector", "collector_sleep_interval", 5))
+
+ def get_server_address(self):
+ return self.get("default", "metrics_server")
+
+ def get_log_level(self):
+ return self.get("default", "debug_level", "INFO")
+
+ def get_max_queue_size(self):
+ return int(self.get("collector", "max_queue_size", 5000))
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/controller.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/controller.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/controller.py
new file mode 100644
index 0000000..51f0980
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/controller.py
@@ -0,0 +1,103 @@
+#!/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 logging
+import threading
+import time
+from Queue import Queue
+from threading import Timer
+from application_metric_map import ApplicationMetricMap
+from event_definition import HostMetricCollectEvent, ProcessMetricCollectEvent
+from metric_collector import MetricsCollector
+from emitter import Emitter
+from host_info import HostInfo
+
+logger = logging.getLogger()
+
+class Controller(threading.Thread):
+
+ def __init__(self, config):
+ # Process initialization code
+ threading.Thread.__init__(self)
+ logger.debug('Initializing Controller thread.')
+ self.lock = threading.Lock()
+ self.config = config
+ self.metrics_config = config.getMetricGroupConfig()
+ self.events_cache = []
+ hostinfo = HostInfo()
+ self.application_metric_map = ApplicationMetricMap(hostinfo.get_hostname(),
+ hostinfo.get_ip_address())
+ self.event_queue = Queue(config.get_max_queue_size())
+ self.metric_collector = MetricsCollector(self.event_queue, self.application_metric_map)
+ self.server_url = config.get_server_address()
+ self.sleep_interval = config.get_collector_sleep_interval()
+ self.initialize_events_cache()
+ self.emitter = Emitter(self.config, self.application_metric_map)
+
+ def run(self):
+ logger.info('Running Controller thread: %s' % threading.currentThread().getName())
+ # Wake every 5 seconds to push events to the queue
+ while True:
+ if (self.event_queue.full()):
+ logger.warn('Event Queue full!! Suspending further collections.')
+ else:
+ self.enqueque_events()
+ pass
+ time.sleep(self.sleep_interval)
+ pass
+
+ # TODO: Optimize to not use Timer class and use the Queue instead
+ def enqueque_events(self):
+ # Queue events for up to a minute
+ for event in self.events_cache:
+ t = Timer(event.get_collect_interval(), self.metric_collector.process_event, args=(event,))
+ t.start()
+ pass
+
+ def initialize_events_cache(self):
+ self.events_cache = []
+ try:
+ host_metrics_groups = self.metrics_config['host_metric_groups']
+ process_metrics_groups = self.metrics_config['process_metric_groups']
+ except KeyError, ke:
+ logger.warn('Error loading metric groups.')
+ raise ke
+ pass
+
+ if host_metrics_groups:
+ for name, properties in host_metrics_groups.iteritems():
+ event = HostMetricCollectEvent(properties, name)
+ logger.info('Adding event to cache, {0} : {1}'.format(name, properties))
+ self.events_cache.append(event)
+ pass
+ pass
+
+ if process_metrics_groups:
+ for name, properties in process_metrics_groups.iteritems():
+ event = ProcessMetricCollectEvent(properties, name)
+ logger.info('Adding event to cache, {0} : {1}'.format(name, properties))
+ #self.events_cache.append(event)
+ pass
+ pass
+
+ pass
+
+ def start_emitter(self):
+ self.emitter.start()
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/emitter.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/emitter.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/emitter.py
new file mode 100644
index 0000000..be83250
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/emitter.py
@@ -0,0 +1,88 @@
+#!/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 logging
+import threading
+import time
+import urllib2
+
+logger = logging.getLogger()
+
+class Emitter(threading.Thread):
+ COLLECTOR_URL = "http://{0}/ws/v1/timeline/metrics"
+ RETRY_SLEEP_INTERVAL = 5
+ MAX_RETRY_COUNT = 3
+ """
+ Wake up every send interval seconds and empty the application metric map.
+ """
+ def __init__(self, config, application_metric_map):
+ threading.Thread.__init__(self)
+ logger.debug('Initializing Emitter thread.')
+ self.lock = threading.Lock()
+ self.collector_address = config.get_server_address()
+ self.send_interval = config.get_send_interval()
+ self.application_metric_map = application_metric_map
+
+ def run(self):
+ logger.info('Running Emitter thread: %s' % threading.currentThread().getName())
+ while True:
+ try:
+ self.submit_metrics()
+ time.sleep(self.send_interval)
+ except Exception, e:
+ logger.warn('Unable to emit events. %s' % str(e))
+ time.sleep(self.RETRY_SLEEP_INTERVAL)
+ logger.info('Retrying emit after %s seconds.' % self.RETRY_SLEEP_INTERVAL)
+ pass
+
+ def submit_metrics(self):
+ retry_count = 0
+ while retry_count < self.MAX_RETRY_COUNT:
+ json_data = self.application_metric_map.flatten()
+ if json_data is None:
+ logger.info("Nothing to emit, resume waiting.")
+ break
+ pass
+ response = self.push_metrics(json_data)
+
+ if response and response.getcode() == 200:
+ retry_count = self.MAX_RETRY_COUNT
+ self.application_metric_map.clear()
+ else:
+ logger.warn("Error sending metrics to server. Retrying after {0} "
+ "...".format(self.RETRY_SLEEP_INTERVAL))
+ retry_count += 1
+ time.sleep(self.RETRY_SLEEP_INTERVAL)
+ pass
+ pass
+
+ def push_metrics(self, data):
+ headers = {"Content-Type" : "application/json", "Accept" : "*/*"}
+ server = self.COLLECTOR_URL.format(self.collector_address.strip())
+ logger.info("server: %s" % server)
+ logger.debug("message to sent: %s" % data)
+ req = urllib2.Request(server, data, headers)
+ response = urllib2.urlopen(req, timeout=int(self.send_interval - 10))
+ if response:
+ logger.debug("POST response from server: retcode = {0}".format(response.getcode()))
+ logger.debug(str(response.read()))
+ pass
+ return response
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/event_definition.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/event_definition.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/event_definition.py
new file mode 100644
index 0000000..f356b03
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/event_definition.py
@@ -0,0 +1,85 @@
+#!/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 logging
+
+DEFAULT_COLLECT_INTERVAL = 10
+
+logger = logging.getLogger()
+
+class Event:
+ def __init__(self):
+ self._classname = self.__class__.__name__
+
+ def get_classname(self):
+ return self._classname
+
+ def get_collect_interval(self):
+ return DEFAULT_COLLECT_INTERVAL
+
+
+class EmmitEvent(Event):
+
+ def __init__(self, application_metric_map, config):
+ Event.__init__(self)
+ self.collector_address = config.get_server_address()
+ self.application_metric_map = application_metric_map
+
+ def get_emmit_payload(self):
+ return self.application_metric_map.flatten()
+
+
+class HostMetricCollectEvent(Event):
+
+ def __init__(self, group_config, group_name):
+ Event.__init__(self)
+ self.group_config = group_config
+ self.group_name = group_name
+ try:
+ self.group_interval = group_config['collect_every']
+ self.metrics = group_config['metrics']
+ except KeyError, ex:
+ logger.warn('Unable to create event from metric group. {0}'.format(
+ group_config))
+ raise ex
+
+ def get_metric_value_thresholds(self):
+ metric_value_thresholds = {}
+
+ for metric in self.metrics:
+ try:
+ metric_value_thresholds[metric['name']] = metric['value_threshold']
+ except:
+ logger.warn('Error parsing metric configuration. {0}'.format(metric))
+ pass
+
+ return metric_value_thresholds
+
+ def get_group_name(self):
+ return self.group_name
+
+ def get_collect_interval(self):
+ return int(self.group_interval if self.group_interval else DEFAULT_COLLECT_INTERVAL)
+
+class ProcessMetricCollectEvent:
+
+ def __init__(self, group_config, group_name):
+ # Initialize the Process metric event
+ pass
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/host_info.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/host_info.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/host_info.py
new file mode 100644
index 0000000..6d47485
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/host_info.py
@@ -0,0 +1,190 @@
+#!/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 logging
+import psutil
+import os
+from collections import namedtuple
+import platform
+import socket
+
+logger = logging.getLogger()
+
+def bytes2human(n):
+ bytes = float(n)
+ gigabytes = bytes / 1073741824
+ return '%.2f' % gigabytes
+pass
+
+
+class HostInfo():
+
+
+ def get_cpu_times(self):
+ """
+ Return cpu stats at current time
+ """
+ cpu_times = psutil.cpu_times()
+ load_avg = os.getloadavg()
+
+ return {
+ 'cpu_user' : cpu_times.user if hasattr(cpu_times, 'user') else '',
+ 'cpu_system' : cpu_times.system if hasattr(cpu_times, 'system') else '',
+ 'cpu_idle' : cpu_times.idle if hasattr(cpu_times, 'idle') else '',
+ 'cpu_nice' : cpu_times.nice if hasattr(cpu_times, 'nice') else '',
+ 'cpu_wio' : cpu_times.iowait if hasattr(cpu_times, 'iowait') else '',
+ 'cpu_intr' : cpu_times.irq if hasattr(cpu_times, 'irq') else '',
+ 'cpu_sintr' : cpu_times.softirq if hasattr(cpu_times, 'softirq') else '',
+ 'load_one' : load_avg[0] if len(load_avg) > 0 else '',
+ 'load_five' : load_avg[1] if len(load_avg) > 1 else '',
+ 'load_fifteen' : load_avg[2] if len(load_avg) > 2 else ''
+ }
+ pass
+
+ def get_mem_info(self):
+ """
+ Return memory statistics at current time
+ """
+
+ mem_stats = psutil.virtual_memory()
+ swap_stats = psutil.swap_memory()
+ disk_usage = self.get_combined_disk_usage()
+
+ return {
+ 'mem_free' : mem_stats.free if hasattr(mem_stats, 'free') else '',
+ 'mem_shared' : mem_stats.shared if hasattr(mem_stats, 'shared') else '',
+ 'mem_buffered' : mem_stats.buffers if hasattr(mem_stats, 'buffers') else '',
+ 'mem_cached' : mem_stats.cached if hasattr(mem_stats, 'cached') else '',
+ 'swap_free' : swap_stats.free if hasattr(mem_stats, 'free') else '',
+ 'disk_free' : disk_usage.get("disk_free"),
+ # todo: cannot send string
+ #'part_max_used' : disk_usage.get("max_part_used")[0],
+ 'disk_total' : disk_usage.get("disk_total")
+ }
+ pass
+
+ def get_network_info(self):
+ """
+ Return network counters
+ """
+ net_stats = psutil.net_io_counters()
+
+ return {
+ 'bytes_out' : net_stats.bytes_sent,
+ 'bytes_in' : net_stats.bytes_recv,
+ 'pkts_out' : net_stats.packets_sent,
+ 'pkts_in' : net_stats.packets_recv
+ }
+ pass
+
+ # Faster version
+ def get_combined_disk_usage(self):
+ disk_usage = namedtuple('disk_usage', [ 'total', 'used', 'free',
+ 'percent', 'part_max_used' ])
+ combined_disk_total = 0
+ combined_disk_used = 0
+ combined_disk_free = 0
+ combined_disk_percent = 0
+ max_percent_usage = ('', 0)
+
+ for part in psutil.disk_partitions(all=False):
+ if os.name == 'nt':
+ if 'cdrom' in part.opts or part.fstype == '':
+ # skip cd-rom drives with no disk in it; they may raise
+ # ENOENT, pop-up a Windows GUI error for a non-ready
+ # partition or just hang.
+ continue
+ pass
+ pass
+ usage = psutil.disk_usage(part.mountpoint)
+
+ combined_disk_total += usage.total if hasattr(usage, 'total') else 0
+ combined_disk_used += usage.used if hasattr(usage, 'used') else 0
+ combined_disk_free += usage.free if hasattr(usage, 'free') else 0
+ combined_disk_percent += usage.percent if hasattr(usage, 'percent') else 0
+
+ if hasattr(usage, 'percent') and max_percent_usage[1] < int(usage.percent):
+ max_percent_usage = (part.mountpoint, usage.percent)
+ pass
+ pass
+
+ return { "disk_total" : bytes2human(combined_disk_total),
+ "disk_used" : bytes2human(combined_disk_used),
+ "disk_free" : bytes2human(combined_disk_free),
+ "disk_percent" : bytes2human(combined_disk_percent)
+ # todo: cannot send string
+ #"max_part_used" : max_percent_usage }
+ }
+ pass
+
+ def get_host_static_info(self):
+
+ boot_time = psutil.boot_time()
+ cpu_count_logical = psutil.cpu_count()
+ swap_stats = psutil.swap_memory()
+ mem_info = psutil.virtual_memory()
+
+ return {
+ 'cpu_num' : cpu_count_logical,
+ 'cpu_speed' : '',
+ 'swap_total' : swap_stats.total,
+ 'boottime' : boot_time,
+ 'machine_type' : platform.processor(),
+ 'os_name' : platform.system(),
+ 'os_release' : platform.release(),
+ 'location' : '',
+ 'mem_total' : mem_info.total
+ }
+
+
+
+ def get_disk_usage(self):
+ disk_usage = {}
+
+ for part in psutil.disk_partitions(all=False):
+ if os.name == 'nt':
+ if 'cdrom' in part.opts or part.fstype == '':
+ # skip cd-rom drives with no disk in it; they may raise
+ # ENOENT, pop-up a Windows GUI error for a non-ready
+ # partition or just hang.
+ continue
+ pass
+ pass
+ usage = psutil.disk_usage(part.mountpoint)
+ disk_usage.update(
+ { part.device :
+ {
+ "total" : bytes2human(usage.total),
+ "user" : bytes2human(usage.used),
+ "free" : bytes2human(usage.free),
+ "percent" : int(usage.percent),
+ "fstype" : part.fstype,
+ "mount" : part.mountpoint
+ }
+ }
+ )
+ pass
+ pass
+
+ def get_hostname(self):
+ return socket.getfqdn()
+
+ def get_ip_address(self):
+ return socket.gethostbyname(socket.getfqdn())
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/metric_collector.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/metric_collector.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/metric_collector.py
new file mode 100644
index 0000000..8b82e20
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/core/metric_collector.py
@@ -0,0 +1,87 @@
+#!/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 logging
+from time import time
+from host_info import HostInfo
+from event_definition import HostMetricCollectEvent, ProcessMetricCollectEvent
+
+logger = logging.getLogger()
+
+DEFAULT_HOST_APP_ID = '_HOST'
+
+class MetricsCollector():
+ """
+ The main Reader thread that dequeues events from the event queue and
+ submits a metric record to the emit buffer. Implementation of dequeue is
+ not required if Timer class is used for metric groups.
+ """
+
+ def __init__(self, emit_queue, application_metric_map):
+ self.emit_queue = emit_queue
+ self.application_metric_map = application_metric_map
+ self.host_info = HostInfo()
+ pass
+
+ def process_event(self, event):
+ if event.get_classname() == HostMetricCollectEvent.__name__:
+ self.process_host_collection_event(event)
+ elif event.get_classname() == ProcessMetricCollectEvent.__name__:
+ self.process_process_collection_event(event)
+ else:
+ logger.warn('Unknown event in queue')
+ pass
+
+ def process_host_collection_event(self, event):
+ startTime = int(round(time() * 1000))
+ metrics = None
+
+ if 'cpu' in event.get_group_name():
+ metrics = self.host_info.get_cpu_times()
+
+ elif 'disk' in event.get_group_name():
+ metrics = self.host_info.get_combined_disk_usage()
+
+ elif 'network' in event.get_group_name():
+ metrics = self.host_info.get_network_info()
+
+ elif 'mem' in event.get_group_name():
+ metrics = self.host_info.get_mem_info()
+
+ elif 'all' in event.get_group_name():
+ metrics = {}
+ metrics.update(self.host_info.get_cpu_times())
+ metrics.update(self.host_info.get_combined_disk_usage())
+ metrics.update(self.host_info.get_network_info())
+ metrics.update(self.host_info.get_mem_info())
+
+ else:
+ logger.warn('Unknown metric group.')
+ pass
+
+ if metrics:
+ self.application_metric_map.put_metric(DEFAULT_HOST_APP_ID, metrics, startTime)
+ pass
+
+ def process_process_collection_event(self, event):
+ """
+ Collect Process level metrics and update the application metric map
+ """
+ pass
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/main.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/main.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/main.py
new file mode 100644
index 0000000..09ae7e4
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/main.py
@@ -0,0 +1,64 @@
+#!/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 core
+from core.controller import Controller
+from core.config_reader import Configuration
+import logging
+import signal
+import sys
+
+logger = logging.getLogger()
+
+def main(argv=None):
+ # Allow Ctrl-C
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+ config = Configuration()
+ controller = Controller(config)
+
+ _init_logging(config)
+
+ logger.info('Starting Server RPC Thread: %s' % ' '.join(sys.argv))
+ controller.start()
+ controller.start_emitter()
+
+def _init_logging(config):
+ _levels = {
+ 'DEBUG': logging.DEBUG,
+ 'INFO': logging.INFO,
+ 'WARNING': logging.WARNING,
+ 'ERROR': logging.ERROR,
+ 'CRITICAL': logging.CRITICAL,
+ 'NOTSET' : logging.NOTSET
+ }
+ level = logging.INFO
+ if config.get_log_level() in _levels:
+ level = _levels.get(config.get_log_level())
+ logger.setLevel(level)
+ formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d - %(message)s")
+ stream_handler = logging.StreamHandler()
+ stream_handler.setFormatter(formatter)
+ logger.addHandler(stream_handler)
+
+
+if __name__ == '__main__':
+ main()
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/LICENSE
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/LICENSE b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/LICENSE
new file mode 100644
index 0000000..e91b135
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/LICENSE
@@ -0,0 +1,27 @@
+psutil is distributed under BSD license reproduced below.
+
+Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola'
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the psutil authors nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/MANIFEST.in
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/MANIFEST.in b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/MANIFEST.in
new file mode 100644
index 0000000..d930257
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/MANIFEST.in
@@ -0,0 +1,14 @@
+include CREDITS
+include HISTORY
+include LICENSE
+include make.bat
+include Makefile
+include MANIFEST.in
+include README
+include setup.py
+include TODO
+recursive-include docs *
+recursive-exclude docs/_build *
+recursive-include examples *.py
+recursive-include psutil *.py *.c *.h
+recursive-include test *.py README
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/Makefile
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/Makefile b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/Makefile
new file mode 100644
index 0000000..b812527
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/Makefile
@@ -0,0 +1,77 @@
+# Shortcuts for various tasks (UNIX only).
+# To use a specific Python version run:
+# $ make install PYTHON=python3.3
+
+# You can set these variables from the command line.
+PYTHON = python
+TSCRIPT = test/test_psutil.py
+
+all: test
+
+clean:
+ rm -f `find . -type f -name \*.py[co]`
+ rm -f `find . -type f -name \*.so`
+ rm -f `find . -type f -name .\*~`
+ rm -f `find . -type f -name \*.orig`
+ rm -f `find . -type f -name \*.bak`
+ rm -f `find . -type f -name \*.rej`
+ rm -rf `find . -type d -name __pycache__`
+ rm -rf *.egg-info
+ rm -rf *\$testfile*
+ rm -rf build
+ rm -rf dist
+ rm -rf docs/_build
+
+build: clean
+ $(PYTHON) setup.py build
+
+install: build
+ if test $(PYTHON) = python2.4; then \
+ $(PYTHON) setup.py install; \
+ elif test $(PYTHON) = python2.5; then \
+ $(PYTHON) setup.py install; \
+ else \
+ $(PYTHON) setup.py install --user; \
+ fi
+
+uninstall:
+ if test $(PYTHON) = python2.4; then \
+ pip-2.4 uninstall -y -v psutil; \
+ else \
+ cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
+ fi
+
+test: install
+ $(PYTHON) $(TSCRIPT)
+
+test-process: install
+ $(PYTHON) -m unittest -v test.test_psutil.TestProcess
+
+test-system: install
+ $(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs
+
+# Run a specific test by name; e.g. "make test-by-name disk_" will run
+# all test methods containing "disk_" in their name.
+# Requires "pip install nose".
+test-by-name:
+ @$(PYTHON) -m nose test/test_psutil.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
+
+memtest: install
+ $(PYTHON) test/test_memory_leaks.py
+
+pep8:
+ @hg locate '*py' | xargs pep8
+
+pyflakes:
+ @export PYFLAKES_NODOCTEST=1 && \
+ hg locate '*py' | xargs pyflakes
+
+# Upload source tarball on https://pypi.python.org/pypi/psutil.
+upload-src: clean
+ $(PYTHON) setup.py sdist upload
+
+# Build and upload doc on https://pythonhosted.org/psutil/.
+# Requires "pip install sphinx-pypi-upload".
+upload-doc:
+ cd docs; make html
+ $(PYTHON) setup.py upload_sphinx --upload-dir=docs/_build/html
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/README
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/README b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/README
new file mode 100644
index 0000000..382e5e8
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/README
@@ -0,0 +1,270 @@
+.. image:: https://pypip.in/d/psutil/badge.png
+ :target: https://crate.io/packages/psutil/
+ :alt: Download this month
+
+.. image:: https://pypip.in/v/psutil/badge.png
+ :target: https://pypi.python.org/pypi/psutil/
+ :alt: Latest version
+
+.. image:: https://pypip.in/license/psutil/badge.png
+ :target: https://pypi.python.org/pypi/psutil/
+ :alt: License
+
+===========
+Quick links
+===========
+
+* `Home page <http://code.google.com/p/psutil>`_
+* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
+* `Blog <http://grodola.blogspot.com/search/label/psutil>`_
+* `Documentation <http://pythonhosted.org/psutil/>`_
+* `Forum <http://groups.google.com/group/psutil/topics>`_
+* `What's new <https://psutil.googlecode.com/hg/HISTORY>`_
+
+=======
+Summary
+=======
+
+psutil (python system and process utilities) is a cross-platform library for
+retrieving information on **running processes** and **system utilization**
+(CPU, memory, disks, network) in Python. It is useful mainly for **system
+monitoring**, **profiling and limiting process resources** and **management of
+running processes**. It implements many functionalities offered by command line
+tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
+ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
+**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
+**64-bit** architectures, with Python versions from **2.4 to 3.4**. Pypi is
+also known to work.
+
+==============
+Example usages
+==============
+
+CPU
+===
+
+.. code-block:: python
+
+ >>> import psutil
+ >>> psutil.cpu_times()
+ scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0)
+ >>>
+ >>> for x in range(3):
+ ... psutil.cpu_percent(interval=1)
+ ...
+ 4.0
+ 5.9
+ 3.8
+ >>>
+ >>> for x in range(3):
+ ... psutil.cpu_percent(interval=1, percpu=True)
+ ...
+ [4.0, 6.9, 3.7, 9.2]
+ [7.0, 8.5, 2.4, 2.1]
+ [1.2, 9.0, 9.9, 7.2]
+ >>>
+ >>>
+ >>> for x in range(3):
+ ... psutil.cpu_times_percent(interval=1, percpu=False)
+ ...
+ scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
+ scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
+ scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
+ >>>
+ >>> psutil.cpu_count()
+ 4
+ >>> psutil.cpu_count(logical=False)
+ 2
+ >>>
+
+Memory
+======
+
+.. code-block:: python
+
+ >>> psutil.virtual_memory()
+ svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
+ >>> psutil.swap_memory()
+ sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
+ >>>
+
+Disks
+=====
+
+.. code-block:: python
+
+ >>> psutil.disk_partitions()
+ [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
+ sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
+ >>>
+ >>> psutil.disk_usage('/')
+ sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
+ >>>
+ >>> psutil.disk_io_counters(perdisk=False)
+ sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568)
+ >>>
+
+Network
+=======
+
+.. code-block:: python
+
+ >>> psutil.net_io_counters(pernic=True)
+ {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
+ 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
+ >>>
+ >>> psutil.net_connections()
+ [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
+ pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
+ pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
+ pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
+ ...]
+
+Other system info
+=================
+
+.. code-block:: python
+
+ >>> psutil.users()
+ [user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
+ user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
+ >>>
+ >>> psutil.boot_time()
+ 1365519115.0
+ >>>
+
+Process management
+==================
+
+.. code-block:: python
+
+ >>> import psutil
+ >>> psutil.pids()
+ [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224,
+ 268, 1215, 1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355,
+ 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245,
+ 4263, 4282, 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358,
+ 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, 5167, 5234, 5235,
+ 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]
+ >>>
+ >>> p = psutil.Process(7055)
+ >>> p.name()
+ 'python'
+ >>> p.exe()
+ '/usr/bin/python'
+ >>> p.cwd()
+ '/home/giampaolo'
+ >>> p.cmdline()
+ ['/usr/bin/python', 'main.py']
+ >>>
+ >>> p.status()
+ 'running'
+ >>> p.username()
+ 'giampaolo'
+ >>> p.create_time()
+ 1267551141.5019531
+ >>> p.terminal()
+ '/dev/pts/0'
+ >>>
+ >>> p.uids()
+ puids(real=1000, effective=1000, saved=1000)
+ >>> p.gids()
+ pgids(real=1000, effective=1000, saved=1000)
+ >>>
+ >>> p.cpu_times()
+ pcputimes(user=1.02, system=0.31)
+ >>> p.cpu_percent(interval=1.0)
+ 12.1
+ >>> p.cpu_affinity()
+ [0, 1, 2, 3]
+ >>> p.set_cpu_affinity([0])
+ >>>
+ >>> p.memory_percent()
+ 0.63423
+ >>>
+ >>> p.memory_info()
+ pmem(rss=7471104, vms=68513792)
+ >>> p.ext_memory_info()
+ extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
+ >>> p.memory_maps()
+ [pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
+ pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
+ pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
+ pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0),
+ pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0),
+ ...]
+ >>>
+ >>> p.io_counters()
+ pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
+ >>>
+ >>> p.open_files()
+ [popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
+ >>>
+ >>> p.connections()
+ [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
+ pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
+ pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
+ pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
+ >>>
+ >>> p.num_threads()
+ 4
+ >>> p.num_fds()
+ 8
+ >>> p.threads()
+ [pthread(id=5234, user_time=22.5, system_time=9.2891),
+ pthread(id=5235, user_time=0.0, system_time=0.0),
+ pthread(id=5236, user_time=0.0, system_time=0.0),
+ pthread(id=5237, user_time=0.0707, system_time=1.1)]
+ >>>
+ >>> p.num_ctx_switches()
+ pctxsw(voluntary=78, involuntary=19)
+ >>>
+ >>> p.nice()
+ 0
+ >>> p.set_nice(10)
+ >>>
+ >>> p.set_ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
+ >>> p.ionice()
+ pionice(ioclass=3, value=0)
+ >>>
+ >>> p.set_rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # resource limits (Linux only)
+ >>> p.rlimit(psutil.RLIMIT_NOFILE)
+ (5, 5)
+ >>>
+ >>> p.suspend()
+ >>> p.resume()
+ >>>
+ >>> p.terminate()
+ >>> p.wait(timeout=3)
+ 0
+ >>>
+ >>> psutil.test()
+ USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND
+ root 1 0.0 0.0 24584 2240 Jun17 00:00 init
+ root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd
+ root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0
+ ...
+ giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4
+ giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome
+ root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1
+ >>>
+
+Further process APIs
+====================
+
+.. code-block:: python
+
+ >>> for p in psutil.process_iter():
+ ... print(p)
+ ...
+ psutil.Process(pid=1, name='init')
+ psutil.Process(pid=2, name='kthreadd')
+ psutil.Process(pid=3, name='ksoftirqd/0')
+ ...
+ >>>
+ >>> def on_terminate(proc):
+ ... print("process {} terminated".format(proc))
+ ...
+ >>> # waits for multiple processes to terminate
+ >>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
+ >>>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/build.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/build.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/build.py
new file mode 100644
index 0000000..09fb411
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/build.py
@@ -0,0 +1,57 @@
+#!/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.
+'''
+
+from subprocess import call
+import sys
+import os
+import shutil
+
+def build():
+ path = os.path.dirname(os.path.abspath(__file__))
+ build_path = path + os.sep + 'build'
+ build_out_path = path + os.sep + 'build.out'
+ build_out = open(build_out_path, 'wb')
+
+ # Delete old build dir if exists
+ if (os.path.exists(build_path)):
+ shutil.rmtree(build_path)
+ pass
+
+ cwd = os.getcwd()
+ os.chdir(path)
+
+ print 'Executing make at location: %s ' % path
+
+ if sys.platform.startswith("win"):
+ # Windows
+ returncode = call(['make.bat', 'build'], stdout=build_out, stderr=build_out)
+ else:
+ # Unix based
+ returncode = call(['make', 'build'], stdout=build_out, stderr=build_out)
+ pass
+
+ os.chdir(cwd)
+
+ if returncode != 0:
+ print 'psutil build failed. Please find build output at: %s' % build_out_path
+ pass
+
+if __name__ == '__main__':
+ build()
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/Makefile
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/Makefile b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/Makefile
new file mode 100644
index 0000000..b23ab4b
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ rm -rf $(BUILDDIR)
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/psutil.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psutil.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/psutil"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/psutil"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/README
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/README b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/README
new file mode 100644
index 0000000..9e2f36e
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/README
@@ -0,0 +1,15 @@
+About
+=====
+
+This directory contains the reStructuredText (reST) sources to the psutil
+documentation. You don't need to build them yourself, prebuilt versions are
+available at http://psutil.readthedocs.org/en/latest/.
+In case you want, you need to install sphinx first:
+
+ $ pip install sphinx
+
+Then run:
+
+ $ make html
+
+You'll then have an HTML version of the doc at _build/html/index.html.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/copybutton.js
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/copybutton.js b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/copybutton.js
new file mode 100644
index 0000000..5d82c67
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/copybutton.js
@@ -0,0 +1,57 @@
+$(document).ready(function() {
+ /* Add a [>>>] button on the top-right corner of code samples to hide
+ * the >>> and ... prompts and the output and thus make the code
+ * copyable. */
+ var div = $('.highlight-python .highlight,' +
+ '.highlight-python3 .highlight')
+ var pre = div.find('pre');
+
+ // get the styles from the current theme
+ pre.parent().parent().css('position', 'relative');
+ var hide_text = 'Hide the prompts and output';
+ var show_text = 'Show the prompts and output';
+ var border_width = pre.css('border-top-width');
+ var border_style = pre.css('border-top-style');
+ var border_color = pre.css('border-top-color');
+ var button_styles = {
+ 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
+ 'border-color': border_color, 'border-style': border_style,
+ 'border-width': border_width, 'color': border_color, 'text-size': '75%',
+ 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
+ 'border-radius': '0 3px 0 0'
+ }
+
+ // create and add the button to all the code blocks that contain >>>
+ div.each(function(index) {
+ var jthis = $(this);
+ if (jthis.find('.gp').length > 0) {
+ var button = $('<span class="copybutton">>>></span>');
+ button.css(button_styles)
+ button.attr('title', hide_text);
+ jthis.prepend(button);
+ }
+ // tracebacks (.gt) contain bare text elements that need to be
+ // wrapped in a span to work with .nextUntil() (see later)
+ jthis.find('pre:has(.gt)').contents().filter(function() {
+ return ((this.nodeType == 3) && (this.data.trim().length > 0));
+ }).wrap('<span>');
+ });
+
+ // define the behavior of the button when it's clicked
+ $('.copybutton').toggle(
+ function() {
+ var button = $(this);
+ button.parent().find('.go, .gp, .gt').hide();
+ button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
+ button.css('text-decoration', 'line-through');
+ button.attr('title', show_text);
+ },
+ function() {
+ var button = $(this);
+ button.parent().find('.go, .gp, .gt').show();
+ button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
+ button.css('text-decoration', 'none');
+ button.attr('title', hide_text);
+ });
+});
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/sidebar.js
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/sidebar.js b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/sidebar.js
new file mode 100644
index 0000000..3376963
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_static/sidebar.js
@@ -0,0 +1,161 @@
+/*
+ * sidebar.js
+ * ~~~~~~~~~~
+ *
+ * This script makes the Sphinx sidebar collapsible.
+ *
+ * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds in
+ * .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to
+ * collapse and expand the sidebar.
+ *
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the
+ * width of the sidebar and the margin-left of the document are decreased.
+ * When the sidebar is expanded the opposite happens. This script saves a
+ * per-browser/per-session cookie used to remember the position of the sidebar
+ * among the pages. Once the browser is closed the cookie is deleted and the
+ * position reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+$(function() {
+ // global elements used by the functions.
+ // the 'sidebarbutton' element is defined as global after its
+ // creation, in the add_sidebar_button function
+ var bodywrapper = $('.bodywrapper');
+ var sidebar = $('.sphinxsidebar');
+ var sidebarwrapper = $('.sphinxsidebarwrapper');
+
+ // original margin-left of the bodywrapper and width of the sidebar
+ // with the sidebar expanded
+ var bw_margin_expanded = bodywrapper.css('margin-left');
+ var ssb_width_expanded = sidebar.width();
+
+ // margin-left of the bodywrapper and width of the sidebar
+ // with the sidebar collapsed
+ var bw_margin_collapsed = '.8em';
+ var ssb_width_collapsed = '.8em';
+
+ // colors used by the current theme
+ var dark_color = '#AAAAAA';
+ var light_color = '#CCCCCC';
+
+ function sidebar_is_collapsed() {
+ return sidebarwrapper.is(':not(:visible)');
+ }
+
+ function toggle_sidebar() {
+ if (sidebar_is_collapsed())
+ expand_sidebar();
+ else
+ collapse_sidebar();
+ }
+
+ function collapse_sidebar() {
+ sidebarwrapper.hide();
+ sidebar.css('width', ssb_width_collapsed);
+ bodywrapper.css('margin-left', bw_margin_collapsed);
+ sidebarbutton.css({
+ 'margin-left': '0',
+ //'height': bodywrapper.height(),
+ 'height': sidebar.height(),
+ 'border-radius': '5px'
+ });
+ sidebarbutton.find('span').text('»');
+ sidebarbutton.attr('title', _('Expand sidebar'));
+ document.cookie = 'sidebar=collapsed';
+ }
+
+ function expand_sidebar() {
+ bodywrapper.css('margin-left', bw_margin_expanded);
+ sidebar.css('width', ssb_width_expanded);
+ sidebarwrapper.show();
+ sidebarbutton.css({
+ 'margin-left': ssb_width_expanded-12,
+ //'height': bodywrapper.height(),
+ 'height': sidebar.height(),
+ 'border-radius': '0 5px 5px 0'
+ });
+ sidebarbutton.find('span').text('«');
+ sidebarbutton.attr('title', _('Collapse sidebar'));
+ //sidebarwrapper.css({'padding-top':
+ // Math.max(window.pageYOffset - sidebarwrapper.offset().top, 10)});
+ document.cookie = 'sidebar=expanded';
+ }
+
+ function add_sidebar_button() {
+ sidebarwrapper.css({
+ 'float': 'left',
+ 'margin-right': '0',
+ 'width': ssb_width_expanded - 28
+ });
+ // create the button
+ sidebar.append(
+ '<div id="sidebarbutton"><span>«</span></div>'
+ );
+ var sidebarbutton = $('#sidebarbutton');
+ // find the height of the viewport to center the '<<' in the page
+ var viewport_height;
+ if (window.innerHeight)
+ viewport_height = window.innerHeight;
+ else
+ viewport_height = $(window).height();
+ var sidebar_offset = sidebar.offset().top;
+
+ var sidebar_height = sidebar.height();
+ //var sidebar_height = Math.max(bodywrapper.height(), sidebar.height());
+ sidebarbutton.find('span').css({
+ 'display': 'block',
+ 'margin-top': sidebar_height/2 - 10
+ //'margin-top': (viewport_height - sidebar.position().top - 20) / 2
+ //'position': 'fixed',
+ //'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10
+ });
+
+ sidebarbutton.click(toggle_sidebar);
+ sidebarbutton.attr('title', _('Collapse sidebar'));
+ sidebarbutton.css({
+ 'border-radius': '0 5px 5px 0',
+ 'color': '#444444',
+ 'background-color': '#CCCCCC',
+ 'font-size': '1.2em',
+ 'cursor': 'pointer',
+ 'height': sidebar_height,
+ 'padding-top': '1px',
+ 'padding-left': '1px',
+ 'margin-left': ssb_width_expanded - 12
+ });
+
+ sidebarbutton.hover(
+ function () {
+ $(this).css('background-color', dark_color);
+ },
+ function () {
+ $(this).css('background-color', light_color);
+ }
+ );
+ }
+
+ function set_position_from_cookie() {
+ if (!document.cookie)
+ return;
+ var items = document.cookie.split(';');
+ for(var k=0; k<items.length; k++) {
+ var key_val = items[k].split('=');
+ var key = key_val[0];
+ if (key == 'sidebar') {
+ var value = key_val[1];
+ if ((value == 'collapsed') && (!sidebar_is_collapsed()))
+ collapse_sidebar();
+ else if ((value == 'expanded') && (sidebar_is_collapsed()))
+ expand_sidebar();
+ }
+ }
+ }
+
+ add_sidebar_button();
+ var sidebarbutton = $('#sidebarbutton');
+ set_position_from_cookie();
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/globaltoc.html
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/globaltoc.html b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/globaltoc.html
new file mode 100644
index 0000000..f5fbb40
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/globaltoc.html
@@ -0,0 +1,12 @@
+{#
+ basic/globaltoc.html
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx sidebar template: global table of contents.
+
+ :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+<h3>{{ _('Manual') }}</h3>
+{{ toctree() }}
+<a href="{{ pathto(master_doc) }}">Back to Welcome</a>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexcontent.html
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexcontent.html b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexcontent.html
new file mode 100644
index 0000000..dd5e724
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexcontent.html
@@ -0,0 +1,4 @@
+{% extends "defindex.html" %}
+{% block tables %}
+
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexsidebar.html
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexsidebar.html b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexsidebar.html
new file mode 100644
index 0000000..4af2296
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/indexsidebar.html
@@ -0,0 +1,16 @@
+<!--
+<h3>Other versions</h3>
+<ul>
+ <li><a href="http://psutil.readthedocs.org/en/latest/">Latest</a></li>
+ <li><a href="http://psutil.readthedocs.org/en/0.6/">0.6</a></li>
+ <li><a href="http://psutil.readthedocs.org/en/0.5/">0.5</a></li>
+</ul>
+-->
+<h3>Useful links</h3>
+<ul>
+ <li><a href="http://code.google.com/p/psutil/">Google Code Project</a></li>
+ <li><a href="http://grodola.blogspot.com/search/label/psutil">Blog</a></li>
+ <li><a href="https://pypi.python.org/pypi?:action=display&name=psutil#downloads">Download</a></li>
+ <li><a href="https://code.google.com/p/psutil/issues/list">Issues</a></li>
+ <li><a href="http://groups.google.com/group/psutil/topics">Forum</a></li>
+</ul>
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/page.html
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/page.html b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/page.html
new file mode 100644
index 0000000..e6686e9
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_template/page.html
@@ -0,0 +1,66 @@
+{% extends "!page.html" %}
+{% block extrahead %}
+{{ super() }}
+{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
+<script type="text/javascript">
+
+ // Store editor pop-up help state in localStorage
+ // so it does not re-pop-up itself between page loads.
+ // Do not even to pretend to support IE gracefully.
+ (function($) {
+
+ $(document).ready(function() {
+ var box = $("#editor-trap");
+ var klass = "toggled";
+ var storageKey = "toggled";
+
+ function toggle() {
+ box.toggleClass(klass);
+ // Store the toggle status in local storage as "has value string" or null
+ window.localStorage.setItem(storageKey, box.hasClass(klass) ? "toggled" : "not-toggled");
+ }
+
+ box.click(toggle);
+
+ // Check the persistent state of the editor pop-up
+ // Note that localStorage does not necessarily support boolean values (ugh!)
+ // http://stackoverflow.com/questions/3263161/cannot-set-boolean-values-in-localstorage
+ var v = window.localStorage.getItem(storageKey);
+ if(v == "toggled" || !v) {
+ box.addClass(klass);
+ }
+
+ });
+
+ })(jQuery);
+</script>
+<script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-2097050-4']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+</script>
+{% endblock %}
+
+{% block rootrellink %}
+ <li><a href="http://code.google.com/p/psutil/"><img src="{{ pathto('_static/logo.png', 1) }}" style="height: 30px; vertical-align: middle; padding-right: 1em;" /> Project Homepage</a>{{ reldelim1 }}</li>
+ <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+{% endblock %}
+
+
+{% block footer %}
+<div class="footer">
+ © Copyright {{ copyright|e }}.
+ <br />
+ Last updated on {{ last_updated|e }}.
+ <br />
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version|e }}.
+</div>
+{% endblock %}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
new file mode 100644
index 0000000..4196e55
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
@@ -0,0 +1,187 @@
+@import url("default.css");
+
+body {
+ background-color: white;
+ margin-left: 1em;
+ margin-right: 1em;
+}
+
+div.related {
+ margin-bottom: 1.2em;
+ padding: 0.5em 0;
+ border-top: 1px solid #ccc;
+ margin-top: 0.5em;
+}
+
+div.related a:hover {
+ color: #0095C4;
+}
+
+div.related:first-child {
+ border-top: 0;
+ padding-top: 0;
+ border-bottom: 1px solid #ccc;
+}
+
+div.sphinxsidebar {
+ background-color: #eeeeee;
+ border-radius: 5px;
+ line-height: 130%;
+ font-size: smaller;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+ margin-top: 1.5em;
+}
+
+div.sphinxsidebarwrapper > h3:first-child {
+ margin-top: 0.2em;
+}
+
+div.sphinxsidebarwrapper > ul > li > ul > li {
+ margin-bottom: 0.4em;
+}
+
+div.sphinxsidebar a:hover {
+ color: #0095C4;
+}
+
+div.sphinxsidebar input {
+ font-family: 'Lucida Grande','Lucida Sans','DejaVu Sans',Arial,sans-serif;
+ border: 1px solid #999999;
+ font-size: smaller;
+ border-radius: 3px;
+}
+
+div.sphinxsidebar input[type=text] {
+ max-width: 150px;
+}
+
+div.body {
+ padding: 0 0 0 1.2em;
+}
+
+div.body p {
+ line-height: 140%;
+}
+
+div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
+ margin: 0;
+ border: 0;
+ padding: 0.3em 0;
+}
+
+div.body hr {
+ border: 0;
+ background-color: #ccc;
+ height: 1px;
+}
+
+div.body pre {
+ border-radius: 3px;
+ border: 1px solid #ac9;
+}
+
+div.body div.admonition, div.body div.impl-detail {
+ border-radius: 3px;
+}
+
+div.body div.impl-detail > p {
+ margin: 0;
+}
+
+div.body div.seealso {
+ border: 1px solid #dddd66;
+}
+
+div.body a {
+ color: #00608f;
+}
+
+div.body a:visited {
+ color: #30306f;
+}
+
+div.body a:hover {
+ color: #00B0E4;
+}
+
+tt, pre {
+ font-family: monospace, sans-serif;
+ font-size: 96.5%;
+}
+
+div.body tt {
+ border-radius: 3px;
+}
+
+div.body tt.descname {
+ font-size: 120%;
+}
+
+div.body tt.xref, div.body a tt {
+ font-weight: normal;
+}
+
+p.deprecated {
+ border-radius: 3px;
+}
+
+table.docutils {
+ border: 1px solid #ddd;
+ min-width: 20%;
+ border-radius: 3px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+table.docutils td, table.docutils th {
+ border: 1px solid #ddd !important;
+ border-radius: 3px;
+}
+
+table p, table li {
+ text-align: left !important;
+}
+
+table.docutils th {
+ background-color: #eee;
+ padding: 0.3em 0.5em;
+}
+
+table.docutils td {
+ background-color: white;
+ padding: 0.3em 0.5em;
+}
+
+table.footnote, table.footnote td {
+ border: 0 !important;
+}
+
+div.footer {
+ line-height: 150%;
+ margin-top: -2em;
+ text-align: right;
+ width: auto;
+ margin-right: 10px;
+}
+
+div.footer a:hover {
+ color: #0095C4;
+}
+
+div.body h1,
+div.body h2,
+div.body h3 {
+ background-color: #EAEAEA;
+ border-bottom: 1px solid #CCC;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ padding-left: 5px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+div.body h2 {
+ padding-left:10px;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/theme.conf
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/theme.conf b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/theme.conf
new file mode 100644
index 0000000..95b97e5
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/_themes/pydoctheme/theme.conf
@@ -0,0 +1,23 @@
+[theme]
+inherit = default
+stylesheet = pydoctheme.css
+pygments_style = sphinx
+
+[options]
+bodyfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
+headfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
+footerbgcolor = white
+footertextcolor = #555555
+relbarbgcolor = white
+relbartextcolor = #666666
+relbarlinkcolor = #444444
+sidebarbgcolor = white
+sidebartextcolor = #444444
+sidebarlinkcolor = #444444
+bgcolor = white
+textcolor = #222222
+linkcolor = #0090c0
+visitedlinkcolor = #00608f
+headtextcolor = #1a1a1a
+headbgcolor = white
+headlinkcolor = #aaaaaa
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/conf.py
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/conf.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/conf.py
new file mode 100644
index 0000000..0c6608a
--- /dev/null
+++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/docs/conf.py
@@ -0,0 +1,253 @@
+# -*- coding: utf-8 -*-
+#
+# psutil documentation build configuration file, created by
+# sphinx-quickstart.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import datetime
+import os
+
+
+PROJECT_NAME = u"psutil"
+AUTHOR = u"Giampaolo Rodola'"
+THIS_YEAR = str(datetime.datetime.now().year)
+HERE = os.path.abspath(os.path.dirname(__file__))
+
+def get_version():
+ INIT = os.path.abspath(os.path.join(HERE, '../psutil/__init__.py'))
+ f = open(INIT, 'r')
+ try:
+ for line in f:
+ if line.startswith('__version__'):
+ ret = eval(line.strip().split(' = ')[1])
+ assert ret.count('.') == 2, ret
+ for num in ret.split('.'):
+ assert num.isdigit(), ret
+ return ret
+ else:
+ raise ValueError("couldn't find version string")
+ finally:
+ f.close()
+
+VERSION = get_version()
+
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['sphinx.ext.autodoc',
+ 'sphinx.ext.coverage',
+ 'sphinx.ext.pngmath',
+ 'sphinx.ext.viewcode',
+ 'sphinx.ext.intersphinx']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_template']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = PROJECT_NAME
+copyright = u'2009-%s, %s' % (THIS_YEAR, AUTHOR)
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = VERSION
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+autodoc_docstring_signature = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+html_theme = 'pydoctheme'
+html_theme_options = {'collapsiblesidebar': True}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ["_themes"]
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+html_title = "{project} {version} documentation".format(**locals())
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = 'logo.png'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+html_favicon = 'favicon.ico'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {
+ 'index': 'indexsidebar.html',
+ '**': ['globaltoc.html',
+ 'relations.html',
+ 'sourcelink.html',
+ 'searchbox.html']
+}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {
+# 'index': 'indexcontent.html',
+#}
+
+# If false, no module index is generated.
+html_domain_indices = False
+
+# If false, no index is generated.
+html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = '%s-doc' % PROJECT_NAME
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', '%s.tex' % PROJECT_NAME,
+ u'%s documentation' % PROJECT_NAME, AUTHOR),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', PROJECT_NAME, u'%s documentation' % PROJECT_NAME, [AUTHOR], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False