updated documentation for Monitor API calls.
authorStephen Soltesz <soltesz@cs.princeton.edu>
Mon, 4 May 2009 23:02:54 +0000 (23:02 +0000)
committerStephen Soltesz <soltesz@cs.princeton.edu>
Mon, 4 May 2009 23:02:54 +0000 (23:02 +0000)
docs/Monitor.xml.in
web/MonitorWeb/monitorweb/monitor_xmlrpc.py

index dd38353..cb29420 100644 (file)
 
 <book>
   <bookinfo>
-    <title>PlanetLab Node Manager API Documentation</title>
+    <title>PlanetLab Administrative-Monitor API Documentation</title>
   </bookinfo>
 
   <chapter id="Introduction">
     <title>Introduction</title>
 
-    <para>The PlanetLab Node Manager API (NMAPI) is the interface through
+    <para>The PlanetLab Administrative-Monitor API (Admin-Mon) is the interface through
     which the slices access the Node API.</para>
 
     <section id="Authentication">
       <title>Authentication</title>
 
-         <para>Authentication for NM operations is based on the identity of the
-         connecting slice.  For slices whose roles are defined as
-         'nm-controller', the target slice must be listed delegated and as
-         controlled by the calling slice.</para>
+         <para>Authentication for operations is based on the identity of the
+         connecting user. The standard PLCAPI authetication is used here.</para>
 
-   </section>
-   <section id="Delegation">
-      <title>Delegation</title>
-         <para> None </para>
    </section>
     <section id="Connection">
       <title>Connection</title>
 
-         <para>The NM XMLRPC server listens locally on every PlanetLab node at http://localhost:812.</para>
-         <para>The NM XMLRPC server can be accessed remotely using an SSH connection through the nm-controller account.  Rather than a standard shell, a special command is run that forwards all standard input to the local XMLRPC server, essentially XML-RPC over ssh.</para>
+         <para>The Admin-Mon XMLRPC server listens at http://monitor.planet-lab.org:8082.</para>
+         <para>The XMLRPC server can be accessed remotely using a standard Python XMLRPC shell.</para>
    </section>
     <section id="Example">
-      <title>An Example using the PLC and NM API</title>
+      <title>An Example using the PLC and Admin-Mon API</title>
+
+       <para>Access to the API is via standard XMLRPC.  A simple example is below.</para>
 
-         <para>The nm-controller slice is given a stub account such that it can
-         be accessed over ssh.  So rather than logging into NM server listens
-         locally on every PlanetLab node at http://localhost:812.
-         
-         </para>
       <programlisting>
-controller_slice_fields = {'name'      : 'princeton_mycontroller',
-                           'instantiation' : 'nm-controller',
-                           'url'           : 'http://www.yourhost.com', 
-                           'description'   : 'a brief description of this slice.', }
-controller_slice_id = api.AddSlices(plauth, controller_slice_fields)
+import xmlrpclib
+auth = {'Username'   : API_AUTH_USER,
+        'AuthMethod' : 'password',
+        'AuthString' : API_AUTH_PASSWORD}
+api  =  xmlrpclib.Server(API_SERVER, verbose=False, allow_none=True)
+
+if api.upAndRunning():
+    for i in api.getSiteStatus(auth):
+       print i
       </programlisting>
 
