Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

updates and refactoring

  • Loading branch information...
commit 3b102a39ba3a6ea0da78a9951556fa5795962e40 1 parent baf763b
Andre Charbonneau AndreCharbonneau authored
14 Makefile
View
@@ -0,0 +1,14 @@
+RPI_WEB_WSGI=/usr/local/rpi_web/wsgi
+
+clean:
+ find . -name "*~" | xargs rm -f
+ rm -rf doc/_build
+
+deploy:
+ mkdir -p $(RPI_WEB_WSGI)
+ cp -r wsgi/* $(RPI_WEB_WSGI)
+
+deploy-remote:
+ ssh root@$(RPI_WEB_HOST) "mkdir -p $(RPI_WEB_WSGI)"
+ rsync -avz -e ssh --delete --exclude '.git' --exclude '.rope*' --exclude '*~' --delete-excluded wsgi/ root@$(RPI_WEB_HOST):$(RPI_WEB_WSGI)
+ ssh root@$(RPI_WEB_HOST) "service httpd reload"
27 wsgi/rpi-web.py → wsgi/rpi_web.py
View
@@ -9,27 +9,23 @@
import logging
from cherrypy import _cperror
+from services.cloudscheduler import CloudSchedulerService
+
logger = None
# CherryPy configuration.
# This can be put in a config file. We will do that later...
conf = {}
-conf['global'] = {'environment': 'embedded', 'log.error_file':'/tmp/rpi-web-wsgi-error.log', 'log.access_file':'/tmp/rpi-web-wsgi-access.log', 'tools.sessions.name':'1'}
+conf['global'] = {'environment': 'embedded', 'log.error_file':'/tmp/rpi_web_wsgi_error.log', 'log.access_file':'/tmp/rpi_web_wsgi_access.log', 'tools.sessions.name':'1'}
-# The root CherryPy handler.
-# It does nothing more than act as a parent
-# for all handlers.
-class Root():
- def test(self):
- return 'Test OK'
try:
- root = Root()
-
+ cloudSchedulerService = CloudSchedulerService()
+
logging.debug('Creating request dispatching routes...')
d = cherrypy.dispatch.RoutesDispatcher()
@@ -38,7 +34,12 @@ def test(self):
conf['/'] = {'request.dispatch': d}
- d.connect('test', '/test', controller = root, action = 'test')
+
+ # URL Routes go here:
+ d.connect('cloud-scheduler-info', '/service/info', controller = cloudSchedulerService, action = 'info')
+
+
+
def application(environ, start_response):
#
@@ -50,14 +51,14 @@ def application(environ, start_response):
if not logger:
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
- h = logging.FileHandler('/tmp/rpi-web-wsgi.log')
+ h = logging.FileHandler('/tmp/rpi_web_wsgi.log')
h.setFormatter(logging.Formatter('%(asctime)s %(thread)d : %(message)s'))
logger.addHandler(h)
logging.debug('Log handler added to root logger.')
cherrypy.tree.mount(None, script_name='/wsgi/', config=conf)
return cherrypy.tree(environ, start_response)
- logging.info('rpi-web WSGI app started')
+ logging.info('rpi_web WSGI app started')
except Exception as e:
- logging.exception('Error in rpi-web WSGI app.')
+ logging.exception('Error in rpi_web WSGI app.')
0  wsgi/services/__init__.py
View
No changes.
223 wsgi/services/base.py
View
@@ -0,0 +1,223 @@
+import cherrypy
+import datetime
+import json
+import logging
+
+class RpiService():
+ """
+ An abstract base class for all services.
+ """
+
+ def info(self):
+ """
+ Return basic identification and provenance information about
+ the service. CANARIE's monitoring service will poll this URI
+ periodically.
+
+ When an HTTP GET is performed on this URI, and the Accept
+ header specifies json (ie. application/json) please return the
+ following:
+
+ {
+ "name" : "<name of service>",
+ "synopsis": "<one or two sentences describing what the service is for>",
+ "version" : "<service version identifier>",
+ "institution": "<the name of the institution responsible for the service>",
+ "releaseTime": <time at which this version of the service was published>"
+ }
+
+ where:
+ The value of "version" will be taken as a string and can
+ follow any versioning scheme you deem appropriate.
+
+ The value of "releaseTime" is in the format ddd mmm dd yyyy
+ HH:MM:ss (example Sat Jun 09 2007 17:46:21). Please express in
+ UTC rather than local time.
+
+ If an HTTP GET is performed and the Accept header does not
+ indicate json, or there is no Accept header, please return an
+ HTML page providing the information listed above in
+ human-readable format.
+ """
+ acceptHeader = cherrypy.lib.cptools.accept()
+ logging.debug('Accept header: %s' % (acceptHeader))
+
+ d = {}
+ d['name'] = self.getName()
+ d['synopsis'] = self.getSynopsis()
+ d['version'] = self.getVersion()
+ d['institution'] = self.getInstitution()
+ # TODO: Convert datetime to UTC
+ d['releaseTime'] = self.getReleaseTime().strftime('%a %b %d %Y %H:%M:%S')
+
+ if acceptHeader == 'application/json':
+ return json.dumps(d)
+ else:
+ return """<html><pre>%s</pre></html>""" % (d)
+
+
+ def stats(self):
+ """
+ Return information about the usage of your RPI. CANARIE's
+ monitoring service will poll this URI periodically. If a
+ request to this URI fails or times out, the monitoring service
+ will flag your RPI as unavailable. With this in mind, please
+ endeavor to architect your RPI such that that requests to this
+ URI will fail if the rest of the service is not available.
+
+ When an HTTP Get is performed on this URI, and the Accept
+ header specifies json (ie. application/json) please return the
+ following:
+
+ {
+ "invocations" : "<number of times service has been used since last reset>",
+ "lastReset": "<the time and date at which invocations was last reset to zero>",
+ }
+
+ where:
+ The value of "invocations" is a positive integer. This value
+ should start at zero when the service is first published and
+ should be incremented every time the service's API (excluding
+ anything under <base>/service) is accessed. The value of
+ "lastReset" is in the format ddd mmm dd yyyy HH:MM:ss (example
+ Sat Jun 09 2007 17:46:21). Please express in UTC rather than
+ local time. If you reset your invocations value to zero or it
+ wraps around, please update this value accordingly.
+ """
+ acceptHeader = cherrypy.lib.cptools.accept()
+ d = {}
+ d['invocations'] = self.getInvocations()
+ d['lastReset'] = self.getLastReset()
+
+ if acceptHeader == 'application/json':
+ return json.dumps(d)
+ else:
+ return """<html><pre>%s</pre></html>""" % (d)
+
+
+ def doc(self):
+ """
+ Make the online documentation for your service available.
+
+ When an HTTP GET is performed, return the user documentation
+ for your service in a human-readable format. This information
+ should include:
+
+ A detailed description of the service and what it does
+
+ A complete description of the API
+
+ Sample code illustrating API usage, as appropriate
+
+ If the documentation is hosted elsewhere, returning an HTTP
+ redirect in response to this request is acceptable.
+ """
+ return self.getDoc()
+
+
+ def releasenotes(self):
+ """
+ Return release notes describing the current version of your
+ service.
+
+ When an HTTP GET is performed, return the release notes for
+ the current version of your service. These notes should
+ identify changes made from previous versions as well as any
+ know issues with work-arounds (where applicable). If the
+ release notes are hosted elsewhere, please return an HTTP
+ redirect in response to this request.
+ """
+ return self.getReleaseNotes()
+
+
+ def support(self):
+ """
+ Provide users with information on how to get support for your
+ RPI.
+
+ When an HTTP GET is performed, return instructions for users
+ on how to get support for your service, in human-readable
+ format. Include help desk contact info, a link to any bug
+ tracking systems and/or forums, etc.
+ """
+ return self.getSupport()
+
+
+ def source(self):
+ """
+ When an HTTP GET is performed, return link(s) to the source
+ code for you service. This is only applicable if you are
+ making your source code publicly available. If the source code
+ is hosted elsewhere, please return and HTTP redirect in
+ response to this request. If you are not providing access to
+ your service's source code, please return status code 204 (No
+ Content).
+ """
+ return self.getSource()
+
+
+ def tryme(self):
+ """
+ Allow users to try out your RPI online.
+
+ This URI returns a page that allows the user to try your
+ service, possibly with fixed input. Consider displaying the
+ text of the HTTP request and response for reference
+ purposes. If you are not providing this capability, please
+ return status code 204 (No Content).
+ """
+ return self.getTryMe()
+
+
+
+
+
+
+
+
+ # The following abastract methods needs to be implemented in
+ # each RPI service subclasses.
+ # These are defined in the "RPI API Enhancements for CANARIE
+ # Service Registry and Monitoring System" document.
+
+ def getName(self):
+ raise NotImplementedError()
+
+ def getSynopsis(self):
+ raise NotImplementedError()
+
+ def getVersion(self):
+ raise NotImplementedError()
+
+ def getInstitution(self):
+ raise NotImplementedError()
+
+ def getReleaseTime(self):
+ """
+ Must return a datetime.datetime object.
+ """
+ raise NotImplementedError()
+
+ def getInvocations(self):
+ raise NotImplementedError()
+
+ def getLastReset(self):
+ raise NotImplementedError()
+
+ def getDoc(self):
+ raise NotImplementedError()
+
+ def getReleaseNotes(self):
+ raise NotImplementedError()
+
+ def getSupport(self):
+ raise NotImplementedError()
+
+ def getSource(self):
+ raise NotImplementedError()
+
+ def getTryMe(self):
+ raise NotImplementedError()
+
+
+
35 wsgi/services/cloudscheduler.py
View
@@ -0,0 +1,35 @@
+from base import RpiService
+import datetime
+
+class CloudSchedulerService(RpiService):
+ def getName(self):
+ return 'CloudScheduler'
+
+ def getSynopsis(self):
+ return 'A service to schedule work between clouds.'
+
+ def getVersion(self):
+ return '0.1'
+
+ def getInstitution(self):
+ return 'UVIC HEP Group'
+
+ def getReleaseTime(self):
+ """
+ Must return a datetime.datetime object.
+ """
+ return datetime.datetime.now()
+
+ def getInvocations(self):
+ raise NotImplementedError()
+
+ def getLastReset(self):
+ raise NotImplementedError()
+
+ def getDoc(self):
+ return 'This is the service documentation page.'
+
+ def getReleaseNotes(self):
+ return 'These are the release notes.'
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.