improved views and links between them.
improved pcuview
added testing functions for rebooting, and probing the node state in real-time.
improved pcucontrol/reboot.py object model.
improved findbad.py ability to update a single record. more needed here.
from nodequery import verify,query_to_dict,node_select
import traceback
-print "starting sqlfindbad.py"
+#print "starting sqlfindbad.py"
# QUERY all nodes.
COMON_COTOPURL= "http://summer.cs.princeton.edu/status/tabulator.cgi?" + \
"table=table_nodeview&" + \
fbnodesync = FindbadNodeRecordSync.findby_or_create(hostname=nodename,
if_new_set={'round' : global_round})
- fbrec = FindbadNodeRecord(
- date_checked=datetime.fromtimestamp(values['date_checked']),
+ # NOTE: This code will either add a new record for the new global_round,
+ # OR it will find the previous value, and update it
+ # with new information.
+ # The data that is 'lost' is not that important, b/c older
+ # history still exists.
+ fbrec = FindbadNodeRecord.findby_or_create(
round=global_round,
- hostname=nodename,
- loginbase=values['loginbase'],
- kernel_version=values['kernel'],
- bootcd_version=values['bootcd'],
- nm_status=values['nm'],
- fs_status=values['readonlyfs'],
- dns_status=values['dns'],
- princeton_comon_dir=values['princeton_comon'],
- princeton_comon_running=values['princeton_comon_running'],
- princeton_comon_procs=values['princeton_comon_procs'],
- plc_node_stats = values['plcnode'],
- plc_site_stats = values['plcsite'],
- plc_pcuid = values['pcu'],
- comon_stats = values['comonstats'],
- ping_status = (values['ping'] == "PING"),
- ssh_portused = values['sshport'],
- ssh_status = (values['ssh'] == "SSH"),
- ssh_error = values['ssherror'],
- observed_status = values['state'],
- observed_category = values['category'],
- )
+ hostname=nodename)
+ before = fbrec.to_dict()
+ print "BEFORE, ", before
+ fbrec.flush()
+ time.sleep(2)
+ print "Setting VALUES"
+ fbrec.set( date_checked=datetime.fromtimestamp(values['date_checked']),
+ loginbase=values['loginbase'],
+ kernel_version=values['kernel'],
+ bootcd_version=values['bootcd'],
+ nm_status=values['nm'],
+ fs_status=values['readonlyfs'],
+ dns_status=values['dns'],
+ princeton_comon_dir=values['princeton_comon'],
+ princeton_comon_running=values['princeton_comon_running'],
+ princeton_comon_procs=values['princeton_comon_procs'],
+ plc_node_stats = values['plcnode'],
+ plc_site_stats = values['plcsite'],
+ plc_pcuid = values['pcu'],
+ comon_stats = values['comonstats'],
+ ping_status = (values['ping'] == "PING"),
+ ssh_portused = values['sshport'],
+ ssh_status = (values['ssh'] == "SSH"),
+ ssh_error = values['ssherror'],
+ observed_status = values['state'],
+ observed_category = values['category'])
+ after = fbrec.to_dict()
+ print "AFTER , ", after
+
+ for v in before.keys():
+ if before[v] == after[v]:
+ print "SAME FOR KEY %s" % v
+ print "%s : %s\t%s" % ( v, before[v], after[v] )
+
+ fbrec.flush()
fbnodesync.round = global_round
fbnodesync.flush()
fbsync.flush()
- fbrec.flush()
count += 1
print "%d %s %s" % (count, nodename, values)
for i in result:
print "Result: %s" % i
+def probe(hostname):
+ try:
+ (nodename, values) = collectPingAndSSH(hostname, {})
+ recordPingAndSSH(None, (nodename, values))
+ session.flush()
+ return True
+ except:
+ print traceback.print_exc()
+ return False
+
def checkAndRecordState(l_nodes, cohash):
global global_round
errorState = {}
count = 0
-def nmap_portstatus(status):
+def nmap_port_status(status):
ps = {}
l_nmap = status.split()
ports = l_nmap[4:]
#### COMPLETE ENTRY #######################
- values['complete_entry'] = []
+ values['entry_complete'] = []
#if values['protocol'] is None or values['protocol'] is "":
- # values['complete_entry'] += ["protocol"]
+ # values['entry_complete'] += ["protocol"]
if values['plc_pcu_stats']['model'] is None or values['plc_pcu_stats']['model'] is "":
- values['complete_entry'] += ["model"]
+ values['entry_complete'] += ["model"]
# Cannot continue due to this condition
continue_probe = False
if values['plc_pcu_stats']['password'] is None or values['plc_pcu_stats']['password'] is "":
- values['complete_entry'] += ["password"]
+ values['entry_complete'] += ["password"]
# Cannot continue due to this condition
continue_probe = False
- if len(values['complete_entry']) > 0:
+ if len(values['entry_complete']) > 0:
continue_probe = False
if values['plc_pcu_stats']['hostname'] is None or values['plc_pcu_stats']['hostname'] is "":
- values['complete_entry'] += ["hostname"]
+ values['entry_complete'] += ["hostname"]
if values['plc_pcu_stats']['ip'] is None or values['plc_pcu_stats']['ip'] is "":
- values['complete_entry'] += ["ip"]
+ values['entry_complete'] += ["ip"]
# If there are no nodes associated with this PCU, then we cannot continue.
if len(values['plc_pcu_stats']['node_ids']) == 0:
continue_probe = False
- values['complete_entry'] += ['NoNodeIds']
+ values['entry_complete'] += ['NoNodeIds']
#### DNS and IP MATCH #######################
if values['plc_pcu_stats']['hostname'] is not None and values['plc_pcu_stats']['hostname'] is not "" and \
try:
ipaddr = socket.gethostbyname(values['plc_pcu_stats']['hostname'])
if ipaddr == values['plc_pcu_stats']['ip']:
- values['dnsmatch'] = "DNS-OK"
+ values['dns_status'] = "DNS-OK"
else:
- values['dnsmatch'] = "DNS-MISMATCH"
+ values['dns_status'] = "DNS-MISMATCH"
continue_probe = False
except Exception, err:
- values['dnsmatch'] = "DNS-NOENTRY"
+ values['dns_status'] = "DNS-NOENTRY"
values['plc_pcu_stats']['hostname'] = values['plc_pcu_stats']['ip']
#print err
else:
if values['plc_pcu_stats']['ip'] is not None and values['plc_pcu_stats']['ip'] is not "":
- values['dnsmatch'] = "NOHOSTNAME"
+ values['dns_status'] = "NOHOSTNAME"
values['plc_pcu_stats']['hostname'] = values['plc_pcu_stats']['ip']
else:
- values['dnsmatch'] = "NO-DNS-OR-IP"
+ values['dns_status'] = "NO-DNS-OR-IP"
values['plc_pcu_stats']['hostname'] = "No_entry_in_DB"
continue_probe = False
nmap = util.command.CMD()
(oval,eval) = nmap.run_noexcept("nmap -oG - -P0 -p22,23,80,443,5869,9100,16992 %s | grep Host:" % reboot.pcu_name(values['plc_pcu_stats']))
# NOTE: an empty / error value for oval, will still work.
- (values['portstatus'], continue_probe) = nmap_portstatus(oval)
+ (values['port_status'], continue_probe) = nmap_port_status(oval)
else:
- values['portstatus'] = None
+ values['port_status'] = None
###### DRY RUN ############################
if 'node_ids' in values['plc_pcu_stats'] and len(values['plc_pcu_stats']['node_ids']) > 0:
- rb_ret = reboot.reboot_test(values['plc_pcu_stats']['nodenames'][0], values, continue_probe, 1, True)
+ rb_ret = reboot.reboot_test_new(values['plc_pcu_stats']['nodenames'][0], values, continue_probe, 1, True)
else:
rb_ret = "Not_Run" # No nodes to test"
print "____________________________________"
errors['traceback'] = traceback.format_exc()
print errors['traceback']
+ values['reboot'] = errors['traceback']
values['date_checked'] = time.time()
return (pcuname, values, errors)
round=fbsync.round,
plc_pcuid=pcu_id,
plc_pcu_stats=values['plc_pcu_stats'],
- dns_status=values['dnsmatch'],
- port_status=values['portstatus'],
- entry_complete=" ".join(values['complete_entry']),
+ dns_status=values['dns_status'],
+ port_status=values['port_status'],
+ entry_complete=" ".join(values['entry_complete']),
reboot_trial_status="%s" % values['reboot'],
)
fbnodesync.round = global_round
return 0
+print "main"
if __name__ == '__main__':
import logging
logger = logging.getLogger("monitor")
site=None,
dbname="findbadpcus",
cachenodes=False,
- refresh=False,
+ cachecalls=True,
force=False,
)
parser.add_option("-f", "--nodelist", dest="nodelist", metavar="FILE",
help="Cache node lookup from PLC")
parser.add_option("", "--dbname", dest="dbname", metavar="FILE",
help="Specify the name of the database to which the information is saved")
- parser.add_option("", "--refresh", action="store_true", dest="refresh",
+ parser.add_option("", "--nocachecalls", action="store_false", dest="cachecalls",
help="Refresh the cached values")
parser.add_option("-i", "--increment", action="store_true", dest="increment",
help="Increment round number to force refresh or retry")
help="Force probe without incrementing global 'round'.")
parser = parsermodule.getParser(['defaults'], parser)
config = parsermodule.parse_args(parser)
+ if hasattr(config, 'cachecalls') and not config.cachecalls:
+ # NOTE: if explicilty asked, refresh cached values.
+ print "Reloading PLCCache"
+ plccache.init()
try:
# NOTE: evidently, there is a bizarre interaction between iLO and ssh
# when LANG is set... Do not know why. Unsetting LANG, fixes the problem.
f.write( api.AdmGenerateNodeConfFile(n[0]['node_id']) )
f.close()
print os.system("cd bootcd; ./build.sh -f %s.txt -t iso -o /plc/data/var/www/html/bootcds/%s.iso &> /dev/null" % ( hostname, hostname))
+ print "cd bootcd; ./build.sh -f %s.txt -t usb_partition -o /plc/data/var/www/html/bootcds/%s-partition.usb &> /dev/null" % ( hostname, hostname)
print os.system("cd bootcd; ./build.sh -f %s.txt -t usb_partition -o /plc/data/var/www/html/bootcds/%s-partition.usb &> /dev/null" % ( hostname, hostname))
else:
# assume that the images have already been generated..
cachetime=60
[commandline]
+embedded=True
echo=False
debug=0
mail=1
fbsync = FindbadNodeRecordSync.get_by(hostname="global")
if fbsync:
kwargs['round'] = fbsync.round
- return cls.query.filter_by(**kwargs)
+ return cls.query.filter_by(**kwargs).order_by(FindbadNodeRecord.date_checked.desc())
else:
return []
def get_latest_by(cls, **kwargs):
fbsync = FindbadPCURecordSync.get_by(plc_pcuid=0)
kwargs['round'] = fbsync.round
- return cls.query.filter_by(**kwargs)
+ return cls.query.filter_by(**kwargs).order_by(FindbadPCURecord.date_checked.desc())
# ACCOUNTING
date_checked = Field(DateTime)
round = Field(Int,default=0)
def run_or_returncached(*params):
cachename = self._param_to_str(name, *params)
#print "cachename is %s" % cachename
+ if hasattr(config, 'refresh'):
+ refresh = config.refresh
+ else:
+ refresh = False
+
if 'Get' in name:
if not database.cachedRecently(cachename):
load_old_cache = False
anon = {'AuthMethod': "anonymous"}
nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0]
if nodeinfo['pcu_ids']:
+ print nodeinfo
sitepcu = api.GetPCUs(auth.auth, nodeinfo['pcu_ids'])[0]
+ print sitepcu
+ print nodeinfo["ports"]
sitepcu[nodename] = nodeinfo["ports"][0]
return sitepcu
else:
id2lb[site['site_id']] = site['login_base']
else:
#print "Two sites have the same login_base value %s!" % site['login_base']
- sys.exit(1)
+ #sys.exit(1)
+ continue
return (d_sites, id2lb)
def dsn_from_dsln(d_sites, id2lb, l_nodes):
l_sites = plc.getSites({'peer_id':None}, ['login_base', 'site_id', 'abbreviated_name', 'latitude', 'longitude',
'max_slices', 'slice_ids', 'node_ids' ])
if len(l_sites) == 0:
+ print "no sites! exiting..."
sys.exit(1)
(d_sites,id2lb) = dsites_from_lsites(l_sites)
import pcucontrol.transports.pyssh as pyssh
from monitor import config
+from monitor.database.info.model import FindbadPCURecord
+
# Timeouts in seconds
TELNET_TIMEOUT = 45
# This class captures the observed pcu records from FindBadPCUs.py
class PCURecord:
def __init__(self, pcu_record_dict):
- for field in ['nodenames', 'portstatus',
- 'dnsmatch',
- 'complete_entry', ]:
+ for field in ['port_status',
+ 'dns_status',
+ 'entry_complete', ]:
if field in pcu_record_dict:
if field == "reboot":
self.__setattr__("reboot_str", pcu_record_dict[field])
TELNET = 1
SSH = 2
HTTP = 3
- IPAL = 4
+ HTTPS = 4
+ IPAL = 5
TELNET_TIMEOUT = 120
PCUModel.__init__(self, plc_pcu_record)
PCURecord.__init__(self, plc_pcu_record)
type = None
- if self.portstatus:
- if '22' in supported_ports and self.portstatus['22'] == "open":
+ if self.port_status:
+ if '22' in supported_ports and self.port_status['22'] == "open":
type = Transport.SSH
- elif '23' in supported_ports and self.portstatus['23'] == "open":
+ elif '23' in supported_ports and self.port_status['23'] == "open":
type = Transport.TELNET
- elif '80' in supported_ports and self.portstatus['80'] == "open":
- type = Transport.HTTP
- elif '443' in supported_ports and self.portstatus['443'] == "open":
+ # NOTE: prefer https over http
+ elif '443' in supported_ports and self.port_status['443'] == "open":
+ type = Transport.HTTPS
+ elif '80' in supported_ports and self.port_status['80'] == "open":
type = Transport.HTTP
- elif '5869' in supported_ports and self.portstatus['5869'] == "open":
+ elif '5869' in supported_ports and self.port_status['5869'] == "open":
# For DRAC cards. Racadm opens this port.
type = Transport.HTTP
- elif '9100' in supported_ports and self.portstatus['9100'] == "open":
+ elif '9100' in supported_ports and self.port_status['9100'] == "open":
type = Transport.IPAL
- elif '16992' in supported_ports and self.portstatus['16992'] == "open":
+ elif '16992' in supported_ports and self.port_status['16992'] == "open":
type = Transport.HTTP
else:
raise ExceptionPort("Unsupported Port: No transport from open ports")
else:
- raise Exception("No Portstatus: No transport because no open ports")
+ raise ExceptionPort("No Portstatus: No transport because no open ports")
Transport.__init__(self, type, verbose)
def run(self, node_port, dryrun):
except ExceptionNotFound, err:
return "error: " + str(err)
except ExceptionPassword, err:
- return "password exception: " + str(err)
+ return "Password exception: " + str(err)
except ExceptionTimeout, err:
- return "timeout exception: " + str(err)
+ return "Timeout exception: " + str(err)
except ExceptionUsername, err:
- return "exception: no username prompt: " + str(err)
+ return "No username prompt: " + str(err)
except ExceptionSequence, err:
- return "sequence error: " + str(err)
+ return "Sequence error: " + str(err)
except ExceptionPrompt, err:
- return "prompt exception: " + str(err)
+ return "Prompt exception: " + str(err)
+ except ExceptionNoTransport, err:
+ return "No Transport: " + str(err)
except ExceptionPort, err:
- return "no ports exception: " + str(err)
+ return "No ports exception: " + str(err)
except socket.error, err:
return "socket error: timeout: " + str(err)
+ except urllib2.HTTPError, err:
+ return "HTTPError: " + str(err)
+ except urllib2.URLError, err:
+ return "URLError: " + str(err)
except EOFError, err:
if self.verbose:
logger.debug("reboot: EOF")
elif self.type == Transport.TELNET:
return self.run_telnet(node_port, dryrun)
else:
- raise Exception("Unimplemented Transport for IPAL")
+ raise ExceptionNoTransport("Unimplemented Transport for IPAL")
def run_telnet(self, node_port, dryrun):
# TELNET version of protocol...
s.close()
return 0
+class APCControl(PCUControl):
+ supported_ports = [22,23,80,443]
+ reboot_sequence = []
-class APCEurope(PCUControl):
def run(self, node_port, dryrun):
- self.open(self.host, self.username)
- self.sendPassword(self.password)
-
- self.ifThenSend("\r\n> ", "1", ExceptionPassword)
- self.ifThenSend("\r\n> ", "2")
- self.ifThenSend("\r\n> ", str(node_port))
- # 3- Immediate Reboot
- self.ifThenSend("\r\n> ", "3")
-
- if not dryrun:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "YES\r\n",
- ExceptionSequence)
+ print "RUNNING!!!!!!!!!!!!"
+ if self.type == Transport.HTTPS or self.type == Transport.HTTP:
+ print "APC via http...."
+ return self.run_http_or_https(node_port, dryrun)
else:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "", ExceptionSequence)
- self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
- self.close()
- return 0
+ print "APC via telnet/ssh...."
+ return self.run_telnet_or_ssh(node_port, dryrun)
-class APCBrazil(PCUControl):
- def run(self, node_port, dryrun):
+ def run_telnet_or_ssh(self, node_port, dryrun):
self.open(self.host, self.username)
self.sendPassword(self.password)
- self.ifThenSend("\r\n> ", "1", ExceptionPassword)
- self.ifThenSend("\r\n> ", str(node_port))
- # 4- Immediate Reboot
- self.ifThenSend("\r\n> ", "4")
+ first = True
+ for val in self.reboot_sequence:
+ if first:
+ self.ifThenSend("\r\n> ", val, ExceptionPassword)
+ first = False
+ else:
+ self.ifThenSend("\r\n> ", val)
if not dryrun:
self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
self.close()
return 0
-class APCBerlin(PCUControl):
- def run(self, node_port, dryrun):
- self.open(self.host, self.username)
- self.sendPassword(self.password)
-
- self.ifThenSend("\r\n> ", "1", ExceptionPassword)
- self.ifThenSend("\r\n> ", "2")
- self.ifThenSend("\r\n> ", "1")
- self.ifThenSend("\r\n> ", str(node_port))
- # 3- Immediate Reboot
- self.ifThenSend("\r\n> ", "3")
-
+ def run_http_or_https(self, node_port, dryrun):
if not dryrun:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "YES\r\n",
- ExceptionSequence)
- else:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "", ExceptionSequence)
- self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
+ # send reboot signal.
+ # TODO: send a ManualPCU() reboot request for this PCU.
+ # NOTE: this model defies automation because, the port numbering
+ # and the form numbers are not consistent across models. There is
+ # not direct mapping from port# to form#.
+ return "Manual Reboot Required"
- self.close()
- return 0
+ else:
+ # TODO: also send message for https, since that doesn't work this way...
+ if self.type == Transport.HTTPS:
+ cmd = self.get_https_cmd()
+ elif self.type == Transport.HTTP:
+ cmd = self.get_http_cmd()
+ else:
+ raise ExceptionNoTransport("Unsupported transport for http command")
-class APCFolsom(PCUControl):
- def run(self, node_port, dryrun):
- self.open(self.host, self.username)
- self.sendPassword(self.password)
+ cmd = cmd % ( self.username, self.password, self.host)
+ print "CMD: %s" % cmd
- self.ifThenSend("\r\n> ", "1", ExceptionPassword)
- self.ifThenSend("\r\n> ", "2")
- self.ifThenSend("\r\n> ", "1")
- self.ifThenSend("\r\n> ", str(node_port))
- self.ifThenSend("\r\n> ", "1")
+ p = os.popen(cmd)
+ result = p.read()
+ if len(result.split('\n')) > 2:
+ self.logout()
+ return 0
+ else:
+ # NOTE: an error has occurred, so no need to log out.
+ print "RESULT: ", result
+ return result
- # 3- Immediate Reboot
- self.ifThenSend("\r\n> ", "3")
+ def get_https_cmd(self):
+ version = self.get_version()
+ print "VERSION: %s" % version
+ if "AP96" in version:
+ cmd = "curl -s --insecure --user '%s:%s' https://%s/outlets.htm " + \
+ " | grep -E '^[^<]+' " + \
+ " | grep -v 'Protected Object' "
+ else:
+ # NOTE: no other case known right now...
+ cmd = "curl -s --insecure --user '%s:%s' https://%s/outlets.htm " + \
+ " | grep -E '^[^<]+' " + \
+ " | grep -v 'Protected Object' "
+
+ return cmd
+
+ def get_http_cmd(self):
+ version = self.get_version()
+ print "VERSION: %s" % version
+ if "AP7900" in version:
+ cmd = "curl -s --anyauth --user '%s:%s' http://%s/rPDUout.htm | grep -E '^[^<]+'"
+ elif "AP7920" in version:
+ cmd = "curl -s --anyauth --user '%s:%s' http://%s/ms3out.htm | grep -E '^[^<]+' "
+ else:
+ # default case...
+ print "USING DEFAULT"
+ cmd = "curl -s --anyauth --user '%s:%s' http://%s/ms3out.htm | grep -E '^[^<]+' "
+
+ return cmd
+
+ def get_version(self):
+ # NOTE: this command returns and formats all data.
+ #cmd = """curl -s --anyauth --user '%s:%s' http://%s/about.htm """ +
+ # """ | sed -e "s/<[^>]*>//g" -e "s/ //g" -e "/^$/d" """ +
+ # """ | awk '{line=$0 ; if ( ! /:/ && length(pline) > 0 ) \
+ # { print pline, line } else { pline=line} }' """ +
+ # """ | grep Model """
+
+ # NOTE: we may need to return software version, no model version to
+ # know which file to request on the server.
+
+ if self.type == Transport.HTTP:
+ cmd = """curl -s --anyauth --user '%s:%s' http://%s/about.htm """ + \
+ """ | sed -e "s/<[^>]*>//g" -e "s/ //g" -e "/^$/d" """ + \
+ """ | grep -E "AP[[:digit:]]+" """
+ #""" | grep -E "v[[:digit:]].*" """
+ elif self.type == Transport.HTTPS:
+ cmd = """curl -s --insecure --user '%s:%s' https://%s/about.htm """ + \
+ """ | sed -e "s/<[^>]*>//g" -e "s/ //g" -e "/^$/d" """ + \
+ """ | grep -E "AP[[:digit:]]+" """
+ #""" | grep -E "v[[:digit:]].*" """
+ else:
+ raise ExceptionNoTransport("Unsupported transport to get version")
- if not dryrun:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "YES\r\n",
- ExceptionSequence)
+ cmd = cmd % ( self.username, self.password, self.host)
+ p = os.popen(cmd)
+ result = p.read()
+ return result.strip()
+
+ def logout(self):
+ # NOTE: log out again, to allow other uses to access the machine.
+ if self.type == Transport.HTTP:
+ cmd = """curl -s --anyauth --user '%s:%s' http://%s/logout.htm """ + \
+ """ | grep -E '^[^<]+' """
+ elif self.type == Transport.HTTPS:
+ cmd = """curl -s --insecure --user '%s:%s' http://%s/logout.htm """ + \
+ """ | grep -E '^[^<]+' """
else:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "", ExceptionSequence)
- self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
+ raise ExceptionNoTransport("Unsupported transport to logout")
- self.close()
- return 0
+ cmd = cmd % ( self.username, self.password, self.host)
+ p = os.popen(cmd)
+ print p.read()
-class APCMaster(PCUControl):
- supported_ports = [22,23]
+class APCControl12p3(APCControl):
def run(self, node_port, dryrun):
- print "Rebooting %s" % self.host
- self.open(self.host, self.username)
- self.sendPassword(self.password)
+ self.reboot_sequence = ["1", "2", str(node_port), "3"]
+ return super(APCControl12p3, self).run(node_port, dryrun)
- # 1- Device Manager
- self.ifThenSend("\r\n> ", "1", ExceptionPassword)
- # 3- Outlet Control/Config
- self.ifThenSend("\r\n> ", "3")
- # n- Outlet n
- self.ifThenSend("\r\n> ", str(node_port))
- # 1- Control Outlet
- self.ifThenSend("\r\n> ", "1")
- # 3- Immediate Reboot
- self.ifThenSend("\r\n> ", "3")
-
- if not dryrun:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "YES\r\n",
- ExceptionSequence)
- else:
- self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel",
- "", ExceptionSequence)
- self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
- self.close()
- return 0
+class APCControl1p4(APCControl):
+ def run(self, node_port, dryrun):
+ self.reboot_sequence = ["1", str(node_port), "4"]
+ return super(APCControl1p4, self).run(node_port, dryrun)
-class APC(PCUControl):
- def __init__(self, plc_pcu_record, verbose):
- PCUControl.__init__(self, plc_pcu_record, verbose)
+class APCControl121p3(APCControl):
+ def run(self, node_port, dryrun):
+ self.reboot_sequence = ["1", "2", "1", str(node_port), "3"]
+ return super(APCControl121p3, self).run(node_port, dryrun)
- self.master = APCMaster(plc_pcu_record, verbose)
- self.folsom = APCFolsom(plc_pcu_record, verbose)
- self.europe = APCEurope(plc_pcu_record, verbose)
+class APCControl121p1(APCControl):
+ def run(self, node_port, dryrun):
+ self.reboot_sequence = ["1", "2", "1", str(node_port), "1", "3"]
+ return super(APCControl121p1, self).run(node_port, dryrun)
+class APCControl13p13(APCControl):
def run(self, node_port, dryrun):
- try_again = True
- sleep_time = 1
+ self.reboot_sequence = ["1", "3", str(node_port), "1", "3"]
+ return super(APCControl13p13, self).run(node_port, dryrun)
- for pcu in [self.master, self.europe, self.folsom]:
- if try_again:
- try:
- print "-*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"
- try_again = False
- print "sleeping 5"
- time.sleep(sleep_time)
- ret = pcu.reboot(node_port, dryrun)
- except ExceptionSequence, err:
- del pcu
- sleep_time = 130
- try_again = True
-
- if try_again:
- return "Unknown reboot sequence for APC PCU"
- else:
- return ret
class IntelAMT(PCUControl):
supported_ports = [16992]
print cmd_str
return cmd.system(cmd_str, self.TELNET_TIMEOUT)
-class DRACRacAdm(PCUControl):
+class DRAC(PCUControl):
def run(self, node_port, dryrun):
print "trying racadm_reboot..."
return 0
-class DRAC(PCUControl):
+class DRACDefault(PCUControl):
supported_ports = [22,443,5869]
def run(self, node_port, dryrun):
self.open(self.host, self.username)
class HPiLO(PCUControl):
supported_ports = [22,443]
def run(self, node_port, dryrun):
+ if self.type == Transport.SSH:
+ return self.run_ssh(node_port, dryrun)
+ elif self.type == Transport.HTTP or self.type == Transport.HTTPS:
+ return self.run_https(node_port, dryrun)
+ else:
+ raise ExceptionNoTransport("Unimplemented Transport for HPiLO %s" % self.type)
+
+ def run_ssh(self, node_port, dryrun):
+
self.open(self.host, self.username)
self.sendPassword(self.password)
self.close()
return 0
-
-class HPiLOHttps(PCUControl):
- supported_ports = [22,443]
- def run(self, node_port, dryrun):
+ def run_https(self, node_port, dryrun):
locfg = command.CMD()
return 0
-class BayTechAU(PCUControl):
+class BayTechRPC3NC(PCUControl):
def run(self, node_port, dryrun):
self.open(self.host, self.username, None, "Enter user name:")
self.sendPassword(self.password, "Enter Password:")
self.close()
return 0
-class BayTechGeorgeTown(PCUControl):
+class BayTechRPC16(PCUControl):
def run(self, node_port, dryrun):
self.open(self.host, self.username, None, "Enter user name:")
self.sendPassword(self.password, "Enter Password:")
if index == 0:
print "Reboot %d" % node_port
+ time.sleep(5)
s.send("Reboot %d\r\n" % node_port)
time.sleep(5)
self.close()
return 0
-class ePowerSwitchGood(PCUControl):
+class ePowerSwitchNew(PCUControl):
# NOTE:
# The old code used Python's HTTPPasswordMgrWithDefaultRealm()
# For some reason this both doesn't work and in some cases, actually
self.close()
return 0
-class ePowerSwitch(PCUControl):
+class ePowerSwitchOld(PCUControl):
supported_ports = [80]
def run(self, node_port, dryrun):
self.url = "http://%s:%d/" % (self.host,80)
pass
return 0
+class PM211MIP(ManualPCU):
+ supported_ports = [80,443]
+
### rebooting european BlackBox PSE boxes
# Thierry Parmentelat - May 11 2005
# tested on 4-ports models known as PSE505-FR
else:
return None
-#import database
-from monitor import database
-fb = None
def get_pcu_values(pcu_id):
- global fb
- if fb == None:
- # this shouldn't be loaded each time...
- fb = database.dbLoad("findbadpcus")
-
+ print "pcuid: %s" % pcu_id
try:
- values = fb['nodes']["id_%s" % pcu_id]['values']
+ pcurec = FindbadPCURecord.get_latest_by(plc_pcuid=pcu_id).first()
+ if pcurec:
+ values = pcurec.to_dict()
+ else:
+ values = None
except:
values = None
def reboot(nodename):
return reboot_policy(nodename, True, False)
+
+def reboot_str(nodename):
+ global verbose
+ continue_probe = True
+ dryrun=False
+
+ pcu = plc.getpcu(nodename)
+ if not pcu:
+ logger.debug("no pcu for %s" % nodename)
+ print "no pcu for %s" % nodename
+ return False # "%s has no pcu" % nodename
+
+ values = get_pcu_values(pcu['pcu_id'])
+ if values == None:
+ logger.debug("No values for pcu probe %s" % nodename)
+ print "No values for pcu probe %s" % nodename
+ return False #"no info for pcu_id %s" % pcu['pcu_id']
+
+ # Try the PCU first
+ logger.debug("Trying PCU %s %s" % (pcu['hostname'], pcu['model']))
+
+ ret = reboot_test_new(nodename, values, verbose, dryrun)
+ return ret
def reboot_policy(nodename, continue_probe, dryrun):
global verbose
pcu = plc.getpcu(nodename)
if not pcu:
- logger.debug("no pcu for %s" % hostname)
- print "no pcu for %s" % hostname
+ logger.debug("no pcu for %s" % nodename)
+ print "no pcu for %s" % nodename
return False # "%s has no pcu" % nodename
values = get_pcu_values(pcu['pcu_id'])
if values == None:
- logger.debug("No values for pcu probe %s" % hostname)
- print "No values for pcu probe %s" % hostname
+ logger.debug("No values for pcu probe %s" % nodename)
+ print "No values for pcu probe %s" % nodename
return False #"no info for pcu_id %s" % pcu['pcu_id']
# Try the PCU first
logger.debug("Trying PCU %s %s" % (pcu['hostname'], pcu['model']))
- ret = reboot_test(nodename, values, continue_probe, verbose, dryrun)
+ ret = reboot_test_new(nodename, values, verbose, dryrun)
if ret != 0:
print ret
def model_to_object(modelname):
if "AMT" in modelname:
return IntelAMT
- elif "DS4-RPC" in modelname:
+ elif "BayTech" in modelname:
return BayTech
- elif "ilo2" in modelname:
+ elif "HPiLO" in modelname:
return HPiLO
- elif "IP-41x" in modelname:
+ elif "IPAL" in modelname:
return IPAL
- elif "AP79xx" in modelname or "Masterswitch" in modelname:
- return APCMaster
+ elif "APC" in modelname:
+ return APCControl
elif "DRAC" in modelname:
return DRAC
elif "WTI" in modelname:
return WTIIPS4
elif "ePowerSwitch" in modelname:
- return ePowerSwitch
- elif "ipmi" in modelname:
+ return ePowerSwitchNew
+ elif "IPMI" in modelname:
return IPMI
- elif "bbsemaverick" in modelname:
+ elif "BlackBoxPSMaverick" in modelname:
return BlackBoxPSMaverick
+ elif "PM211MIP" in modelname:
+ return PM211MIP
+ elif "ManualPCU" in modelname:
+ return ManualPCU
else:
+ print "UNKNOWN model %s"%modelname
return Unknown
+def reboot_test_new(nodename, values, verbose, dryrun):
+ rb_ret = ""
+ if 'plc_pcu_stats' in values:
+ values.update(values['plc_pcu_stats'])
+
+ try:
+ modelname = values['model']
+ if modelname:
+ object = eval('%s(values, verbose, ["22", "23", "80", "443", "9100", "16992", "5869"])' % modelname)
+ rb_ret = object.reboot(values[nodename], dryrun)
+ else:
+ rb_ret = "Not_Run"
+ # TODO: how to handle the weird, georgetown pcus, the drac faults, and ilo faults
+ except ExceptionPort, err:
+ rb_ret = str(err)
+
+ return rb_ret
+
+
def reboot_test(nodename, values, continue_probe, verbose, dryrun):
rb_ret = ""
if 'plc_pcu_stats' in values:
# TODO: make a more robust version of APC
if values['pcu_id'] in [1102,1163,1055,1111,1231,1113,1127,1128,1148]:
- apc = APCEurope(values, verbose, ['22', '23'])
+ apc = APCControl12p3(values, verbose, ['22', '23'])
rb_ret = apc.reboot(values[nodename], dryrun)
elif values['pcu_id'] in [1110,86]:
- apc = APCBrazil(values, verbose, ['22', '23'])
+ apc = APCControl1p4(values, verbose, ['22', '23'])
rb_ret = apc.reboot(values[nodename], dryrun)
elif values['pcu_id'] in [1221,1225,1220,1192]:
- apc = APCBerlin(values, verbose, ['22', '23'])
+ apc = APCControl121p3(values, verbose, ['22', '23'])
rb_ret = apc.reboot(values[nodename], dryrun)
elif values['pcu_id'] in [1173,1240,47,1363,1405,1401,1372,1371]:
- apc = APCFolsom(values, verbose, ['22', '23'])
+ apc = APCControl121p1(values, verbose, ['22', '23'])
rb_ret = apc.reboot(values[nodename], dryrun)
else:
- apc = APCMaster(values, verbose, ['22', '23'])
+ apc = APCControl13p13(values, verbose, ['22', '23'])
rb_ret = apc.reboot(values[nodename], dryrun)
# BayTech DS4-RPC
rb_ret = baytech.reboot(values[nodename], dryrun)
elif values['pcu_id'] in [93]:
- baytech = BayTechAU(values, verbose, ['22', '23'])
+ baytech = BayTechRPC3NC(values, verbose, ['22', '23'])
rb_ret = baytech.reboot(values[nodename], dryrun)
elif values['pcu_id'] in [1057]:
# This pcu sometimes doesn't present the 'Username' prompt,
# unless you immediately try again...
try:
- baytech = BayTechGeorgeTown(values, verbose, ['22', '23'])
+ baytech = BayTechRPC16(values, verbose, ['22', '23'])
rb_ret = baytech.reboot(values[nodename], dryrun)
except:
- baytech = BayTechGeorgeTown(values, verbose, ['22', '23'])
+ baytech = BayTechRPC16(values, verbose, ['22', '23'])
rb_ret = baytech.reboot(values[nodename], dryrun)
else:
baytech = BayTech(values, verbose, ['22', '23'])
# DRAC ssh
elif continue_probe and values['model'].find("DRAC") >= 0:
- # TODO: I don't think DRACRacAdm will throw an exception for the
+ # TODO: I don't think DRAC will throw an exception for the
# default method to catch...
try:
- drac = DRACRacAdm(values, verbose, ['443', '5869'])
+ drac = DRAC(values, verbose, ['443', '5869'])
rb_ret = drac.reboot(0, dryrun)
except:
- drac = DRAC(values, verbose, ['22'])
+ drac = DRACDefault(values, verbose, ['22'])
rb_ret = drac.reboot(0, dryrun)
elif continue_probe and values['model'].find("WTI IPS-4") >= 0:
elif continue_probe and values['model'].find("ePowerSwitch") >=0:
# TODO: allow a different port than http 80.
if values['pcu_id'] in [1089, 1071, 1046, 1035, 1118]:
- eps = ePowerSwitchGood(values, verbose, ['80'])
+ eps = ePowerSwitchNew(values, verbose, ['80'])
elif values['pcu_id'] in [1003]:
# OLD EPOWER
print "OLD EPOWER"
- eps = ePowerSwitch(values, verbose, ['80'])
+ eps = ePowerSwitchOld(values, verbose, ['80'])
else:
- eps = ePowerSwitchGood(values, verbose, ['80'])
+ eps = ePowerSwitchNew(values, verbose, ['80'])
rb_ret = eps.reboot(values[nodename], dryrun)
elif continue_probe and values['pcu_id'] in [1122]:
rb_ret = "Unsupported_PCU"
elif continue_probe == False:
- if 'portstatus' in values:
+ if 'port_status' in values:
rb_ret = "NetDown"
else:
rb_ret = "Not_Run"
print err
if __name__ == '__main__':
- import plc
logger = logging.getLogger("monitor")
main()
from distutils.core import setup
packages=['monitor', 'monitor.database', 'monitor.database.zabbixapi',
- 'monitor.database.info', 'monitor.pcu', 'monitor.sources',
+ 'monitor.database.info', 'monitor.sources',
'monitor.util', 'monitor.wrapper' ]
print packages
import turbogears as tg
-from turbogears import controllers, expose, flash
+from turbogears import controllers, expose, flash, exception_handler
+from cherrypy import request, response
+import cherrypy
# from monitorweb import model
# import logging
# log = logging.getLogger("monitorweb.controllers")
from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
from monitor.wrapper.plccache import plcdb_lb2hn as site_lb2hn
+from monitorweb.templates.links import *
+
+import findbad
+
def format_ports(pcu):
retval = []
if pcu.port_status and len(pcu.port_status.keys()) > 0 :
query.append(node)
return dict(now=time.ctime(), query=query, fc=filtercount)
+
+ def nodeaction_handler(self, tg_exceptions=None):
+ """Handle any kind of error."""
+ refurl = request.headers.get("Referer",link("pcu"))
+ print refurl
+ # TODO: do this more intelligently...
+ if len(urllib.splitquery(refurl)) > 1:
+ pcuid = urllib.splitvalue(urllib.splitquery(refurl)[1])[1]
+ else:
+ pcuid=None
+
+ cherry_trail = cherrypy._cputil.get_object_trail()
+ for i in cherry_trail:
+ print "trail: ", i
+ print pcuid
+ return self.pcuview(pcuid, **dict(exceptions=tg_exceptions))
+ #return dict(pcuquery=[], nodequery=[], exceptions=tg_exceptions)
+
+ def nodeaction(self, **data):
+ for item in data.keys():
+ print "%s %s" % ( item, data[item] )
+
+ if 'hostname' in data:
+ hostname = data['hostname']
+ else:
+ flash("No hostname given in submitted data")
+ return
+
+ if 'submit' in data:
+ action = data['submit']
+ else:
+ flash("No submit action given in submitted data")
+ return
+
+ if action == "Reboot":
+ print "REBOOT: %s" % hostname
+ ret = reboot.reboot_str(str(hostname))
+ print ret
+ if ret: raise RuntimeError("Error using PCU: " + ret)
+
+ elif action == "ExternalProbe":
+ raise RuntimeError("THIS IS A PROBLEM")
+
+ elif action == "DeepProbe":
+ findbad.probe(str(hostname))
+ else:
+ # unknown action
+ flash("Unknown action given")
+ return
+
+ # TODO: add form validation
@expose(template="monitorweb.templates.pcuview")
- def pcuview(self, pcuid=None):
+ @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
+ def pcuview(self, pcuid=None, **data):
pcuquery=[]
+ nodequery=[]
+ if 'submit' in data.keys():
+ self.nodeaction(**data)
+ if 'exceptions' in data:
+ exceptions = data['exceptions']
+ else:
+ exceptions = None
+
if pcuid:
for pcu in FindbadPCURecord.get_latest_by(plc_pcuid=pcuid):
# NOTE: count filter
prep_pcu_for_display(pcu)
pcuquery += [pcu]
-
- return dict(pcuquery=pcuquery)
+ for nodename in pcu.plc_pcu_stats['nodenames']:
+ print "query for %s" % nodename
+ node = FindbadNodeRecord.get_latest_by(hostname=nodename).first()
+ print "%s" % node
+ if node:
+ prep_node_for_display(node)
+ nodequery += [node]
+ return dict(pcuquery=pcuquery, nodequery=nodequery, exceptions=exceptions)
@expose(template="monitorweb.templates.pculist")
def pcu(self, filter='all'):
font-size: 180%;\r
}\r
\r
+ pre.results {\r
+ margin: 0 auto 0 auto;\r
+} \r
+\r
a.link, a, a.active {\r
color: #369;\r
+ display: inline;\r
+ page-break-after: avoid;\r
+ page-break-before: avoid;\r
}\r
\r
+\r
/*@media screen {*/\r
a.ext-link .icon {\r
background: URL(../images/extlink.gif) left center no-repeat;\r
padding-left: 16px;\r
}\r
+\r
+a.info{\r
+ position:relative; /*this is the key*/\r
+ z-index:24;\r
+ color:#000;\r
+ }\r
+\r
+a.info:hover{z-index:25;}\r
+\r
+a.info span{display: none}\r
+\r
+a.info:hover span{ /*the span will display just on :hover state*/\r
+ display:block;\r
+ position:absolute;\r
+ top:2em; left:2em; width:15em;\r
+ border:1px solid #AAA;\r
+ color:#DDD;\r
+ background-color:black; \r
+ text-align: center}\r
+\r
+div#links a:hover span {display: block;\r
+ /*position: absolute; top: 200px; left: 0; width: 125px;*/\r
+ /*position: relative; top: 0px; left: 40; width: 30em;*/\r
+ float: left; width: 30em;\r
+ padding: 5px; margin: 5px; z-index: 100;\r
+ color: #AAA; background: black;\r
+ font: 10px Verdana, sans-serif; text-align: center;}\r
+\r
+\r
+div.oneline { clear : both; }\r
+a.left { float: left; }\r
+a.right { float: right; }\r
+\r
/** html a.ext-link .icon { display: inline-block; }*/\r
/*}*/\r
\r
\r
.code {\r
font-family: monospace;\r
+ width: 100%;\r
+ background: #eee;\r
}\r
\r
span.code {\r
- font-weight: bold;\r
- background: #eee;\r
+ font-size: 120%;\r
+ /*font-weight: bold;*/\r
+ margin: 20 20 20 20;\r
+ padding: 20 20 20 20;\r
}\r
\r
#status_block {\r
background: #eef URL('../images/info.png') left center no-repeat;\r
border: 1px solid #cce;\r
}\r
+.error {\r
+ margin: 0.5em auto 0.5em auto;\r
+ padding: 15px 10px 15px 55px;\r
+ width: 450px;\r
+ background: #e30 URL('../images/widgets.png') left center no-repeat;\r
+ border: 1px solid #c00;\r
+}\r
\r
.fielderror {\r
color: red;\r
from monitor import config
+import turbogears as tg
import urllib
def plc_node_uri(hostname):
tgpath += '?' + query_string
return tgpath
-def link(base, ext=True, **kwargs):
- if ext:
+def link(base, **kwargs):
+ if config.embedded:
str = "?query=" + base + query_to_path(**kwargs)
else:
str = tg.url(base, **kwargs)
layout_params['page_title'] = "Monitor Node List"
from monitor.util import diff_time
from time import mktime
+from links import *
?>
<html py:layout="'sitemenu.kid'"
xmlns:py="http://purl.org/kid/ns#"
<table width="100%">
<thead>
<tr>
- <th><a href="${tg.url('node', filter='BOOT')}">Production(${fc['BOOT']})</a></th>
- <th><a href="${tg.url('node', filter='DEBUG')}">Debug(${fc['DEBUG']})</a></th>
- <th><a href="${tg.url('node', filter='DOWN')}">Down(${fc['DOWN']})</a></th>
- <th><a href="${tg.url('node', filter='neverboot')}">Never Booted(${fc['neverboot']})</a></th>
- <th><a href="${tg.url('node', filter='pending')}">Pending Reply(${fc['pending']})</a></th>
- <th><a href="${tg.url('node', filter='all')}">All</a></th>
+ <th><a href="${link('node', filter='BOOT')}">Production(${fc['BOOT']})</a></th>
+ <th><a href="${link('node', filter='DEBUG')}">Debug(${fc['DEBUG']})</a></th>
+ <th><a href="${link('node', filter='DOWN')}">Down(${fc['DOWN']})</a></th>
+ <th><a href="${link('node', filter='neverboot')}">Never Booted(${fc['neverboot']})</a></th>
+ <th><a href="${link('node', filter='pending')}">Pending Reply(${fc['pending']})</a></th>
+ <th><a href="${link('node', filter='all')}">All</a></th>
</tr>
</thead>
<tbody>
<tbody>
<tr py:for="i,node in enumerate(query)" class="${i%2 and 'odd' or 'even'}" >
<td></td>
- <td><a href="siteview?loginbase=${node.loginbase}">${node.loginbase}</a></td>
- <td nowrap="true"><a href="nodeview?hostname=${node.hostname}" py:content="node.hostname"></a></td>
+ <td><a href="${link('siteview', loginbase=node.loginbase)}">${node.loginbase}</a></td>
+ <td nowrap="true"><a target="_top" href="${link('nodeview', hostname=node.hostname)}" py:content="node.hostname"></a></td>
<td py:content="node.ping_status"></td>
<td id="status-${node.pcu_short_status}" py:content="node.pcu_short_status"></td>
<td py:content="node.observed_status"></td>
<tbody>
<tr py:for="i,node in enumerate(nodequery)" class="${i%2 and 'odd' or 'even'}" >
<td></td>
- <td><a class="ext-link" href="${plc_site_link_id(node.plc_node_stats['site_id'])}">
+ <td><a class="ext-link" href="${plc_site_uri_id(node.plc_node_stats['site_id'])}">
<span class="icon">${node.loginbase}</span></a>
</td>
<td id="node-${node.observed_status}" nowrap="true" >
- <a class="ext-link" href="${plc_node_link(node.hostname)}">
+ <a class="ext-link" href="${plc_node_uri(node.hostname)}">
<span class="icon">${node.hostname}</span></a>
</td>
<td py:content="node.ping_status"></td>
<td py:if="node.pcu_short_status != 'none'" id="status-${node.pcu_short_status}">
- <a href="pcuview?pcuid=${node.plc_node_stats['pcu_ids']}">${node.pcu_short_status}</a></td>
+ <a href="${link('pcuview', pcuid=node.plc_node_stats['pcu_ids'])}">${node.pcu_short_status}</a></td>
<td py:if="node.pcu_short_status == 'none'" id="status-${node.pcu_short_status}">
${node.pcu_short_status}</td>
<td nowrap="true" py:content="node.kernel"></td>
<table id="sub-table" width="100%">
<thead>
<tr>
- <th><a href="${tg.url('pcu', filter='ok')}">Ok(${fc['ok']})</a></th>
- <th><a href="${tg.url('pcu', filter='Not_Run')}">Misconfigured(${fc['Not_Run']})</a></th>
- <th><a href="${tg.url('pcu', filter='NetDown')}">Offline(${fc['NetDown']})</a></th>
- <th><a href="${tg.url('pcu', filter='pending')}">Runtime Error(${fc['pending']})</a></th>
- <th><a href="${tg.url('pcu', filter='all')}">All</a></th>
+ <th><a href="${link('pcu', filter='ok')}">Ok(${fc['ok']})</a></th>
+ <th><a href="${link('pcu', filter='Not_Run')}">Misconfigured(${fc['Not_Run']})</a></th>
+ <th><a href="${link('pcu', filter='NetDown')}">Offline(${fc['NetDown']})</a></th>
+ <th><a href="${link('pcu', filter='pending')}">Runtime Error(${fc['pending']})</a></th>
+ <th><a href="${link('pcu', filter='all')}">All</a></th>
</tr>
</thead>
<tbody>
<th>PCU Name</th>
<th>Missing Fields</th>
<th>DNS Status</th>
- <th>Port Status</th>
- <th width="80%">Test Results</th>
+ <th nowrap='true' >Port Status</th>
+ <th nowrap='true' width="80%">Test Results</th>
<th>Model</th>
<th>Nodes</th>
</tr>
<tbody>
<tr py:for="i,node in enumerate(query)" class="${i%2 and 'odd' or 'even'}" >
<td></td>
- <td><a href="${plc_site_link_id(node.plc_pcu_stats['site_id'])}">${node.loginbase}</a></td>
- <td nowrap="true" >
- <a href="${plc_pcu_link_id(node.plc_pcu_stats['pcu_id'])}">${pcu_name(node.plc_pcu_stats)}</a></td>
+ <td><a href="${link('siteview', loginbase=node.loginbase)}">${node.loginbase}</a></td>
+ <td nowrap='true'>
+ <div class='oneline'>
+ <a class='left' href="${link('pcuview', pcuid=node.plc_pcuid)}">${pcu_name(node.plc_pcu_stats)}</a>
+ <a class='right' href="${plc_pcu_uri_id(node.plc_pcu_stats['pcu_id'])}">
+ <img style='display: inline' border='0' src="static/images/extlink.gif" align='right'/></a>
+ </div>
+ </td>
<td py:content="node.entry_complete"></td>
<td id="dns-${node.dns_status}" py:content="node.dns_status"></td>
<td>
<span py:for="port,state in node.ports"
id="port${state}" py:content="'%s, ' % port">80</span>
</td>
- <td width="40" id="status-${node.status}" py:content="node.reboot_trial_status"></td>
+ <td width="20%" nowrap='true' align='center' id="status-${node.status}">
+ <div id="links">
+ <a class="info" py:if="'error' in node.status"
+ href="${link('pcuview', pcuid=node.plc_pcuid)}">
+ Error Message<span><pre>${node.reboot_trial_status}</pre></span></a>
+ <a py:if="'error' not in node.status"
+ href="${link('pcuview', pcuid=node.plc_pcuid)}"
+ py:content="node.status">Reboot Status</a>
+ </div>
+ </td>
<td py:content="node.plc_pcu_stats['model']"></td>
<td py:content="len(node.plc_pcu_stats['node_ids'])"></td>
</tr>
layout_params['page_title'] = "Monitor PCU View"
from monitor.util import diff_time
from monitor import config
+from time import mktime
from pcucontrol.reboot import pcu_name, model_to_object
from links import *
?>
</tr>
</thead>
<tbody>
- <tr py:for="i,node in enumerate(pcuquery)" class="${i%2 and 'odd' or 'even'}" >
+ <tr py:for="i,pcu in enumerate(pcuquery)" class="${i%2 and 'odd' or 'even'}" >
<td></td>
- <td><a class="ext-link" href="${plc_site_link_id(node.plc_pcu_stats['site_id'])}">
- <span class="icon">${node.loginbase}</span>
+ <td><a class="ext-link" href="${plc_site_uri_id(pcu.plc_pcu_stats['site_id'])}">
+ <span class="icon">${pcu.loginbase}</span>
</a>
</td>
<td nowrap="true" >
- <a class="ext-link" href="${plc_pcu_link_id(node.plc_pcu_stats['pcu_id'])}">
- <span class="icon">${pcu_name(node.plc_pcu_stats)}</span>
+ <a class="ext-link" href="${plc_pcu_uri_id(pcu.plc_pcu_stats['pcu_id'])}">
+ <span class="icon">${pcu_name(pcu.plc_pcu_stats)}</span>
</a>
</td>
- <td py:content="node.entry_complete"></td>
- <td id="dns-${node.dns_status}" py:content="node.dns_status"></td>
+ <td py:content="pcu.entry_complete"></td>
+ <td id="dns-${pcu.dns_status}" py:content="pcu.dns_status"></td>
<td>
- <span py:for="port,state in node.ports"
+ <span py:for="port,state in pcu.ports"
id="port${state}" py:content="'%s, ' % port">80</span>
</td>
- <td width="40" id="status-${node.status}" py:content="node.reboot_trial_status"></td>
- <td py:content="node.plc_pcu_stats['model']"></td>
- <td py:content="len(node.plc_pcu_stats['node_ids'])"></td>
+ <td width="40" id="status-${pcu.status}"><pre py:content="pcu.reboot_trial_status"></pre></td>
+ <td py:content="pcu.plc_pcu_stats['model']"></td>
+ <td py:content="len(pcu.plc_pcu_stats['node_ids'])"></td>
</tr>
</tbody>
</table>
+ <h4>Convenience Calls</h4>
+ <?python
+ if len(pcuquery) == 0: pcu = None
+ ?>
+ <div py:if="pcu is not None" class="code">
+ <span py:for="port,state in pcu.ports">
+ <span class="code" py:if="port == 22 and state == 'open'">
+ ssh -o PasswordAuthentication=yes -o PubkeyAuthentication=no
+ ${pcu.plc_pcu_stats['username']}@${pcu_name(pcu.plc_pcu_stats)}
+ </span>
+ <span class="code" py:if="port == 23 and state == 'open'">
+ telnet ${pcu_name(pcu.plc_pcu_stats)}
+ </span>
+ <span class="code" py:if="port == 80 and state == 'open'">
+ <a href="http://${pcu_name(pcu.plc_pcu_stats)}">http://${pcu_name(pcu.plc_pcu_stats)}</a>
+ </span>
+ <span class="code" py:if="port == 443 and state == 'open'">
+ <a href="https://${pcu_name(pcu.plc_pcu_stats)}">https://${pcu_name(pcu.plc_pcu_stats)}</a>
+ <br/>
+ /usr/share/monitor/racadm.py -r ${pcu.plc_pcu_stats['ip']}
+ -u ${pcu.plc_pcu_stats['username']} -p '${pcu.plc_pcu_stats['password']}'
+ <br/>
+ /usr/share/monitor/pcucontrol/models/hpilo/locfg.pl
+ -f /usr/share/monitor/pcucontrol/models/hpilo/iloxml/Reset_Server.xml
+ -s ${pcu_name(pcu.plc_pcu_stats)}
+ -u ${pcu.plc_pcu_stats['username']}
+ -p '${pcu.plc_pcu_stats['password']} ' | grep MESSAGE"
+ </span>
+ <span class="code" py:if="port == 16992 and state == 'open'">
+ /usr/share/monitor/pcucontrol/models/intelamt/remoteControl -A
+ -verbose 'http://${pcu_name(pcu.plc_pcu_stats)}:16992/RemoteControlService'
+ -user admin -pass '${pcu.plc_pcu_stats['password']}'
+ </span>
+ </span>
+ </div>
<h3>Controls</h3>
- ... node list ...
- <br/>
- form for reboot
-
+ <table id="sortable_table" class="datagrid" border="1" width="100%">
+ <thead>
+ <tr>
+ <th mochi:format="int"></th>
+ <th>Hostname</th>
+ <th>last_contact</th>
+ <th>Last_checked</th>
+ <th>External Probe</th>
+ <th>Internal Probe</th>
+ <th>Reboot</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr py:for="i,node in enumerate(nodequery)" class="${i%2 and 'odd' or 'even'}" >
+ <td></td>
+ <td id="node-${node.observed_status}" nowrap="true" >
+ <a class="ext-link" href="${plc_node_uri(node.hostname)}">
+ <span class="icon">${node.hostname}</span></a>
+ </td>
+ <td py:content="diff_time(node.plc_node_stats['last_contact'])"></td>
+ <td py:content="diff_time(mktime(node.date_checked.timetuple()))"></td>
+ <td>
+ <!-- TODO: add some values/code to authenticate the operation. -->
+ <form action="${link('pcuview', pcuid=pcu.plc_pcuid)}" name="nodeaction" method='post'>
+ <input type='hidden' name='hostname' value='${node.hostname}'/>
+ <input type='submit' name='submit' value='ExternalProbe' />
+ </form>
+ </td>
+ <td>
+ <!-- TODO: add some values/code to authenticate the operation. -->
+ <form action="${link('pcuview', pcuid=pcu.plc_pcuid)}" name="nodeaction" method='post'>
+ <input type='hidden' name='hostname' value='${node.hostname}'/>
+ <input type='submit' name='submit' value='DeepProbe' />
+ </form>
+ </td>
+ <td>
+ <!-- TODO: add some values/code to authenticate the operation. -->
+ <form action="${link('pcuview', pcuid=pcu.plc_pcuid)}" name="nodeaction" method='post'>
+ <input type='hidden' name='hostname' value='${node.hostname}'/>
+ <input type='submit' name='submit' value='Reboot' />
+ </form>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="error" py:if="exceptions is not None">
+ ${exceptions}
+ </div>
+ <div id="status_block" class="flash"
+ py:if="value_of('tg_flash', None)" py:content="tg_flash"></div>
<h3>Legend</h3>
<table border="1" align="center" width="80%">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<?python
layout_params['page_title'] = "Monitor Site List"
+from links import *
?>
<html py:layout="'sitemenu.kid'"
xmlns:py="http://purl.org/kid/ns#"
<table width="100%">
<thead>
<tr>
- <th><a href="${tg.url('site', filter='good')}">Compliant(${fc['good']})</a></th>
- <th><a href="${tg.url('site', filter='down')}">Down(${fc['down']})</a></th>
- <th><a href="${tg.url('site', filter='new')}">New Sites(${fc['new']})</a></th>
- <th><a href="${tg.url('site', filter='pending')}">Disabled(${fc['pending']})</a></th>
- <th><a href="${tg.url('site', filter='all')}">All(${fc['all']})</a></th>
+ <th><a href="${link('site', filter='good')}">Compliant(${fc['good']})</a></th>
+ <th><a href="${link('site', filter='down')}">Down(${fc['down']})</a></th>
+ <th><a href="${link('site', filter='new')}">New Sites(${fc['new']})</a></th>
+ <th><a href="${link('site', filter='pending')}">Disabled(${fc['pending']})</a></th>
+ <th><a href="${link('site', filter='all')}">All(${fc['all']})</a></th>
</tr>
</thead>
<tbody>
<tbody>
<tr py:for="i,site in enumerate(query)" class="${i%2 and 'odd' or 'even'}" >
<td></td>
- <td nowrap="true"><a href="siteview?loginbase=${site.loginbase}">${site.loginbase}</a></td>
+ <td nowrap="true"><a href="${link('siteview', loginbase=site.loginbase)}">${site.loginbase}</a></td>
<td id="site-${site.status}" py:content="site.last_changed"></td>
<td>${site.slices_used}/${site.slices_total}</td>
<td>${site.nodes_up} / ${site.nodes_total}</td>
<script type="text/javascript" src="tg_js/MochiKit.js"></script>
<script type="text/javascript" src="static/javascript/sortable_tables.js"></script>
+ <!-- If in an iframe, then include this... -->
+ <?python from monitor import config ?>
+ <base py:if="config.embedded" target="_top" href="https://${config.MONITOR_HOST}/db/monitor/" />
+
</head>
<body>
<table id="nps-table" width="100%">
<thead>
<tr>
- <th><a href="${tg.url('site')}">Sites</a></th>
- <th><a href="${tg.url('pcu')}">PCUs</a></th>
- <th><a href="${tg.url('node')}">Nodes</a></th>
- <th><a href="${tg.url('action')}">Actions</a></th>
+ <?python from monitorweb.templates.links import link ?>
+ <th><a href="${link('site')}">Sites</a></th>
+ <th><a href="${link('pcu')}">PCUs</a></th>
+ <th><a href="${link('node')}">Nodes</a></th>
+ <th><a href="${link('action')}">Actions</a></th>
</tr>
</thead>
<tbody>
</thead>
<tbody>
<tr py:for="i,site in enumerate(sitequery)" class="${i%2 and 'odd' or 'even'}" >
- <td nowrap="true"><a class="ext-link" href="${plc_site_link(site.loginbase)}">
+ <td nowrap="true"><a class="ext-link" href="${plc_site_uri(site.loginbase)}">
<span class="icon">${site.loginbase}</span></a>
</td>
<td id="site-${site.status}" py:content="site.last_changed"></td>
<tbody>
<tr py:for="i,node in enumerate(nodequery)" class="${i%2 and 'odd' or 'even'}" >
<td></td>
- <td id="node-${node.observed_status}" nowrap="true"><a href="nodeview?hostname=${node.hostname}" py:content="node.hostname">your.host.org</a></td>
+ <td id="node-${node.observed_status}" nowrap="true">
+ <a href="${link('nodeview', hostname=node.hostname)}" py:content="node.hostname">your.host.org</a></td>
<td py:content="node.ping_status"></td>
<td py:if="node.pcu_short_status != 'none'" id="status-${node.pcu_short_status}">
- <a href="pcuview?pcuid=${node.plc_node_stats['pcu_ids']}">${node.pcu_short_status}</a></td>
+ <a href="${link('pcuview', pcuid=node.plc_node_stats['pcu_ids'])}">${node.pcu_short_status}</a></td>
<td py:if="node.pcu_short_status == 'none'" id="status-${node.pcu_short_status}">
${node.pcu_short_status}</td>
<td nowrap="true" py:content="node.kernel"></td>
'debug' : 3,
'boot' : 4,
}
- #print "--%s--" % line
- #print "--%s--" % type(line)
if line.strip() == "" or line.strip() == "Timeout":
return mapping["down"]
(p22, p80, p806) = line.split()
else:
return mapping["unknown"]
-print get_state_from_port(sys.argv[1])
+if __name__ == "__main__":
+ print get_state_from_port(sys.argv[1])