-       <para>After this, the controller owner, should both add users and nodes to
-       this slice.  As well, the controller slice is created using the standard
-       PlanetLab and NM mechanism.  So, wait at least 15 minutes before attempting 
-       to access the controller slice on any node.</para>
-
-       <para> Subsequently, slices that will be delegated to this controller will
-       be registered at PLC.  An example follows.
-       </para>
-
-       <programlisting>
-delegated_slice_fields = {'name'        : 'anothersite_mydelegated',
-                        'instantiation' : 'delegated',
-                        'url'           : 'http://www.yourhost.com', 
-                        'description'   : 'a brief description of this slice.', }
-delegated_slice_id = api.AddSlices(plauth, delegated_slice_fields)
-
-# Get ticket for this slice.
-ticket = api.GetSliceTicket(plauth, "princetondsl_solteszdelegated")
-       </programlisting>
-
-       <para>After the slice is registered with PLC, and your application has the
-       Ticket, the last step is to redeem the ticket by presenting it to the NM
-       through the nm-controller account.  The following code formats the message
-       correctly.</para>
-
-       <programlisting>
-# generate an XMLRPC request.
-print xmlrpclib.dumps((ticket,), 'Ticket')
-       </programlisting>
-
-       <para>Finally, this message must be sent to the NM using the controller
-       account.  It should be possible to create a program that creates the ssh
-       connection or to use a library that does this automatically such as: 
-       <ulink url="http://cheeseshop.python.org/pypi/pyXMLRPCssh/1.0-0">pyXMLRPCssh</ulink>
-       </para>
-
-       <para>
-       Or, you could use something much simpler.  Assuming the output from
-       <literal>dumps()</literal> above, is saved to a file called
-       <literal>ticket.txt</literal>, you could run a command like:
-       </para>
-
-       <programlisting>
-cat ticket.txt | ssh princeton_mycontroller@mynode.someuniversity.edu
-       </programlisting>
-       <para>
-       Alternately,
-       </para>
-       <programlisting>
-p = subprocess.Popen(['/usr/bin/ssh', 'princeton_mycontroller@mynode.someuniversity.edu'], 
-                                       stdin=subprocess.PIPE, stdout=subprocess.PIPE)
-print >>p.stdin, xmlrpclib.dumps((ticket,), 'Ticket')
-p.stdin.close()
-print xmlrpclib.loads(p.stdout.read())
-p.wait() 
-       </programlisting>
-       <para>
-       The following is a stub to use as you would use the current
-       xmlrpclib.Server() object, but redirects the connection of SSH.
-       </para>
-       <programlisting>
-"""XML-RPC over SSH.
-
-       To use, create an XmlRpcOverSsh object like so:
-               >>> api = XmlRpcOverSsh('princeton_deisenst@planetlab-1.cs.princeton.edu')
-       and call methods as with the normal xmlrpclib.ServerProxy interface.
-"""
-
-from subprocess import PIPE, Popen
-from xmlrpclib import Fault, dumps, loads
-
-__all__ = ['XmlRpcOverSsh']
-
-
-class XmlRpcOverSsh:
-    def __init__(self, userAtHost):
-        self.userAtHost = userAtHost
-
-    def __getattr__(self, method):
-        return _Method(self.userAtHost, method)
-
-
-class _Method:
-    def __init__(self, userAtHost, method):
-        self.userAtHost = userAtHost
-        self.method = method
-
-    def __call__(self, *args):
-        p = Popen(['ssh', self.userAtHost], stdin=PIPE, stdout=PIPE)
-        stdout, stderr = p.communicate(dumps(args, self.method))
-        if stderr:
-            raise Fault(1, stderr)
-        else:
-            return loads(stdout)
-       </programlisting>
-
    </section>
 
   </chapter>
index ce1f26c..45f5c01 100644 (file)
@@ -121,15 +121,22 @@ class MonitorXmlrpcServer(object):
        @cherrypy.expose
        @export_to_docbook(roles=['tech', 'user', 'pi', 'admin'],
                           accepts=[],
-                                          returns=Parameter(bool, 'True is successful'))
+                                          returns=Parameter(bool, 'True if successful'))
        def upAndRunning(self):
-               """ This is a test """
+               """ This call can indicate to a script whether the server is up
+               and running before trying any more sophisticated operations. """
                return True
 
        # SITES ------------------------------------------------------------
 
        @cherrypy.expose
+       @export_to_docbook(roles=['tech', 'user', 'pi', 'admin'],
+                          accepts=[Parameter(dict, "Auth struct")],
+                                          returns=Parameter(list, 'array of SiteStatus records'))
        def getSiteStatus(self, auth):
+               """ This call returns a list that includes the status and observations 
+               of all sites, including those blacklisted.  At this time, there is no
+               indication which sites are blacklisted from this list. """
                ret_list = []
                sites = HistorySiteRecord.query.all()
                for q in sites:
@@ -139,7 +146,12 @@ class MonitorXmlrpcServer(object):
                return ret_list
 
        @cherrypy.expose
+       @export_to_docbook(roles=['admin'],
+                          accepts=[Parameter(dict, "Auth struct")],
+                                          returns=Parameter(bool, 'True on success.'))
        def clearSitePenalty(self, auth, loginbase):
+               """ Rather than waiting for monitor to run automatically, this call
+                       will manually clear a site's penalties. """
                sitehist = SiteInterface.get_or_make(loginbase=loginbase)
                sitehist.clearPenalty()
                #sitehist.applyPenalty()
@@ -148,7 +160,12 @@ class MonitorXmlrpcServer(object):
                return True
 
        @cherrypy.expose
