######################################## PCU Control
%package pcucontrol
-Summary: PCU Controls for Monitor and PLCAPI
-Group: Applications/System
-Requires: python
+summary: pcu controls for monitor and plcapi
+group: applications/system
+requires: python
%description pcucontrol
-Both Monitor and the PLCAPI use a set of common commands to reboot machines
-using their external or internal PCUs. This package is a library of several
+both monitor and the plcapi use a set of common commands to reboot machines
+using their external or internal pcus. this package is a library of several
supported models.
+####################################### RunlevelAgent
+%package runlevelagent
+summary: the RunlevelAgent that reports node runlevels
+group: applications/system
+requires: python
+
+%description runlevelagent
+The RunlevelAgent starts as early as possible during boot-up and production
+mode to actively report the observed runlevel to PLC and update the
+'last_contact' field.
+
%prep
%setup -q
#install -D -m 755 monitor-default.conf $RPM_BUILD_ROOT/etc/monitor.conf
#cp $RPM_BUILD_ROOT/usr/share/%{name}/monitorconfig-default.py $RPM_BUILD_ROOT/usr/share/%{name}/monitorconfig.py
+#################### RunlevelAgent
+install -D -m 755 RunlevelAgent.py $RPM_BUILD_ROOT/usr/bin/RunlevelAgent.py
+install -D -m 755 monitor-runlevelagent.init $RPM_BUILD_ROOT/%{_initrddir}/monitor-runlevelagent
+
+
%clean
rm -rf $RPM_BUILD_ROOT
%files pcucontrol
%{python_sitearch}/pcucontrol
+%files runlevelagent
+/usr/bin/RunlevelAgent.py
+/%{_initrddir}/monitor-runlevelagent
+
%post server
# TODO: this will be nice when we have a web-based service running., such as
# an API server or so on.
chkconfig --add monitor
chkconfig monitor on
+%post runlevelagent
+chkconfig --add monitor-runlevelagent
+chkconfig monitor-runlevelagent on
+
%changelog
* Mon Jan 05 2009 Stephen Soltesz <soltesz@cs.princeton.edu> - Monitor-2.0-0
- new changes are significantly different, that I'm upping the number for clarity.
--- /dev/null
+#!/usr/bin/python
+
+import xml, xmlrpclib
+import logging
+import time
+import traceback
+import sys
+import os
+import string
+
+CONFIG_FILE="/tmp/source/configuration"
+SESSION_FILE="/etc/planetlab/session"
+
+def read_config_file(filename):
+ ## NOTE: text copied from BootManager.py
+ # TODO: unify this code to make it common. i.e. use ConfigParser module
+ vars = {}
+ vars_file= file(filename,'r')
+ validConfFile = True
+ for line in vars_file:
+ # if its a comment or a whitespace line, ignore
+ if line[:1] == "#" or string.strip(line) == "":
+ continue
+
+ parts= string.split(line,"=")
+ if len(parts) != 2:
+ print "Invalid line in vars file: %s" % line
+ validConfFile = False
+ break
+
+ name= string.strip(parts[0])
+ value= string.strip(parts[1])
+ vars[name]= value
+
+ vars_file.close()
+ if not validConfFile:
+ print "Unable to read configuration vars."
+
+ return vars
+
+try:
+ sys.path = ['/etc/planetlab'] + sys.path
+ import plc_config
+ api_server_url = "https://" + plc_config.PLC_API_HOST + plc_config.PLC_API_PATH
+except:
+ filename=CONFIG_FILE
+ vars = read_config_file(filename)
+ api_server_url = vars['BOOT_API_SERVER']
+
+
+class Auth:
+ def __init__(self, username=None, password=None, **kwargs):
+ if 'session' in kwargs:
+ self.auth= { 'AuthMethod' : 'session',
+ 'session' : kwargs['session'] }
+ else:
+ if username==None and password==None:
+ self.auth = {'AuthMethod': "anonymous"}
+ else:
+ self.auth = {'Username' : username,
+ 'AuthMethod' : 'password',
+ 'AuthString' : password}
+class PLC:
+ def __init__(self, auth, url):
+ self.auth = auth
+ self.url = url
+ self.api = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
+
+ def __getattr__(self, name):
+ method = getattr(self.api, name)
+ if method is None:
+ raise AssertionError("method does not exist")
+
+ return lambda *params : method(self.auth.auth, *params)
+
+ def __repr__(self):
+ return self.api.__repr__()
+
+def main():
+
+ f=open(SESSION_FILE,'r')
+ session_str=f.read().strip()
+ api = PLC(Auth(session=session_str), api_server_url)
+ # NOTE: should we rely on bootmanager for this functionality?
+ api.AuthCheck()
+
+ while True:
+ print "reporting status: ", os.popen("uptime").read().strip()
+ try:
+ # NOTE: alternately, check other stuff in the environment to infer
+ # run_level
+ # is BootManager running?
+ # what is the boot_state at PLC?
+ # does /vservers exist?
+ # what about /tmp/source?
+ # is BootManager in /tmp/source?
+ # is /tmp/mnt/sysimg mounted?
+ # how long have we been running? if we were in safeboot and
+ # still running, we're likely in failboot now.
+ # length of runtime increases the certainty of inferred state.
+ #
+ api.ReportRunlevel({'run_level' : 'safeboot'})
+ except:
+ traceback.print_exc()
+ time.sleep(30)
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/bin/bash
+#
+# monitor-runlevelagent starts the RunlevelAgent in production mode.
+#
+# Load before nm, vcached, and vservers, vserver-reference
+# chkconfig: 3 14 85
+# description: Start RunlevelAgent to report the current Runlevel to PLC at
+# periodic intervals.
+#
+# Stephen Soltesz <soltesz@cs.princeton.edu>
+# Copyright (C) 2008 The Trustees of Princeton University
+#
+# $Id$
+#
+
+case "$1" in
+ start|restart|reload)
+ ;;
+ stop|status)
+ exit 0
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
+
+# NOTE: If user already exists, this just exists with status 9. I think it's
+# ok to simply let this command check and error out.
+# Parse PLC configuration
+if [ -r /etc/planetlab/plc_config ] ; then
+ . /etc/planetlab/plc_config
+else
+ PLC_NAME="PlanetLab"
+ PLC_SLICE_PREFIX="pl"
+ PLC_BOOT_HOST="boot.planet-lab.org"
+fi
+
+USER="${PLC_SLICE_PREFIX}_monitor"
+/usr/sbin/useradd -p "" -m $USER &> /dev/null || :
+
+if [ ! -d /home/$USER/.ssh ] ; then
+ mkdir /home/$USER/.ssh
+ chmod 700 /home/$USER/.ssh
+ chown $USER.$USER /home/$USER/.ssh
+fi
+
+URL="http://${PLC_BOOT_HOST}/PlanetLabConf/keys.php?$USER"
+curl -s "$URL" > /home/$USER/.ssh/authorized_keys
+chown $USER.$USER /home/$USER/.ssh/authorized_keys