Source code for pyfarm.agent.http.system

# No shebang line, this module is meant to be imported
#
# Copyright 2014 Oliver Palmer
#
# Licensed 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 time
from datetime import timedelta

try:
    from httplib import OK
except ImportError:  # pragma: no cover
    from http.client import OK

import psutil
from pyfarm.core.enums import AgentState
from pyfarm.agent.config import config
from pyfarm.agent.http.core.resource import Resource
from pyfarm.agent.sysinfo import cpu, memory


[docs]def mb(value): if isinstance(value, float): value = int(value) return str(value) + "MB"
[docs]def seconds(value): if value is not None: return "%.2f seconds" % value
[docs]class HTMLResource(Resource): # TODO: add content types for forms once they work again ALLOWED_CONTENT_TYPE = frozenset(["text/html", ""]) ALLOWED_ACCEPT = frozenset(["text/html", "*/*"])
[docs]class Index(HTMLResource): """serves request for the root, '/', target""" TEMPLATE = "index.html"
[docs] def get(self, **_): # convert the state integer to a string for key, value in AgentState._asdict().iteritems(): if config["state"] == value: state = key.title() break ram_allocated = int( (memory.used_ram() / float(config["agent_ram"])) * 100) if ram_allocated >= 100: # pragma: no cover ram_css = "danger" elif ram_allocated >= 75: # pragma: no cover ram_css = "warning" elif ram_allocated >= 50: # pragma: no cover ram_css = "info" else: ram_css = None memory_info = [ ("RAM Used", "%.2f%% (%s of %s)" % ( ram_allocated, memory.used_ram(), mb((config["agent_ram"]))), ram_css), ("System RAM", memory.total_ram(), None), ("System RAM (reported)", mb(config["agent_ram"]), None), ("Agent RAM Usage", memory.process_memory(), None)] network_info = [ ("Hostname", config["agent_hostname"]), ("Agent Port", config["agent_api_port"]), ("Master API", config["master_api"])] cpu_info = [ ("CPUs", cpu.total_cpus()), ("CPUs (reported)", config["agent_cpus"]), ("System Time", seconds(cpu.system_time())), ("User Time", seconds(cpu.user_time())), ("Idle Time", seconds(cpu.idle_time())), ("IO Wait", seconds(cpu.iowait()) or "Not Supported")] agent_id = config["agent_id"] if "agent_id" in config else None miscellaneous = [ ("Database ID", agent_id), ("Agent State", state), ("Logged On User(s)", ", ".join(sorted(set(user.name for user in psutil.users())))), ("Host Uptime", str(timedelta(seconds=time.time() - psutil.boot_time()))), ("Agent Uptime", str(timedelta(seconds=time.time() - config["start"])))] return self.template.render( memory_info=memory_info, network_info=network_info, cpu_info=cpu_info, miscellaneous=miscellaneous), OK
# TODO: form submission # TODO: make 'port' field editable (requires restart) # TODO: add callbacks for any field that needs to update the db
[docs]class Configuration(HTMLResource): TEMPLATE = "configuration.html" # fields which nobody can see HIDDEN_FIELDS = ( "agent", "agent_pretty_json") # fields that a user can edit EDITABLE_FIELDS = ( "agent_cpus", "agent_hostname", "master_api", "master", "agent_ram_check_interval", "agent_ram", "agent_ram_report_delta", "agent_time_offset", "state", "agent_http_retry_delay_factor", "agent_http_retry_delay_offset")
[docs] def get(self, **_): editable_fields = [] non_editable_fields = [] for key, value in sorted(config.items()): if key in self.HIDDEN_FIELDS: pass elif key in self.EDITABLE_FIELDS: editable_fields.append((key, value)) else: non_editable_fields.append((key, value)) return self.template.render( non_editable_fields=non_editable_fields, editable_fields=editable_fields), OK