+       @export_to_docbook(roles=['admin'],
+                          accepts=[Parameter(dict, "Auth struct")],
+                                          returns=Parameter(bool, 'True on success.'))
        def increaseSitePenalty(self, auth, loginbase):
+               """ Rather than waiting for monitor to run automatically, this call
+                       will manually increase a site's penalties."""
                sitehist = SiteInterface.get_or_make(loginbase=loginbase)
                sitehist.increasePenalty()
                #sitehist.applyPenalty()
@@ -158,7 +175,13 @@ class MonitorXmlrpcServer(object):
        # NODES ------------------------------------------------------------
 
        @cherrypy.expose
+       @export_to_docbook(roles=['tech', 'user', 'pi', 'admin'],
+                          accepts=[Parameter(dict, "Auth struct")],
+                                          returns=Parameter(list, 'array of NodeStatus records.'))
        def getNodeStatus(self, auth):
+               """ This call returns a list of all nodes, including those
+                       blacklisted.  The current observation and recorded status of each node
+                       is returned."""
                ret_list = []
                sites = HistoryNodeRecord.query.all()
                for q in sites:
@@ -168,14 +191,28 @@ class MonitorXmlrpcServer(object):
                return ret_list
 
        @cherrypy.expose
+       @export_to_docbook(roles=['tech', 'user', 'pi', 'admin'],
+                          accepts=[Parameter(dict, "Auth struct")],
+                                          returns=Parameter(bool, 'True on success.'))
        def getRecentActions(self, auth, loginbase=None, hostname=None):
+               """ Monitor takes various actions on sites (such as applying
+                       penalties) and nodes (such as repairing a node installation via
+                       BootManager).  As well, it makes a log of every email message sent
+                       out, or believed to be sent.  This call returns a list of all actions,
+                       filtered on site or for a specific node. """
                ret_list = []
                return ret_list
 
        # BLACKLIST ------------------------------------------------------------
 
        @cherrypy.expose
+       @export_to_docbook(roles=['tech', 'user', 'pi', 'admin'],
+                          accepts=[Parameter(dict, "Auth struct")],
+                                          returns=Parameter(bool, 'True on success.'))
        def getBlacklist(self, auth):
+               """ Return a list of all nodes and sites that are excluded from
+               penalties.  Currently there is no way to exclude a node or site 
+               from being monitored. """
                bl = BlacklistRecord.query.all()
                ret_list = []
                for q in bl:
@@ -184,20 +221,37 @@ class MonitorXmlrpcServer(object):
                        ret_list.append(d)
 
                return ret_list
-               # datetime.datetime.fromtimestamp(time.mktime(time.strptime(mytime, time_format)))
        
        @cherrypy.expose
+       @export_to_docbook(roles=['admin'],
+                          accepts=[Parameter(dict, "Auth struct"), 
+                                                               Parameter(str, "hostname"), 
+                                                               Parameter(int, "expires number of seconds from time.now()")],
+                                          returns=Parameter(bool, 'True on success.'))
        def addHostToBlacklist(self, auth, hostname, expires=0):
+               """ Add a host to the blacklist, with an optional expiration time"""
                bl = BlacklistRecord.findby_or_create(hostname=hostname, expires=expires)
                return True
 
        @cherrypy.expose
+       @export_to_docbook(roles=['admin'],
+                          accepts=[Parameter(dict, "Auth struct"),
+                                                               Parameter(str, "loginbase"), 
+                                                               Parameter(int, "expires number of seconds from time.now()")],
+                                          returns=Parameter(bool, 'True on success.'))
        def addSiteToBlacklist(self, auth, loginbase, expires=0):
+               """ Add a site to the blacklist, with an optional expiration time"""
                bl = BlacklistRecord.findby_or_create(hostname=hostname, expires=expires)
                return True
 
        @cherrypy.expose
+       @export_to_docbook(roles=['admin'],
+                          accepts=[Parameter(dict, "Auth struct"),
+                                                               Parameter(str, "loginbase"), 
+                                                               Parameter(str, "hostname"),],
+                                          returns=Parameter(bool, 'True on success.'))
        def deleteFromBlacklist(self, auth, loginbase=None, hostname=None):
+               """ Remove a host or site from the blacklist """
                if (loginbase==None and hostname == None) or (loginbase != None and hostname != None):
                        raise Exception("Please specify a single record to delete: either hostname or loginbase")
                elif loginbase != None: